Browse Source

Merge pull request #3 from jl777/dev

dev update
pass-iguana-arg
ca333 7 years ago
committed by GitHub
parent
commit
24bb43b18f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      .gitignore
  2. 19
      OSlibs/win/mingw.h
  3. 11
      crypto777/OS_portable.h
  4. 6
      crypto777/OS_time.c
  5. 87
      crypto777/bitcoind_RPC.c
  6. 132
      crypto777/cJSON.c
  7. 12
      crypto777/iguana_OS.c
  8. 6
      crypto777/iguana_utils.c
  9. 2
      iguana/coins/basilisk/mshark
  10. 2
      iguana/coins/chips_7776
  11. 2
      iguana/coins/genshark
  12. 2
      iguana/coins/mshark_7776
  13. 2
      iguana/coins/shark_7776
  14. 16
      iguana/dexscripts.win32/1-client.cmd
  15. 7
      iguana/dexscripts.win32/2-getuserpass.cmd
  16. 4
      iguana/dexscripts.win32/balance.cmd
  17. 7
      iguana/dexscripts.win32/bot_buy.cmd
  18. 7
      iguana/dexscripts.win32/bot_list.cmd
  19. 7
      iguana/dexscripts.win32/bot_statuslist.cmd
  20. 7
      iguana/dexscripts.win32/bot_stop.cmd
  21. BIN
      iguana/dexscripts.win32/curl.exe
  22. 9
      iguana/dexscripts.win32/electrum.cmd
  23. 4
      iguana/dexscripts.win32/enable.cmd
  24. 4
      iguana/dexscripts.win32/getcoin.cmd
  25. 4
      iguana/dexscripts.win32/getutxos.cmd
  26. 2
      iguana/dexscripts.win32/help.cmd
  27. 100
      iguana/dexscripts.win32/how_to_use.md
  28. BIN
      iguana/dexscripts.win32/images/conemu_jq.png
  29. BIN
      iguana/dexscripts.win32/images/userpass.png
  30. BIN
      iguana/dexscripts.win32/images/userpass_usage.png
  31. 4
      iguana/dexscripts.win32/inventory.cmd
  32. 4
      iguana/dexscripts.win32/listunspent.cmd
  33. 4
      iguana/dexscripts.win32/orderbook.cmd
  34. 1
      iguana/dexscripts.win32/passphrase
  35. 4
      iguana/dexscripts.win32/portfolio.cmd
  36. 5
      iguana/dexscripts.win32/sendrawtransaction.cmd
  37. 5
      iguana/dexscripts.win32/snapshot.cmd
  38. 0
      iguana/dexscripts.win32/userpass
  39. 8
      iguana/dexscripts.win32/withdraw.cmd
  40. 14
      iguana/dexscripts.win32/withdraw_10_send.cmd
  41. 14
      iguana/dexscripts.win32/withdraw_send.cmd
  42. 2
      iguana/dpow/dpow_network.c
  43. 2
      iguana/dpow/dpow_rpc.c
  44. 0
      iguana/exchanges/DB/PRICES/.tmpmarker
  45. 6
      iguana/exchanges/DEXstats.h
  46. 342
      iguana/exchanges/LP_NXT.c
  47. 86
      iguana/exchanges/LP_RTmetrics.c
  48. 248
      iguana/exchanges/LP_bitcoin.c
  49. 350
      iguana/exchanges/LP_cache.c
  50. 136
      iguana/exchanges/LP_coins.c
  51. 420
      iguana/exchanges/LP_commands.c
  52. 283
      iguana/exchanges/LP_include.h
  53. 650
      iguana/exchanges/LP_instantdex.c
  54. 928
      iguana/exchanges/LP_nativeDEX.c
  55. 149
      iguana/exchanges/LP_network.c
  56. 1403
      iguana/exchanges/LP_ordermatch.c
  57. 156
      iguana/exchanges/LP_peers.c
  58. 299
      iguana/exchanges/LP_portfolio.c
  59. 489
      iguana/exchanges/LP_prices.c
  60. 337
      iguana/exchanges/LP_privkey.c
  61. 375
      iguana/exchanges/LP_remember.c
  62. 632
      iguana/exchanges/LP_rpc.c
  63. 21
      iguana/exchanges/LP_scan.c
  64. 235
      iguana/exchanges/LP_signatures.c
  65. 400
      iguana/exchanges/LP_socket.c
  66. 1978
      iguana/exchanges/LP_statemachine.c
  67. 644
      iguana/exchanges/LP_stats.c
  68. 342
      iguana/exchanges/LP_swap.c
  69. 694
      iguana/exchanges/LP_tradebots.c
  70. 1133
      iguana/exchanges/LP_transaction.c
  71. 729
      iguana/exchanges/LP_utxo.c
  72. 808
      iguana/exchanges/LP_utxos.c
  73. 9
      iguana/exchanges/Makefile
  74. 2
      iguana/exchanges/auto_chipsbtc
  75. 2
      iguana/exchanges/auto_chipskmd
  76. 3
      iguana/exchanges/balances
  77. 14
      iguana/exchanges/barterDEX.c
  78. 3
      iguana/exchanges/bot_buy
  79. 3
      iguana/exchanges/bot_list
  80. 3
      iguana/exchanges/bot_pause
  81. 3
      iguana/exchanges/bot_resume
  82. 3
      iguana/exchanges/bot_sell
  83. 3
      iguana/exchanges/bot_settings
  84. 3
      iguana/exchanges/bot_status
  85. 3
      iguana/exchanges/bot_statuslist
  86. 3
      iguana/exchanges/bot_stop
  87. 4
      iguana/exchanges/bots
  88. 3
      iguana/exchanges/claim
  89. 2
      iguana/exchanges/coins
  90. 6
      iguana/exchanges/coins.json
  91. 3
      iguana/exchanges/deposit1
  92. 3
      iguana/exchanges/deposit10
  93. 4
      iguana/exchanges/dex
  94. 3
      iguana/exchanges/dynamictrust
  95. 14
      iguana/exchanges/enable
  96. 4
      iguana/exchanges/fundvalue
  97. 4
      iguana/exchanges/hodl
  98. 2
      iguana/exchanges/install
  99. 4
      iguana/exchanges/invreset
  100. 4
      iguana/exchanges/jumblr

4
.gitignore

@ -489,3 +489,7 @@ iguana/DB/PRICES/.tmpmarker
iguana/DB/KMD/0/.tmpmarker
*.swp
iguana/myipaddr
iguana/DB/UNSPENTS/.tmpmarker

19
OSlibs/win/mingw.h

@ -61,13 +61,18 @@
* @remarks - #if (defined(_M_X64) || defined(__amd64__)) && defined(WIN32)
* is equivalent to #if defined(_M_X64) as _M_X64 is defined for MSVC only
*/
#if !defined(_M_X64)
struct pollfd {
SOCKET fd; /* file descriptor */
short events; /* requested events */
short revents; /* returned events */
};
#endif
// [Decker] pollfs is already defined in winsock2.h
//#if !defined(_M_X64)
//struct pollfd {
//SOCKET fd; /* file descriptor */
//short events; /* requested events */
//short revents; /* returned events */
//};
//#endif
#if defined(_M_X64)
/*

11
crypto777/OS_portable.h

@ -143,6 +143,15 @@ typedef struct queue
char name[64],initflag;
} queue_t;
struct rpcrequest_info
{
struct rpcrequest_info *next,*prev;
pthread_t T;
int32_t sock;
uint32_t ipbits;
uint16_t port,pad;
};
struct OS_mappedptr
{
char fname[512];
@ -267,6 +276,7 @@ void *queue_delete(queue_t *queue,struct queueitem *copy,int32_t copysize,int32_
void *queue_free(queue_t *queue);
void *queue_clone(queue_t *clone,queue_t *queue,int32_t size);
int32_t queue_size(queue_t *queue);
char *mbstr(char *str,double n);
void iguana_memreset(struct OS_memspace *mem);
void iguana_mempurge(struct OS_memspace *mem);
@ -316,6 +326,7 @@ int32_t btc_convaddr(char *hexaddr,char *addr58);
uint64_t RS_decode(char *rs);
int32_t RS_encode(char *rsaddr,uint64_t id);
char *cmc_ticker(char *base);
void calc_sha1(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len);
void calc_md2(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len);

6
crypto777/OS_time.c

@ -21,7 +21,7 @@
#define TAI_PACK 8
#define TAI_UTC_DIFF ((uint64_t)4611686018427387914ULL)
//#define UTC_ADJUST -36
//#define UTC_ADJUST -37
#define tai_approx(t) ((double) ((t)->x))
#define tai_less(t,u) ((t)->x < (u)->x)
@ -300,7 +300,7 @@ void tai_add(struct tai *t,struct tai *u,struct tai *v) { t->x = u->x + v->x; }
void tai_sub(struct tai *t,struct tai *u,struct tai *v) { t->x = u->x - v->x; }
// {"leapseconds":["+1972-06-30", "+1972-12-31", "+1973-12-31", "+1974-12-31", "+1975-12-31", "+1976-12-31", "+1977-12-31", "+1982-06-30", "+1983-06-30", "+1985-06-30", "+1987-12-31", "+1989-12-31", "+1990-12-31", "+1992-06-30", "+1993-06-30", "+1994-06-30", "+1995-12-31", "+1997-06-30", "+1998-12-31", "+2005-12-31", "+2008-12-31", "+2012-06-30", "+2015-06-30"]}
char *leapseconds[] = { "+1972-06-30", "+1972-12-31", "+1973-12-31", "+1974-12-31", "+1975-12-31", "+1976-12-31", "+1977-12-31", "+1982-06-30", "+1983-06-30", "+1985-06-30", "+1987-12-31", "+1989-12-31", "+1990-12-31", "+1992-06-30", "+1993-06-30", "+1994-06-30", "+1995-12-31", "+1997-06-30", "+1998-12-31", "+2005-12-31", "+2008-12-31", "+2012-06-30", "+2015-06-30" };
char *leapseconds[] = { "+1972-06-30", "+1972-12-31", "+1973-12-31", "+1974-12-31", "+1975-12-31", "+1976-12-31", "+1977-12-31", "+1982-06-30", "+1983-06-30", "+1985-06-30", "+1987-12-31", "+1989-12-31", "+1990-12-31", "+1992-06-30", "+1993-06-30", "+1994-06-30", "+1995-12-31", "+1997-06-30", "+1998-12-31", "+2005-12-31", "+2008-12-31", "+2012-06-30", "+2015-06-30", "+2016-12-31" };
struct tai leaptais[sizeof(leapseconds)/sizeof(*leapseconds)];
char *dayname[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" } ;
@ -355,7 +355,7 @@ struct tai tai_now()
{
First_TAI = t, First_utc = (uint32_t)now;
#ifndef DISABLE_LEAPS
UTC_ADJUST = -36;
UTC_ADJUST = -37;
#endif
//printf("TAINOW.%llu %03.3f UTC.%u vs %u [diff %d]\n",(long long)t.x,t.millis,First_utc,tai2utc(t),UTC_ADJUST);
}

87
crypto777/bitcoind_RPC.c

@ -13,10 +13,24 @@
* *
******************************************************************************/
#ifndef FROM_JS
#include "OS_portable.h"
#define LIQUIDITY_PROVIDER 1
/*#define malloc(n) LP_alloc(n)
#define realloc(ptr,n) LP_realloc(ptr,n)
#define calloc(a,b) LP_alloc((uint64_t)(a) * (b))
#define free(ptr) LP_free(ptr)
#define clonestr(str) LP_clonestr(str)
void *LP_realloc(void *ptr,uint64_t len);
void *LP_alloc(uint64_t len);
void LP_free(void *ptr);
char *LP_clonestr(char *str);*/
#if LIQUIDITY_PROVIDER
#include <curl/curl.h>
#include <curl/easy.h>
@ -31,8 +45,11 @@ struct return_string {
size_t len;
};
struct MemoryStruct { char *memory; size_t size,allocsize; };
size_t accumulate(void *ptr, size_t size, size_t nmemb, struct return_string *s);
void init_string(struct return_string *s);
static size_t WriteMemoryCallback(void *ptr,size_t size,size_t nmemb,void *data);
/************************************************************************
@ -55,7 +72,9 @@ 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);
#ifdef FROM_MARKETMAKER
//usleep(3000);
#endif
//printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr);
if ( command == 0 || rpcstr == 0 || rpcstr[0] == 0 )
{
@ -76,7 +95,8 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *
{
if ( (error->type&0xff) == cJSON_NULL && (result->type&0xff) != cJSON_NULL )
{
retstr = cJSON_Print(result);
retstr = jprint(result,0);
//printf("%s %s rpc retstr.%p\n",command,params,retstr);
len = strlen(retstr);
if ( retstr[0] == '"' && retstr[len-1] == '"' )
{
@ -93,7 +113,10 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *
rpcstr = 0;
}
if ( rpcstr != 0 )
{
//printf("free rpcstr.%p\n",rpcstr);
free(rpcstr);
}
} else retstr = rpcstr;
free_json(json);
//fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: postprocess returns.(%s)\n",retstr);
@ -120,8 +143,9 @@ char *Jay_NXTrequest(char *command,char *params)
char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params,int32_t timeout)
{
static int didinit,count,count2; static double elapsedsum,elapsedsum2; extern int32_t USE_JAY;
struct MemoryStruct chunk;
struct curl_slist *headers = NULL; struct return_string s; CURLcode res; CURL *curl_handle;
char *bracket0,*bracket1,*databuf = 0; long len; int32_t specialcase,numretries; double starttime;
char *bracket0,*bracket1,*retstr,*databuf = 0; long len; int32_t specialcase,numretries; double starttime;
if ( didinit == 0 )
{
didinit = 1;
@ -145,14 +169,24 @@ try_again:
*retstrp = 0;
starttime = OS_milliseconds();
curl_handle = curl_easy_init();
init_string(&s);
headers = curl_slist_append(0,"Expect:");
curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )");
curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl_handle,CURLOPT_URL, url);
curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION, (void *)accumulate); // send all data to this function
curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback
if ( (0) )
{
init_string(&s);
curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION, (void *)accumulate); // send all data to this function
curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback
}
else
{
memset(&chunk,0,sizeof(chunk));
curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION,WriteMemoryCallback);
curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA,(void *)&chunk);
}
curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash
curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback
if ( timeout > 0 )
@ -201,23 +235,24 @@ try_again:
free(databuf);
databuf = 0;
}
retstr = chunk.memory; // retstr = s.ptr;
if ( res != CURLE_OK )
{
numretries++;
if ( specialcase != 0 || timeout != 0 )
{
//printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res);
free(s.ptr);
//printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,retstr,res);
free(retstr);
return(0);
}
else if ( numretries >= 4 )
{
printf( "curl_easy_perform() failed: %s %s.(%s %s), retries: %d\n",curl_easy_strerror(res),debugstr,url,command,numretries);
//printf("Maximum number of retries exceeded!\n");
free(s.ptr);
free(retstr);
return(0);
}
free(s.ptr);
free(retstr);
sleep((1<<numretries));
goto try_again;
@ -232,25 +267,22 @@ try_again:
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 )
{
*retstrp = s.ptr;
return(s.ptr);
*retstrp = retstr;
return(retstr);
}
return(post_process_bitcoind_RPC(debugstr,command,s.ptr,params));
return(post_process_bitcoind_RPC(debugstr,command,retstr,params));
}
else
{
if ( (0) && specialcase != 0 )
fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: BTCD.(%s) -> (%s)\n",params,s.ptr);
fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: BTCD.(%s) -> (%s)\n",params,retstr);
count2++;
elapsedsum2 += (OS_milliseconds() - starttime);
if ( (count2 % 10000) == 0)
printf("%d: ave %9.6f | elapsed %.3f millis | NXT calls.(%s) cmd.(%s)\n",count2,elapsedsum2/count2,(double)(OS_milliseconds() - starttime),url,command);
return(s.ptr);
return(retstr);
}
}
//printf("bitcoind_RPC: impossible case\n");
//free(s.ptr);
//return(0);
}
/************************************************************************
@ -292,13 +324,24 @@ size_t accumulate(void *ptr,size_t size,size_t nmemb,struct return_string *s)
return(size * nmemb);
}
struct MemoryStruct { char *memory; size_t size; };
static size_t WriteMemoryCallback(void *ptr,size_t size,size_t nmemb,void *data)
{
size_t realsize = (size * nmemb);
size_t needed,realsize = (size * nmemb);
struct MemoryStruct *mem = (struct MemoryStruct *)data;
mem->memory = (ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1);
needed = mem->size + realsize + 1;
if ( ptr == 0 && needed < 256 )
{
mem->allocsize = 256;
mem->memory = malloc(mem->allocsize);
}
if ( mem->allocsize < needed )
{
//printf("curl needs %d more\n",(int32_t)realsize);
mem->memory = (ptr != 0) ? realloc(mem->memory,needed) : malloc(needed);
//printf("mem->memory.%p len.%d\n",mem->memory,(int32_t)needed);
mem->allocsize = needed;
}
//mem->memory = (ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1);
if ( mem->memory != 0 )
{
if ( ptr != 0 )

132
crypto777/cJSON.c

@ -54,8 +54,43 @@ static int32_t cJSON_strcasecmp(const char *s1,const char *s2)
return tolower((int32_t)(*(const unsigned char *)s1)) - tolower((int32_t)(*(const unsigned char *)s2));
}
static void *(*cJSON_malloc)(size_t sz) = malloc;
static void (*cJSON_free)(void *ptr) = free;
void *LP_alloc(uint64_t len);
void LP_free(void *ptr);
static void *(*cJSON_malloc)(size_t sz) = (void *)malloc;//LP_alloc;
static void (*cJSON_free)(void *ptr) = free;//LP_free;
static void *cJSON_mallocstr(int32_t len)
{
return(cJSON_malloc(len));
}
static char **cJSON_mallocptrs(int32_t num,char **space,int32_t max)
{
if ( num < max )
return(space);
else return(cJSON_malloc(num * sizeof(char *)));
}
static void *cJSON_mallocnode()
{
return(cJSON_malloc(sizeof(cJSON)));
}
static void cJSON_freeptrs(char **ptrs,int32_t num,char **space)
{
if ( ptrs != space )
cJSON_free(ptrs);
}
static void cJSON_freestr(char *str)
{
cJSON_free(str);
}
static void cJSON_freenode(cJSON *item)
{
cJSON_free(item);
}
static char* cJSON_strdup(const char* str)
{
@ -63,7 +98,7 @@ static char* cJSON_strdup(const char* str)
char* copy;
len = strlen(str) + 1;
if (!(copy = (char*)cJSON_malloc(len+1))) return 0;
if (!(copy = (char*)cJSON_mallocstr((int32_t)len+1))) return 0;
memcpy(copy,str,len);
return copy;
}
@ -76,14 +111,14 @@ void cJSON_InitHooks(cJSON_Hooks* hooks)
return;
}
cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
}
/* Internal constructor. */
static cJSON *cJSON_New_Item(void)
{
cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
cJSON* node = (cJSON*)cJSON_mallocnode();
if (node) memset(node,0,sizeof(cJSON));
return node;
}
@ -96,9 +131,9 @@ void cJSON_Delete(cJSON *c)
{
next=c->next;
if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
if (c->string) cJSON_free(c->string);
cJSON_free(c);
if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_freestr(c->valuestring);
if (c->string) cJSON_freestr(c->string);
cJSON_freenode(c);
c=next;
}
}
@ -132,13 +167,13 @@ static char *print_number(cJSON *item)
double d = item->valuedouble;
if ( fabs(((double)item->valueint) - d) <= DBL_EPSILON && d >= (1. - DBL_EPSILON) && d < (1LL << 62) )//d <= INT_MAX && d >= INT_MIN )
{
str = (char *)cJSON_malloc(24); /* 2^64+1 can be represented in 21 chars + sign. */
str = (char *)cJSON_mallocstr(24); /* 2^64+1 can be represented in 21 chars + sign. */
if ( str != 0 )
sprintf(str,"%lld",(long long)item->valueint);
}
else
{
str = (char *)cJSON_malloc(66); /* This is a nice tradeoff. */
str = (char *)cJSON_mallocstr(66); /* This is a nice tradeoff. */
if ( str != 0 )
{
if ( fabs(floor(d) - d) <= DBL_EPSILON && fabs(d) < 1.0e60 )
@ -173,7 +208,7 @@ static const char *parse_string(cJSON *item,const char *str)
while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; // Skip escaped quotes
out=(char*)cJSON_malloc(len+2); /* This is how long we need for the string, roughly. */
out=(char*)cJSON_mallocstr(len+2); /* This is how long we need for the string, roughly. */
if (!out) return 0;
ptr=str+1;ptr2=out;
@ -238,7 +273,7 @@ static char *print_string_ptr(const char *str)
if (!str) return cJSON_strdup("");
ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
out=(char*)cJSON_malloc(len+3+1);
out=(char*)cJSON_mallocstr(len+3+1);
if (!out) return 0;
ptr2=out;ptr=str;
@ -372,7 +407,7 @@ static const char *parse_array(cJSON *item,const char *value)
/* Render an array to text */
static char *print_array(cJSON *item,int32_t depth,int32_t fmt)
{
char **entries;
char **entries,*space_entries[512];
char *out=0,*ptr,*ret;int32_t len=5;
cJSON *child=item->child;
int32_t numentries=0,i=0,fail=0;
@ -382,12 +417,12 @@ static char *print_array(cJSON *item,int32_t depth,int32_t fmt)
/* Explicitly handle numentries==0 */
if (!numentries)
{
out=(char*)cJSON_malloc(3+1);
out=(char*)cJSON_mallocstr(3+1);
if (out) strcpy(out,"[]");
return out;
}
/* Allocate an array to hold the values for each */
entries=(char**)cJSON_malloc((1+numentries)*sizeof(char*));
entries=cJSON_mallocptrs(1+numentries,space_entries,sizeof(space_entries)/sizeof(*space_entries));
if (!entries) return 0;
memset(entries,0,numentries*sizeof(char*));
/* Retrieve all the results: */
@ -401,15 +436,15 @@ static char *print_array(cJSON *item,int32_t depth,int32_t fmt)
}
/* If we didn't fail, try to malloc the output string */
if (!fail) out=(char*)cJSON_malloc(len+1);
if (!fail) out=(char*)cJSON_mallocstr(len+1);
/* If that fails, we fail. */
if (!out) fail=1;
/* Handle failure. */
if (fail)
{
for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
cJSON_free(entries);
for (i=0;i<numentries;i++) if (entries[i]) cJSON_freestr(entries[i]);
cJSON_freeptrs(entries,numentries,space_entries);
return 0;
}
@ -420,9 +455,9 @@ static char *print_array(cJSON *item,int32_t depth,int32_t fmt)
{
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
cJSON_free(entries[i]);
cJSON_freestr(entries[i]);
}
cJSON_free(entries);
cJSON_freeptrs(entries,numentries,space_entries);
*ptr++=']';*ptr++=0;
return out;
}
@ -466,7 +501,7 @@ static const char *parse_object(cJSON *item,const char *value)
/* Render an object to text. */
static char *print_object(cJSON *item,int32_t depth,int32_t fmt)
{
char **entries=0,**names=0;
char **entries=0,**names=0,*space_entries[512],*space_names[512];
char *out=0,*ptr,*ret,*str;int32_t len=7,i=0,j;
cJSON *child=item->child,*firstchild;
int32_t numentries=0,fail=0;
@ -485,7 +520,7 @@ static char *print_object(cJSON *item,int32_t depth,int32_t fmt)
/* Explicitly handle empty object case */
if (!numentries)
{
out=(char*)cJSON_malloc(fmt?depth+4+1:3+1);
out=(char*)cJSON_mallocstr(fmt?depth+4+1:3+1);
if (!out) return 0;
ptr=out;*ptr++='{';
if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';}
@ -493,10 +528,10 @@ static char *print_object(cJSON *item,int32_t depth,int32_t fmt)
return out;
}
/* Allocate space for the names and the objects */
entries=(char**)cJSON_malloc(numentries*sizeof(char*));
entries=(char**)cJSON_mallocptrs(numentries,space_entries,sizeof(space_entries)/sizeof(*space_entries));
if (!entries) return 0;
names=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!names) {cJSON_free(entries);return 0;}
names=(char**)cJSON_mallocptrs(numentries,space_names,sizeof(space_names)/sizeof(*space_names));
if (!names) {cJSON_freeptrs(entries,numentries,space_entries);return 0;}
memset(entries,0,sizeof(char*)*numentries);
memset(names,0,sizeof(char*)*numentries);
@ -513,14 +548,15 @@ static char *print_object(cJSON *item,int32_t depth,int32_t fmt)
}
/* Try to allocate the output string */
if (!fail) out=(char*)cJSON_malloc(len+1);
if (!fail) out=(char*)cJSON_mallocstr(len+1);
if (!out) fail=1;
/* Handle failure */
if (fail)
{
for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
cJSON_free(names);cJSON_free(entries);
for (i=0;i<numentries;i++) {if (names[i]) cJSON_freestr(names[i]);if (entries[i]) cJSON_freestr(entries[i]);}
cJSON_freeptrs(names,numentries,space_names);
cJSON_freeptrs(entries,numentries,space_entries);
return 0;
}
@ -534,10 +570,11 @@ static char *print_object(cJSON *item,int32_t depth,int32_t fmt)
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
if (i!=numentries-1) *ptr++=',';
if (fmt) *ptr++='\n';*ptr=0;
cJSON_free(names[i]);cJSON_free(entries[i]);
cJSON_freestr(names[i]);cJSON_freestr(entries[i]);
}
cJSON_free(names);cJSON_free(entries);
cJSON_freeptrs(names,numentries,space_names);
cJSON_freeptrs(entries,numentries,space_entries);
if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
*ptr++='}';*ptr++=0;
return out;
@ -578,8 +615,6 @@ cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->t
cJSON *cJSON_CreateBool(int32_t b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int64_t)num;}return item;}
cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
/* Create Arrays: */
cJSON *cJSON_CreateIntArray(int64_t *numbers,int32_t count) {int32_t i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber((double)numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
@ -1129,4 +1164,33 @@ cJSON *addrs_jsonarray(uint64_t *addrs,int32_t num)
return(array);
}
void free_json(cJSON *json) { if ( json != 0 ) cJSON_Delete(json); }
cJSON *cJSON_CreateArray(void)
{
cJSON *item = cJSON_New_Item();
if ( item )
item->type = cJSON_Array;
//#ifdef CJSON_GARBAGECOLLECTION
// cJSON_register(item);
//#endif
return(item);
}
cJSON *cJSON_CreateObject(void)
{
cJSON *item = cJSON_New_Item();
if ( item )
item->type = cJSON_Object;
//#ifdef CJSON_GARBAGECOLLECTION
// cJSON_register(item);
//#endif
return item;
}
void free_json(cJSON *item)
{
//#ifdef CJSON_GARBAGECOLLECTION
// cJSON_unregister(item);
//#endif
if ( item != 0 )
cJSON_Delete(item);
}

12
crypto777/iguana_OS.c

@ -877,7 +877,7 @@ void *OS_loadfile(char *fname,char **bufp,long *lenp,long *allocsizep)
{
fclose(fp);
*lenp = 0;
printf("OS_loadfile null size.(%s)\n",fname);
//printf("OS_loadfile null size.(%s)\n",fname);
return(0);
}
if ( filesize > buflen-1 )
@ -901,11 +901,15 @@ void *OS_loadfile(char *fname,char **bufp,long *lenp,long *allocsizep)
return(buf);
}
void *OS_filestr(long *allocsizep,char *fname)
void *OS_filestr(long *allocsizep,char *_fname)
{
long filesize = 0; char *buf = 0;
long filesize = 0; char *fname,*buf = 0; void *retptr;
*allocsizep = 0;
return(OS_loadfile(fname,&buf,&filesize,allocsizep));
fname = malloc(strlen(_fname)+1);
strcpy(fname,_fname);
retptr = OS_loadfile(fname,&buf,&filesize,allocsizep);
free(fname);
return(retptr);
}
// following functions cant be fully implemented in one or more OS

6
crypto777/iguana_utils.c

@ -303,7 +303,7 @@ struct iguana_thread *iguana_launch(struct iguana_info *coin,char *name,iguana_f
coin->Launched[t->type]++;
retval = OS_thread_create(&t->handle,NULL,(void *)iguana_launcher,(void *)t);
if ( retval != 0 )
printf("error launching %s\n",t->name);
printf("error launching %s retval.%d errno.%d\n",t->name,retval,errno);
while ( (t= queue_dequeue(&TerminateQ)) != 0 )
{
if ( (rand() % 100000) == 0 && coin != 0 )
@ -446,7 +446,6 @@ char *clonestr(char *str)
return(clone);
}
int32_t safecopy(char *dest,char *src,long len)
{
int32_t i = -1;
@ -459,6 +458,7 @@ int32_t safecopy(char *dest,char *src,long len)
if ( i == len )
{
printf("safecopy: %s too long %ld\n",src,len);
//printf("divide by zero! %d\n",1/zeroval());
#ifdef __APPLE__
//getchar();
#endif
@ -992,6 +992,7 @@ int32_t RS_encode(char *rsaddr,uint64_t id)
rsaddr[j++] = '-';
}
rsaddr[j] = 0;
//printf("%llu -> NXT RS (%s)\n",(long long)id,rsaddr);
return(0);
}
@ -1122,6 +1123,7 @@ void calc_NXTaddr(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len)
{
uint8_t mysecret[32]; uint64_t nxt64bits;
nxt64bits = conv_NXTpassword(mysecret,buf,msg,len);
//printf("call RSencode with %llu\n",(long long)nxt64bits);
RS_encode(hexstr,nxt64bits);
}

2
iguana/coins/basilisk/mshark

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"SHARK.conf\",\"path\":\"${HOME#"/"}/.komodo/SHARK\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":0,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"SHARK\",\"name\":\"SHARK\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"54a5e30c\",\"p2p\":14103,\"rpc\":14104,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}"

2
iguana/coins/chips_7776

@ -1,2 +1,2 @@
#!/bin/bash
curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"chips.conf\",\"path\":\"${HOME#"/"}/.chips\",\"prefetchlag\":-1,\"poll\":1,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"newcoin\":\"CHIPS\",\"startpend\":64,\"endpend\":64,\"services\":0,\"maxpeers\":512,\"RELAY\":-1,\"VALIDATE\":0,\"portp2p\":57777,\"minconfirms\":1}"
curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"chips.conf\",\"path\":\"${HOME#"/"}/.chips\",\"prefetchlag\":-1,\"poll\":1,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"newcoin\":\"CHIPS\",\"startpend\":64,\"endpend\":64,\"services\":0,\"maxpeers\":512,\"RELAY\":-1,\"VALIDATE\":0,\"portp2p\":57777,\"minconfirms\":1,\"pubval\":60,\"p2shval\":85,\"wifval\":188}"

2
iguana/coins/genshark

@ -1,2 +1,2 @@
curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"SHARK.conf\",\"path\":\"${HOME#"/"}/.komodo/SHARK\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":1,\"VALIDATE\":1,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"SHARK\",\"name\":\"SHARK\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"54a5e30c\",\"p2p\":10113,\"rpc\":10114,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}"
curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"SHARK.conf\",\"path\":\"${HOME#"/"}/.komodo/SHARK\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":1,\"VALIDATE\":1,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"SHARK\",\"name\":\"SHARK\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"54a5e30c\",\"p2p\":14103,\"rpc\":14104,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}"

2
iguana/coins/mshark_7776

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"MSHARK.conf\",\"path\":\"${HOME#"/"}/.komodo/MSHARK\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"MSHARK\",\"name\":\"MSHARK\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"54a5e30c\",\"p2p\":8845,\"rpc\":8846,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}"

2
iguana/coins/shark_7776

@ -1,2 +1,2 @@
curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"SHARK.conf\",\"path\":\"${HOME#"/"}/.komodo/SHARK\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"SHARK\",\"name\":\"SHARK\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"54a5e30c\",\"p2p\":10113,\"rpc\":10114,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}"
curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"SHARK.conf\",\"path\":\"${HOME#"/"}/.komodo/SHARK\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"SHARK\",\"name\":\"SHARK\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"54a5e30c\",\"p2p\":14103,\"rpc\":14104,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}"

16
iguana/dexscripts.win32/1-client.cmd

@ -0,0 +1,16 @@
@echo off
set USERHOME=%APPDATA:\=\\%
rem [!] Coins config now taked from coins.json file, no need to put in environment variable
rem ---------------------------------------------------------------------------------------
rem set COINS=[{\"coin\":\"REVS\",\"active\":1,\"asset\":\"REVS\",\"rpcport\":10196}]
rem marketmaker "{\"gui\":\"nogui\",\"client\":1, \"userhome\":\"%USERHOME%\", \"passphrase\":\"mypassphrase\", \"coins\":%COINS%}"
set COINS=\"\"
set /p PASSPHRASE=<passphrase
rem , \"canbind\":1
rem marketmaker "{\"gui\":\"nogui\",\"client\":1, \"userhome\":\"%USERHOME%\", \"passphrase\":\"%PASSPHRASE%\"}" 1> marketmaker.log 2>&1
marketmaker "{\"gui\":\"nogui\",\"client\":1, \"userhome\":\"%USERHOME%\", \"passphrase\":\"%PASSPHRASE%\"}"

7
iguana/dexscripts.win32/2-getuserpass.cmd

@ -0,0 +1,7 @@
@echo off
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":null,\"method\":\"enable\",\"coin\":\" \"}" -s > userpass.json
for /f "tokens=2 delims=:," %%a in (' find "userpass" "userpass.json" ') do (
echo UserPass: %%~a
echo %%~a > userpass
)
del userpass.json

4
iguana/dexscripts.win32/balance.cmd

@ -0,0 +1,4 @@
@echo off
set /p TMPUSERPASS=<userpass
set USERPASS=%TMPUSERPASS: =%
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"balance\",\"coin\":\"KMD\",\"address\":\"RSpP2Nffy379SwF1cAkooNg6vwPHpakCpC\"}"

7
iguana/dexscripts.win32/bot_buy.cmd

@ -0,0 +1,7 @@
@echo off
set /p TMPUSERPASS=<userpass
set USERPASS=%TMPUSERPASS: =%
set /p PASSPHRASE=<passphrase
echo passphrase: "%PASSPHRASE%"
echo userpass: "%USERPASS%"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"bot_buy\",\"base\":\"MNZ\",\"rel\":\"KMD\",\"maxprice\":0.20,\"relvolume\":10.0}"

7
iguana/dexscripts.win32/bot_list.cmd

@ -0,0 +1,7 @@
@echo off
set /p TMPUSERPASS=<userpass
set USERPASS=%TMPUSERPASS: =%
set /p PASSPHRASE=<passphrase
rem echo passphrase: "%PASSPHRASE%"
rem echo userpass: "%USERPASS%"
curl -s --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"bot_list\"}"

7
iguana/dexscripts.win32/bot_statuslist.cmd

@ -0,0 +1,7 @@
@echo off
set /p TMPUSERPASS=<userpass
set USERPASS=%TMPUSERPASS: =%
set /p PASSPHRASE=<passphrase
rem echo passphrase: "%PASSPHRASE%"
rem echo userpass: "%USERPASS%"
curl -s --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"bot_statuslist\"}"

7
iguana/dexscripts.win32/bot_stop.cmd

@ -0,0 +1,7 @@
@echo off
set /p TMPUSERPASS=<userpass
set USERPASS=%TMPUSERPASS: =%
set /p PASSPHRASE=<passphrase
rem echo passphrase: "%PASSPHRASE%"
rem echo userpass: "%USERPASS%"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"bot_stop\",\"botid\":1376557535}"

BIN
iguana/dexscripts.win32/curl.exe

Binary file not shown.

9
iguana/dexscripts.win32/electrum.cmd

@ -0,0 +1,9 @@
@echo off
rem http://pad.supernet.org/electrum-servers
set /p TMPUSERPASS=<userpass
set USERPASS=%TMPUSERPASS: =%
set /p PASSPHRASE=<passphrase
echo passphrase: "%PASSPHRASE%"
echo userpass: "%USERPASS%"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"electrum\",\"coin\":\"KMD\",\"ipaddr\":\"electrum.cipig.net\",\"port\":10001}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"electrum\",\"coin\":\"MNZ\",\"ipaddr\":\"electrum.cipig.net\",\"port\":10002}"

4
iguana/dexscripts.win32/enable.cmd

@ -0,0 +1,4 @@
@echo off
set /p TMPUSERPASS=<userpass
set USERPASS=%TMPUSERPASS: =%
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"enable\",\"coin\":\"REVS\"}"

4
iguana/dexscripts.win32/getcoin.cmd

@ -0,0 +1,4 @@
@echo off
set /p TMPUSERPASS=<userpass
set USERPASS=%TMPUSERPASS: =%
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"getcoin\",\"coin\":\"KMD\"}"

4
iguana/dexscripts.win32/getutxos.cmd

@ -0,0 +1,4 @@
@echo off
set /p TMPUSERPASS=<userpass
set USERPASS=%TMPUSERPASS: =%
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"getutxos\",\"coin\":\"KMD\"}"

2
iguana/dexscripts.win32/help.cmd

@ -0,0 +1,2 @@
@echo off
curl --url "http://127.0.0.1:7783" --data "{\"method\":\"help\"}"

100
iguana/dexscripts.win32/how_to_use.md

@ -0,0 +1,100 @@
## DexScripts for Windows. How to use? ##
**1.** Before start you should put scripts and following binaries into one folder:
- curl.exe (required for all scripts)
- marketmaker.exe
- libcurl.dll (required to run marketmaker)
- nanomsg.dll (required to run marketmaker)
**2.** Don't forget to put `coins.json` file into a same folder. This file is available it this repo.
**3.** Type your passphrase into passphrase file in this folder (you should create file with name `passphrase` and without extension) and run `1-client.cmd`. This will run marketmaker. Next step is to obtain userpass needed for other scripts, you can simply copy and paste it from marketmaker output on startup into userpass file.
![](./images/userpass.png)
Or run `2-getuserpass.cmd` to fill userpass file automatically.** NB!** To get userpass you shouldn't run any scripts between 1-client.cmd and 2-getuserpass.cmd launching.
Sample output of correct `2-getuserpass.cmd` usage is:
![](./images/userpass_usage.png)
You should see your userpass on screen, and after it will automatically copied in userpass file. It's important to all other scripts to have this password in userpass file. If output of `2-getuserpass.cmd` is not same as showed on screen above - wait some seconds and run `2-getuserpass.cmd` again. Also make sure that you have allowed marketmaker to accept incoming connections in your Windows Firewall (first time launched system should automatically asked for it).
**4.** For using other scripts please refer to barterDEX API. Or **barterDEX API Summary by Category** document by *shossain*.
## Scripts List ##
**NB!** Before you use any script that do some actions with your coins (for example, withdraw and others) **edit it** and make sure that it have correct addresses, coin name and volumes inside. Don't run any scripts without looking on it's source and clearly understanding what it does.
* **1-client.cmd** - used to start Marketmaker. Make sure you already have filled a strong passphrase into `passphrase` file as described above.
* **2-getuserpass.cmd** - fills userpass in `userpass` file. this step needed to use any other scripts.
* **balance.cmd** - displays current balance of selected coin.
* **enable.cmd** - enables a selected coin for trading.
* **getcoin.cmd** - prints information about a selecting coin:
{"result":"success","enabled":2,"disabled":70,"coin":{"coin":"KMD","installed":true,"height":580716,"balance":72.68774305,"KMDvalue":72.68774305,"status":"active","electrum":"electrum.cipig.net:10001","smartaddress":"RTCVGuoSNehKG8YYxcoskC7LK1yZhgvQRV","rpc":"127.0.0.1:7771","pubtype":60,"p2shtype":85,"wiftype":188,"txfee":10000}}
* **getutxos.cmd** - seems alredy deprecated.
* **inventory.cmd** - prints your inventory.
* **listunspent.cmd** - prints your utxos.
* **orderbook.cmd** - prints base/rel orderbook.
* **portfolio.cmd** - prints porfolio information.
* **snapshot.cmd** - ...
* **electrum.cmd** - allows you to run coins in electum mode (!), example includes two coins - KMD and MNZ. if you need to run more coins in electrum mode, add needed electrum servers from here - [http://pad.supernet.org/electrum-servers](http://pad.supernet.org/electrum-servers).
* **help.cmd** - displays help about all available API commands.
* **bot_buy.cmd** - launches bot for buying. you'll need to set base and rel coin in script, and also maxprice and relvolume.
* **bot_list.cmd** - lists id of all running bots.
* **bot_statuslist.cmd** - list statuses of all running bots.
* **bot_stop.cmd** - stopt the bot with given bot_id.
* **withdraw.cmd** - example of withdraw method. you can send coins from your smartaddress to any other address using widthraw. as a result method generates signed raw tx in hex, which you can use with sendrawtransaction.cmd . remember, that withdraw only *prepares* transaction, but it doesn't broadcast (send) it to network. after tx is prepared we need to send it using sendrawtransaction method.
* **sendrawtransaction.cmd** - sends raw transaction. you'll need a signedtx in hex.
* **withdraw_send.cmd** - combines withdraw and send raw tx scripts. you can call it `send`, just specify coin, volume and addresses to which you wan send coins and it will prepare and broadcast transaction automatically.
* **withdraw_10_send.cmd** - example of inventory split: this split 10 KMD from your balance to Alice inventory in 10 utxos pairs (1.002, 0.00386871). Strongly recommended to read [http://pad.supernet.org/barterdex-readme](http://pad.supernet.org/barterdex-readme) -> UTXO PAIRS to understand the basics. This script is just for example how you can split your coins in (X, X/777) to start trading them.
## F.A.Q. ##
**Q.** Is any simple way how i can display JSON results returned by all scripts, like orderbook and others, in human readable form?
**A.** Yes, you can use this service [JSON Editor Online](http://jsoneditoronline.org/), just copy and paste output of script in left column and see structured output in right.
**Q.** I see an output like this when i'm start `1-client.cmd` :
bind(0.0.0.0) port.7783 failed: No error sock.1468. errno.0
bind(0.0.0.0) port.7783 failed: No error sock.1516. errno.0
bind(0.0.0.0) port.7783 failed: No error sock.1444. errno.0
bind(0.0.0.0) port.7783 failed: No error sock.1484. errno.0
bind(0.0.0.0) port.7783 failed: No error sock.1412. errno.0
bind(0.0.0.0) port.7783 failed: No error sock.1524. errno.0
bind(0.0.0.0) port.7783 failed: No error sock.1008. errno.0
And nothing works.
**A.** Before run `1-client.cmd` make sure in Task Manager that you haven't already running `marketmaker.exe`. If have - kill this process via Task Manager or via command line command `taskkill /f /im taskkill.exe` .
**Q.** How can i pretty print JSON answers of marketmaker?
**A.** You can get best results with 2 tools - [conemu](https://conemu.github.io/) and [jq](https://stedolan.github.io/jq/), conemu supports ANSI X3.64 and Xterm 256 colors and jq allow you to pretty-print json output with colors, like this:
![](./images/conemu_jq.png)
Also i'm always recommend to install [Far Manager](https://www.farmanager.com/index.php?l=en) - this is powerful console file manager for Windows, like Midnight Commander in *nix.
**Q.** What additional dependencies required by marketmaker?
**A.** Currently marketmaker (Windows) used the following DLLs:
*32 bit:*
- libcrypto-1_1.dll
- libcurl.dll
- libssl-1_1.dll
- nanomsg.dll
- pthreadvc2.dll
*64-bit:*
- libcurl.dll
- nanomsg.dll
It already included in repo and in archive with release.

BIN
iguana/dexscripts.win32/images/conemu_jq.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
iguana/dexscripts.win32/images/userpass.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
iguana/dexscripts.win32/images/userpass_usage.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

4
iguana/dexscripts.win32/inventory.cmd

@ -0,0 +1,4 @@
@echo off
set /p TMPUSERPASS=<userpass
set USERPASS=%TMPUSERPASS: =%
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"inventory\",\"coin\":\"KMD\"}"

4
iguana/dexscripts.win32/listunspent.cmd

@ -0,0 +1,4 @@
@echo off
set /p TMPUSERPASS=<userpass
set USERPASS=%TMPUSERPASS: =%
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"listunspent\",\"coin\":\"KMD\",\"address\":\"RSpP2Nffy379SwF1cAkooNg6vwPHpakCpC\"}"

4
iguana/dexscripts.win32/orderbook.cmd

@ -0,0 +1,4 @@
@echo off
set /p TMPUSERPASS=<userpass
set USERPASS=%TMPUSERPASS: =%
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"orderbook\",\"base\":\"KMD\",\"rel\":\"REVS\"}"

1
iguana/dexscripts.win32/passphrase

@ -0,0 +1 @@
your_very_strong_secret_passphrase

4
iguana/dexscripts.win32/portfolio.cmd

@ -0,0 +1,4 @@
@echo off
set /p TMPUSERPASS=<userpass
set USERPASS=%TMPUSERPASS: =%
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"portfolio\"}"

5
iguana/dexscripts.win32/sendrawtransaction.cmd

@ -0,0 +1,5 @@
@echo off
set /p TMPUSERPASS=<userpass
set USERPASS=%TMPUSERPASS: =%
set HEX=your_signed_raw_tx
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"sendrawtransaction\",\"coin\":\"KMD\",\"signedtx\":%HEX%"\"}"

5
iguana/dexscripts.win32/snapshot.cmd

@ -0,0 +1,5 @@
@echo off
set /p TMPUSERPASS=<userpass
set USERPASS=%TMPUSERPASS: =%
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"snapshot\",\"coin\":\"KMD\",\"height\":%1}"

0
iguana/dexscripts.win32/userpass

8
iguana/dexscripts.win32/withdraw.cmd

@ -0,0 +1,8 @@
@echo off
set /p TMPUSERPASS=<userpass
set USERPASS=%TMPUSERPASS: =%
rem *** Change coin and outputs before use (!) ***
set COIN=KMD
set OUTPUTS=[{\"RDecker69MM5dhDBosUXPNTzfoGqxPQqHu\":0.00007777}]
curl -s --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"withdraw\",\"coin\":\"%COIN%\",\"outputs\":%OUTPUTS%}" > withdraw.txt
type withdraw.txt

14
iguana/dexscripts.win32/withdraw_10_send.cmd

@ -0,0 +1,14 @@
@echo off
set /p TMPUSERPASS=<userpass
set USERPASS=%TMPUSERPASS: =%
rem *** Change coin and outputs before use (!) ***
set COIN=KMD
set SMARTADDRESS=RDecker69MM5dhDBosUXPNTzfoGqxPQqHu
set OUTPUTS=[{\"%SMARTADDRESS%\":1.002},{\"%SMARTADDRESS%\":0.00386871},{\"%SMARTADDRESS%\":1.002},{\"%SMARTADDRESS%\":0.00386871},{\"%SMARTADDRESS%\":1.002},{\"%SMARTADDRESS%\":0.00386871},{\"%SMARTADDRESS%\":1.002},{\"%SMARTADDRESS%\":0.00386871},{\"%SMARTADDRESS%\":1.002},{\"%SMARTADDRESS%\":0.00386871},{\"%SMARTADDRESS%\":1.002},{\"%SMARTADDRESS%\":0.00386871},{\"%SMARTADDRESS%\":1.002},{\"%SMARTADDRESS%\":0.00386871},{\"%SMARTADDRESS%\":1.002},{\"%SMARTADDRESS%\":0.00386871},{\"%SMARTADDRESS%\":1.002},{\"%SMARTADDRESS%\":0.00386871},{\"%SMARTADDRESS%\":1.002},{\"%SMARTADDRESS%\":0.00386871}]
curl -s --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"withdraw\",\"coin\":\"%COIN%\",\"outputs\":%OUTPUTS%}" > withdraw.txt
type withdraw.txt
timeout /t 5 /nobreak
for /f "tokens=4 delims=:," %%a in (' find "hex" "withdraw.txt" ') do (
rem echo [%%~a]
curl -s --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"sendrawtransaction\",\"coin\":\"%COIN%\",\"signedtx\":\"%%~a\"}"
)

14
iguana/dexscripts.win32/withdraw_send.cmd

@ -0,0 +1,14 @@
@echo off
set /p TMPUSERPASS=<userpass
set USERPASS=%TMPUSERPASS: =%
rem *** Change coin and outputs before use (!) ***
set COIN=KMD
set OUTPUTS=[{\"RDecker69MM5dhDBosUXPNTzfoGqxPQqHu\":0.00007777}]
curl -s --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"withdraw\",\"coin\":\"%COIN%\",\"outputs\":%OUTPUTS%}" > withdraw.txt
type withdraw.txt
timeout /t 5 /nobreak
for /f "tokens=4 delims=:," %%a in (' find "hex" "withdraw.txt" ') do (
rem echo [%%~a]
curl -s --url "http://127.0.0.1:7783" --data "{\"userpass\":\"%USERPASS%\",\"method\":\"sendrawtransaction\",\"coin\":\"%COIN%\",\"signedtx\":\"%%~a\"}"
)

2
iguana/dpow/dpow_network.c

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

2
iguana/dpow/dpow_rpc.c

@ -820,7 +820,7 @@ int32_t dpow_haveutxo(struct supernet_info *myinfo,struct iguana_info *coin,bits
}
}
if ( haveutxo == 0 )
printf("no utxo: need to fund address.(%s) or wait for splitfund to confirm\n",coinaddr);
printf("no %s utxo: need to fund address.(%s) or wait for splitfund to confirm\n",coin->symbol,coinaddr);
} //else printf("null utxo array size\n");
free_json(unspents);
} else printf("null return from dpow_listunspent\n");

0
iguana/exchanges/DB/PRICES/.tmpmarker

6
iguana/exchanges/DEXstats.h

@ -51,7 +51,7 @@ struct DEXstats_pricepoint
struct DEXstats_pairinfo
{
char dest[16];
char dest[128];
int32_t numprices;
struct DEXstats_pricepoint *prices;
};
@ -64,7 +64,7 @@ struct DEXstats_datenuminfo
struct DEXstats_priceinfo
{
char symbol[16];
char symbol[128];
int32_t firstdatenum,numdates;
struct DEXstats_datenuminfo *dates;
} Prices[1024];
@ -927,6 +927,7 @@ char *stats_prices(char *symbol,char *dest,struct DEXstats_disp *prices,int32_t
}
#ifndef FROM_MARKETMAKER
#ifndef FROM_PRIVATEBET
char *stats_JSON(void *ctx,char *myipaddr,int32_t mypubsock,cJSON *argjson,char *remoteaddr,uint16_t port)
{
char *method,*agent,*retstr,*source,*dest; struct tai T; uint32_t endtimestamp; struct DEXstats_disp prices[365]; int32_t leftdatenum,seconds,numdates;
@ -953,5 +954,6 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t mypubsock,cJSON *argjson,char
return(clonestr(jprint(argjson,0)));
}
#endif
#endif
#endif /* DEXstats_h */

342
iguana/exchanges/LP_NXT.c

@ -0,0 +1,342 @@
/******************************************************************************
* Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
//
// LP_NXT.c
// marketmaker
//
char *NXTnodes[] = { "62.75.159.113", "91.44.203.238", "82.114.88.225", "78.63.207.76", "188.174.110.224", "91.235.72.49", "213.144.130.91", "209.222.98.250", "216.155.128.10", "178.33.203.157", "162.243.122.251", "69.163.47.173", "193.151.106.129", "78.94.2.74", "192.3.196.10", "173.33.112.87", "104.198.173.28", "35.184.154.126", "174.140.167.239", "23.88.113.131", "198.71.84.173", "178.150.207.53", "23.88.61.53", "192.157.233.106", "192.157.241.212", "23.89.192.88", "23.89.200.27", "192.157.241.139", "23.89.200.63", "23.89.192.98", "163.172.214.102", "176.9.85.5", "80.150.243.88", "80.150.243.92", "80.150.243.98", "109.70.186.198", "146.148.84.237", "104.155.56.82", "104.197.157.140", "37.48.73.249", "146.148.77.226", "84.57.170.200", "107.161.145.131", "80.150.243.97", "80.150.243.93", "80.150.243.100", "80.150.243.95", "80.150.243.91", "80.150.243.99", "80.150.243.96", "93.231.187.177", "212.237.23.85", "35.158.179.254", "46.36.66.41", "185.170.113.79", "163.172.68.112", "78.47.35.210", "77.90.90.75", "94.177.196.134", "212.237.22.215", "94.177.234.11", "167.160.180.199", "54.68.189.9", "94.159.62.14", "195.181.221.89", "185.33.145.94", "195.181.209.245", "195.181.221.38", "195.181.221.162", "185.33.145.12", "185.33.145.176", "178.79.128.235", "94.177.214.120", "94.177.199.41", "94.177.214.200", "94.177.213.201", "212.237.13.162", "195.181.221.236", "195.181.221.185", "185.28.103.187", "185.33.146.244", "217.61.123.71", "195.181.214.45", "195.181.212.99", "195.181.214.46", "195.181.214.215", "195.181.214.68", "217.61.123.118", "195.181.214.79", "217.61.123.14", "217.61.124.100", "195.181.214.111", "85.255.0.176", "81.2.254.116", "217.61.123.184", "195.181.212.231", "94.177.214.110", "195.181.209.164", "104.129.56.238", "85.255.13.64", "167.160.180.206", "217.61.123.226", "167.160.180.208", "93.186.253.127", "212.237.6.208", "94.177.207.190", "217.61.123.119", "85.255.1.245", "217.61.124.157", "37.59.57.141", "167.160.180.58", "104.223.53.14", "217.61.124.69", "195.181.212.103", "85.255.13.141", "104.207.133.204", "71.90.7.107", "107.150.18.108", "23.94.134.161", "80.150.243.13", "80.150.243.11", "185.81.165.52", "80.150.243.8" };
static char *assetids[][4] =
{
{ "13502152099823770958", "SUPERNETx2", "10000", "10000" },
{ "12071612744977229797", "SUPERNET", "10000", "10000" },
{ "12071612744977229797", "UNITY", "10000", "10000" },
{ "15344649963748848799", "DEX", "1", "100000000" },
{ "6883271355794806507", "PANGEA", "10000", "10000" },
{ "17911762572811467637", "JUMBLR", "10000", "10000" },
{ "17083334802666450484", "BET", "10000", "10000" },
{ "13476425053110940554", "CRYPTO", "1000", "100000" },
{ "6932037131189568014", "HODL", "1", "100000000" },
//{ "3006420581923704757", "SHARK", "10000", "10000" },
{ "3006420581923704757", "MSHARK", "10", "10000000" },
{ "17571711292785902558", "BOTS", "1", "100000000" },
{ "10524562908394749924", "MGW", "1", "100000000" },
{ "8217222248380501882", "MESH", "10000", "10000" },
{ "15641806960898178066", "TOKEN", "1", "100000000" },
};
void LP_sendtoaddress_line(char *validaddress,char *assetname,uint64_t satoshis,uint64_t txnum)
{
char line[1024],lowerstr[64];
if ( strcmp(assetname,"SUPERNETx2") == 0 )
{
sprintf(line,"fiat/supernet sendtoaddress %s %.8f # txnum.%llu",validaddress,dstr(satoshis),(long long)txnum);
printf("%s\n",line);
sprintf(line,"fiat/revs sendtoaddress %s %.8f # txnum.%llu",validaddress,dstr(satoshis),(long long)txnum);
}
else
{
if ( strcmp(assetname,"TOKEN") == 0 )
strcpy(lowerstr,"supernet");
else strcpy(lowerstr,assetname);
tolowercase(lowerstr);
sprintf(line,"sleep 1; fiat/%s sendtoaddress %s %.8f # txnum.%llu",lowerstr,validaddress,dstr(satoshis),(long long)txnum);
}
printf("%s\n",line);
}
uint64_t LP_assetid_mult(int32_t *assetindp,char *name,uint64_t assetid)
{
int32_t i; uint64_t mult = 0;
name[0] = 0;
*assetindp = -1;
for (i=0; i<sizeof(assetids)/sizeof(*assetids); i++)
{
if ( assetid == calc_nxt64bits(assetids[i][0]) )
{
*assetindp = i;
mult = atoi(assetids[i][3]);
strcpy(name,assetids[i][1]);
break;
}
}
return(mult);
}
cJSON *LP_NXT_message(char *method,uint64_t txnum,char *passphrase)
{
char url[1024],*retstr; cJSON *retjson = 0;
sprintf(url,"http://127.0.0.1:7876/nxt?requestType=%s&transaction=%llu&secretPhrase=%s",method,(long long)txnum,passphrase);
//printf("issue.(%s)\n",url);
if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
}
free(retstr);
}
return(retjson);
}
cJSON *LP_NXT_decrypt(uint64_t txnum,char *account,char *data,char *nonce,char *passphrase)
{
char url[1024],*retstr; cJSON *retjson = 0;
if ( account != 0 && data != 0 && nonce != 0 && passphrase != 0 )
{
sprintf(url,"http://127.0.0.1:7876/nxt?requestType=readMessage&transaction=%llu&secretPhrase=%s",(long long)txnum,passphrase);
if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
}
free(retstr);
}
}
return(retjson);
}
int64_t NXTventure_qty(uint64_t assetid)
{
char url[1024],*retstr; uint64_t qty=0; cJSON *retjson;
sprintf(url,"http://127.0.0.1:7876/nxt?requestType=getAccountAssets&account=NXT-XRK4-5HYK-5965-9FH4Z&includeAssetInfo=true");
if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 )
{
printf("NXT_venture_qty(%s)\n",retstr);
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
free_json(retjson);
}
free(retstr);
}
//NXT_venture_qty({"accountAssets":[{"quantityQNT":"3900000000","unconfirmedQuantityQNT":"3900000000","decimals":4,"name":"ATOMIC","asset":"11694807213441909013"},{"quantityQNT":"2900000000","unconfirmedQuantityQNT":"2900000000","decimals":8,"name":"NSC","asset":"6775372232354238105"},{"quantityQNT":"750000000","unconfirmedQuantityQNT":"750000000","decimals":4,"name":"omnigames","asset":"7441230892853180965"},{"quantityQNT":"607438148","unconfirmedQuantityQNT":"607438148","decimals":4,"name":"ARDR","asset":"12422608354438203866"},{"quantityQNT":"451991779","unconfirmedQuantityQNT":"451991779","decimals":4,"name":"SuperNET","asset":"12071612744977229797"},{"quantityQNT":"146960000","unconfirmedQuantityQNT":"146960000","decimals":4,"name":"Privatebet","asset":"17083334802666450484"},{"quantityQNT":"79500188","unconfirmedQuantityQNT":"79500188","decimals":3,"name":"crypto777","asset":"13476425053110940554"},{"quantityQNT":"1495473","unconfirmedQuantityQNT":"1495473","decimals":0,"name":"jl777hodl","asset":"6932037131189568014"},{"quantityQNT":"500000","unconfirmedQuantityQNT":"500000","decimals":0,"name":"Boost","asset":"9719950459730291994"},{"quantityQNT":"200000","unconfirmedQuantityQNT":"200000","decimals":0,"name":"NXTforex","asset":"15245281832566929110"},{"quantityQNT":"150000","unconfirmedQuantityQNT":"150000","decimals":0,"name":"NXTsharks","asset":"8049009002993773168"},{"quantityQNT":"100000","unconfirmedQuantityQNT":"100000","decimals":5,"name":"solarweb","asset":"13604572534081373849"},{"quantityQNT":"75000","unconfirmedQuantityQNT":"75000","decimals":0,"name":"SNN","asset":"15113552914305929842"},{"quantityQNT":"57299","unconfirmedQuantityQNT":"57299","decimals":2,"name":"SLEUTH","asset":"4174874835406708311"},{"quantityQNT":"18801","unconfirmedQuantityQNT":"18801","decimals":2,"name":"BTCDdev","asset":"15131486578879082754"},{"quantityQNT":"18767","unconfirmedQuantityQNT":"18767","decimals":2,"name":"longzai","asset":"10955830010602647139"},{"quantityQNT":"13000","unconfirmedQuantityQNT":"13000","decimals":0,"name":"NXTventure","asset":"16212446818542881180"},{"quantityQNT":"7250","unconfirmedQuantityQNT":"7250","decimals":0,"name":"InstantDEX","asset":"15344649963748848799"},{"quantityQNT":"2873","unconfirmedQuantityQNT":"2873","decimals":4,"name":"EDinar","asset":"17740527756732147253"},{"quantityQNT":"39","unconfirmedQuantityQNT":"39","decimals":0,"name":"JebBush","asset":"1929419574701797581"},{"quantityQNT":"30","unconfirmedQuantityQNT":"30","decimals":0,"name":"Hilary","asset":"11814755740231942504"}],"requestProcessingTime":1})
return(qty);
}
void *curl_post(void **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3);
void NXTventure_liquidation()
{
/*{"quantityQNT":"607438148","unconfirmedQuantityQNT":"607438148","decimals":4,"name":"ARDR","asset":""},
{"quantityQNT":"451991779","unconfirmedQuantityQNT":"451991779","decimals":4,"name":"SuperNET","asset":"12071612744977229797"},
{"quantityQNT":"146960000","unconfirmedQuantityQNT":"146960000","decimals":4,"name":"Privatebet","asset":"17083334802666450484"},
{"quantityQNT":"79500188","unconfirmedQuantityQNT":"79500188","decimals":3,"name":"crypto777","asset":"13476425053110940554"},
{"quantityQNT":"1495473","unconfirmedQuantityQNT":"1495473","decimals":0,"name":"jl777hodl","asset":"6932037131189568014"},
{"quantityQNT":"7250","unconfirmedQuantityQNT":"7250","decimals":0,"name":"InstantDEX","asset":"15344649963748848799"},*/
char *assetids[][4] =
{
{ "12422608354438203866", "607438148", "ARDR", "10000" },
{ "12071612744977229797", "451991779", "SuperNET", "10000" },
{ "17083334802666450484", "146960000", "Privatebet", "10000" },
{ "13476425053110940554", "79500188", "crypto777", "1000" },
{ "6932037131189568014", "1495473", "jl777hodl", "1" },
{ "15344649963748848799", "7250", "InstantDEX", "1" },
};
void *cHandle=0; char *retstr,*retstr2,url[1024],*account; uint64_t txid,qty,qtyA,assetid,sum; double ratio; cJSON *array,*retjson2,*item,*retjson; int32_t i,j,decimals,numassetids=(int32_t)(sizeof(assetids)/sizeof(*assetids)),n=0;
char *passphrase = "";
sprintf(url,"http://127.0.0.1:7876/nxt?requestType=getAssetAccounts&asset=16212446818542881180");
if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (array= jarray(&n,retjson,"accountAssets")) != 0 )
{
for (j=0; j<numassetids; j++)
{
assetid = calc_nxt64bits(assetids[j][0]);
qtyA = calc_nxt64bits(assetids[j][1]);
decimals = (int32_t)calc_nxt64bits(assetids[j][3]);
printf("distribute %llu QNT of %s assetid %llu %.8f\n",(long long)qtyA,assetids[j][2],(long long)assetid,(double)qtyA / decimals);
sum = 0;
for (i=0; i<n; i++)
{
item = jitem(array,i);
qty = j64bits(item,"quantityQNT");
ratio = (double)qty / (1000000. - 13000.);
if ( (account= jstr(item,"accountRS")) != 0 && qtyA*ratio >= 1 )
{
if ( strcmp(account,"NXT-XRK4-5HYK-5965-9FH4Z") != 0 )
{
sum += (long long)(qtyA * ratio);
sprintf(url,"requestType=transferAsset&secretPhrase=%s&recipient=%s&asset=%llu&quantityQNT=%llu&feeNQT=100000000&deadline=60",passphrase,account,(long long)assetid,(long long)(qtyA * ratio));
if ( (retstr2= curl_post(&cHandle,"http://127.0.0.1:7876/nxt","",url,"","","","")) != 0 )
{
if ( (retjson2= cJSON_Parse(retstr2)) != 0 )
{
txid = j64bits(retjson2,"transaction");
printf("%s %.6f %8llu QNT %s -> %llu %.8f txid %llu\n",account,ratio,(long long)qtyA,assetids[j][2],(long long)(qtyA * ratio),((double)(long long)(qtyA * ratio))/decimals,(long long)txid);
free_json(retjson2);
}
free(retstr2);
}
usleep(250000);
}
}
}
printf("%s distribution total %llu QNT %.8f\n",assetids[j][2],(long long)sum,(double)sum/decimals);
}
}
free_json(retjson);
}
printf("NXTventure assethodlers.%d\n",n);
free(retstr);
}
}
cJSON *LP_NXT_redeems()
{
char url[1024],*retstr,*recv,*method,*msgstr,assetname[128]; uint64_t totals[2][sizeof(assetids)/sizeof(*assetids)],mult,txnum,assetid,qty; int32_t i,ind,numtx=0,past_marker=0; cJSON *item,*attach,*decjson,*array,*msgjson,*encjson,*retjson=0;
uint64_t txnum_marker = calc_nxt64bits("5509605741355242617");
uint64_t txnum_marker2 = calc_nxt64bits("7256847492742571143");
char *passphrase = "";
char *account = "NXT-MRBN-8DFH-PFMK-A4DBM";
memset(totals,0,sizeof(totals));
sprintf(url,"http://127.0.0.1:7876/nxt?requestType=getBlockchainTransactions&account=%s",account);
//printf("calling (%s)\n",url);
if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (array= jarray(&numtx,retjson,"transactions")) != 0 )
{
for (i=0; i<numtx; i++)
{
msgjson = encjson = decjson = 0;
txnum = assetid = qty = 0;
item = jitem(array,i);
msgstr = jstr(item,"message");
txnum = j64bits(item,"transaction");
if ( txnum == txnum_marker )
past_marker = 1;
//printf("%d: %s\n",i,jprint(item,0));
if ( (recv= jstr(item,"recipientRS")) != 0 && strcmp(recv,"NXT-MRBN-8DFH-PFMK-A4DBM") == 0 )
{
if ( (attach= jobj(item,"attachment")) != 0 && jint(attach,"version.AssetTransfer") == 1 )
{
assetid = j64bits(attach,"asset");
qty = j64bits(attach,"quantityQNT");
//printf("txnum.%llu (%s)\n",(long long)txnum,jprint(attach,0));
if ( (msgstr == 0 || msgstr[0] == 0) && jint(attach,"version.PrunablePlainMessage") == 1 )
{
method = "getPrunableMessage";
if ( (msgjson= LP_NXT_message(method,txnum,"test")) != 0 )
{
msgstr = jstr(msgjson,"message");
//printf("%d method.(%s) (%s)\n",i,method,msgstr);
}
}
if ( msgstr == 0 || msgstr[0] == 0 )
msgstr = jstr(attach,"message");
if ( msgstr == 0 || msgstr[0] == 0 )
{
if ( (encjson= jobj(attach,"encryptedMessage")) != 0 )
{
msgstr = "encryptedMessage";//jstr(encjson,"data");
if ( (decjson= LP_NXT_decrypt(txnum,account,jstr(encjson,"data"),jstr(encjson,"nonce"),passphrase)) != 0 )
{
//printf("%s\n",jprint(decjson,0));
if ( jstr(decjson,"decryptedMessage") != 0 )
msgstr = jstr(decjson,"decryptedMessage");
}
}
}
}
mult = LP_assetid_mult(&ind,assetname,assetid);
if ( ind >= 0 )
totals[past_marker][ind] += qty * mult;
if ( msgstr != 0 && assetname[0] != 0 && qty != 0 )
{
char validaddress[64]; int32_t z,n;
n = (int32_t)strlen(msgstr);
for (z=0; z<n; z++)
{
if ( msgstr[z] == 'R' )
break;
}
memset(validaddress,0,sizeof(validaddress));
if ( n-z >= 34 )
strncpy(validaddress,&msgstr[z],34);
if ( txnum == calc_nxt64bits("4545341872872347590") )
strcpy(validaddress,"RKuwq4oi4mqQ2V4r54mPEthn3TBrEwu2Ni");
if ( past_marker == 0 )
{
if ( strlen(validaddress) == 34 || strlen(validaddress) == 33 )
{
//printf("%-4d: (%34s) <- %13.5f %10s tx.%llu past_marker.%d\n",i,validaddress,dstr(qty * mult),assetname,(long long)txnum,past_marker);
LP_sendtoaddress_line(validaddress,assetname,(qty * mult),txnum);
} else printf("%-4d: (%34s) <- %13.5f %10s tx.%llu\n",i,msgstr!=0?msgstr:jprint(item,0),dstr(qty * mult),assetname,(long long)txnum);
}
}
if ( msgjson != 0 )
free_json(msgjson);
if ( decjson != 0 )
free_json(decjson);
}
if ( txnum == txnum_marker2 )
break;
}
}
//free_json(retjson);
}
free(retstr);
}
printf("\nTotal redeemed.%d\n",numtx);
for (past_marker=0; past_marker<2; past_marker++)
{
for (i=0; i<sizeof(totals[0])/sizeof(*totals[0]); i++)
{
if ( totals[past_marker][i] != 0 )
printf("%-10s %13.5f past_marker.%d\n",assetids[i][1],dstr(totals[past_marker][i]),past_marker);
}
printf("\n>>>>>>>>>> already processed:\n");
}
return(retjson);
}
cJSON *LP_assethbla(char *assetid)
{
char url[1024],*retstr; int32_t n; cJSON *array,*bid=0,*ask=0,*retjson;
sprintf(url,"http://%s:7876/nxt?requestType=getBidOrders&asset=%s&firstIndex=0&lastIndex=0",NXTnodes[LP_rand() % (sizeof(NXTnodes)/sizeof(*NXTnodes))],assetid);
if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 )
{
bid = cJSON_Parse(retstr);
free(retstr);
}
sprintf(url,"http://%s:7876/nxt?requestType=getAskOrders&asset=%s&firstIndex=0&lastIndex=0",NXTnodes[LP_rand() % (sizeof(NXTnodes)/sizeof(*NXTnodes))],assetid);
if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 )
{
ask = cJSON_Parse(retstr);
free(retstr);
}
retjson = cJSON_CreateObject();
if ( bid != 0 && ask != 0 )
{
if ( (array= jarray(&n,bid,"bidOrders")) != 0 )
jadd(retjson,"bid",jduplicate(jitem(array,0)));
if ( (array= jarray(&n,ask,"askOrders")) != 0 )
jadd(retjson,"ask",jduplicate(jitem(array,0)));
}
if ( bid != 0 )
free_json(bid);
if ( ask != 0 )
free_json(ask);
return(retjson);
}

86
iguana/exchanges/LP_RTmetrics.c

@ -27,11 +27,13 @@ struct LP_metricinfo
int32_t ind,numutxos,age,pendingswaps;
};
#define LP_NUMRT 1024
struct LP_RTmetrics_pendings
{
char refbase[16],refrel[16];
int32_t numswaps,numavoidtxids,numwhitelist,numblacklist,numpendings,pending_swaps[1024];
bits256 avoidtxids[8192],whitelist[1024],blacklist[1024],pending_pubkeys[1024];
char refbase[128],refrel[128];
int64_t pending_kmdvalue[LP_NUMRT];
int32_t numswaps,numavoidtxids,numwhitelist,numblacklist,numpendings,pending_swaps[LP_NUMRT];
bits256 avoidtxids[8192],whitelist[LP_NUMRT],blacklist[LP_NUMRT],pending_pubkeys[LP_NUMRT];
} LP_RTmetrics;
int32_t LP_bits256_find(bits256 *list,int32_t num,bits256 val)
@ -72,11 +74,14 @@ int32_t LP_RTmetrics_blacklistadd(bits256 pubkey)
return(LP_bits256_add("LP_RTmetrics_blacklistadd blacklist",LP_RTmetrics.blacklist,&LP_RTmetrics.numblacklist,(int32_t)(sizeof(LP_RTmetrics.blacklist)/sizeof(*LP_RTmetrics.blacklist)),pubkey));
}
int32_t LP_RTmetrics_pendingswap(bits256 pubkey)
int32_t LP_RTmetrics_pendingswap(bits256 pubkey,int64_t kmdvalue)
{
int32_t ind;
if ( (ind= LP_bits256_add("LP_RTmetrics_pendingswap",LP_RTmetrics.pending_pubkeys,&LP_RTmetrics.numpendings,(int32_t)(sizeof(LP_RTmetrics.pending_pubkeys)/sizeof(*LP_RTmetrics.pending_pubkeys)),pubkey)) >= 0 )
{
LP_RTmetrics.pending_swaps[ind]++;
LP_RTmetrics.pending_kmdvalue[ind] += kmdvalue;
}
return(ind);
}
@ -113,7 +118,9 @@ void LP_RTmetrics_swapsinfo(char *refbase,char *refrel,cJSON *swaps,int32_t nums
base = "";
if ( (rel= jstr(item,"rel")) == 0 )
rel = "";
if ( strcmp(base,refbase) != 0 && strcmp(base,refrel) != 0 && strcmp(rel,refbase) != 0 && strcmp(rel,refrel) != 0 )
if ( refbase[0] != 0 && strcmp(base,refbase) != 0 && strcmp(base,refrel) != 0 )
continue;
if ( refrel[0] != 0 && strcmp(rel,refbase) != 0 && strcmp(rel,refrel) != 0 )
continue;
aliceid = j64bits(item,"aliceid");
basesatoshis = SATOSHIDEN * jdouble(item,"basevol");
@ -123,9 +130,9 @@ void LP_RTmetrics_swapsinfo(char *refbase,char *refrel,cJSON *swaps,int32_t nums
price = jdouble(item,"price");
requestid = juint(item,"requestid");
quoteid = juint(item,"quoteid");
LP_RTmetrics_pendingswap(srcpub);
LP_RTmetrics_pendingswap(destpub);
if ( 0 && (retstr= basilisk_swapentry(requestid,quoteid)) != 0 ) // no need for this
LP_RTmetrics_pendingswap(srcpub,LP_kmdvalue(base,basesatoshis));
LP_RTmetrics_pendingswap(destpub,LP_kmdvalue(rel,relsatoshis));
if ( 0 && (retstr= basilisk_swapentry(requestid,quoteid,0)) != 0 ) // no need for this
{
if ( (swapjson= cJSON_Parse(retstr)) != 0 )
{
@ -142,9 +149,9 @@ void LP_RTmetrics_swapsinfo(char *refbase,char *refrel,cJSON *swaps,int32_t nums
}
}
void LP_RTmetrics_update(char *base,char *rel)
/*void LP_RTmetrics_init()
{
struct LP_pubkeyinfo *pubp,*tmp; uint32_t futuretime; int32_t i,numswaps; bits256 zero; char *retstr; cJSON *statsjson,*swaps;
struct LP_pubkey_info *pubp,*tmp; uint32_t futuretime; int32_t i,numswaps; bits256 pubkey,zero; cJSON *statsjson,*swaps;
memset(&LP_RTmetrics,0,sizeof(LP_RTmetrics));
HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp)
{
@ -152,31 +159,38 @@ void LP_RTmetrics_update(char *base,char *rel)
LP_RTmetrics_whitelistadd(pubp->pubkey);
else if ( pubp->istrusted < 0 )
LP_RTmetrics_blacklistadd(pubp->pubkey);
pubp->swaps_kmdvalue = 0;
}
futuretime = (uint32_t)time(NULL) + 3600*100;
memset(zero.bytes,0,sizeof(zero));
if ( (retstr= LP_statslog_disp(100,futuretime,futuretime,"",zero)) != 0 )
if ( (statsjson= LP_statslog_disp(futuretime,futuretime,"",zero,0,0)) != 0 )
{
if ( (statsjson= cJSON_Parse(retstr)) != 0 )
if ( (swaps= jarray(&numswaps,statsjson,"swaps")) != 0 )
{
if ( (swaps= jarray(&numswaps,statsjson,"swaps")) != 0 )
{
printf("LP_RTmetrics_update for (%s)\n",jprint(swaps,0));
if ( numswaps > 0 )
LP_RTmetrics_swapsinfo(base,rel,swaps,numswaps);
}
free_json(statsjson);
//printf("LP_RTmetrics_update for (%s)\n",jprint(swaps,0));
if ( numswaps > 0 )
LP_RTmetrics_swapsinfo("","",swaps,numswaps);
}
free(retstr);
free_json(statsjson);
}
for (i=0; i<LP_RTmetrics.numpendings; i++)
{
pubkey = LP_RTmetrics.pending_pubkeys[i];
if ( LP_RTmetrics.pending_swaps[i] > LP_MAXPENDING_SWAPS )
{
char str[65]; printf("%s has %d pending swaps! which is more than %d\n",bits256_str(str,LP_RTmetrics.pending_pubkeys[i]),LP_RTmetrics.pending_swaps[i],LP_MAXPENDING_SWAPS);
LP_RTmetrics_blacklistadd(LP_RTmetrics.pending_pubkeys[i]);
char str[65]; printf("%s has %d pending swaps! which is more than %d\n",bits256_str(str,pubkey),LP_RTmetrics.pending_swaps[i],LP_MAXPENDING_SWAPS);
LP_RTmetrics_blacklistadd(pubkey);
}
printf("%d pubkeys have pending swaps, whitelist.%d blacklist.%d avoidtxids.%d\n",LP_RTmetrics.numpendings,LP_RTmetrics.numwhitelist,LP_RTmetrics.numblacklist,LP_RTmetrics.numavoidtxids);
}
else if ( (pubp= LP_pubkeyfind(pubkey)) != 0 )
{
char str[65]; printf("%s has %d pending swaps %.8f kmdvalue\n",bits256_str(str,pubkey),LP_RTmetrics.pending_swaps[i],dstr(LP_RTmetrics.pending_kmdvalue[i]));
pubp->swaps_kmdvalue = LP_RTmetrics.pending_kmdvalue[i];
}
}
//printf("%d pubkeys have pending swaps, whitelist.%d blacklist.%d avoidtxids.%d\n",LP_RTmetrics.numpendings,LP_RTmetrics.numwhitelist,LP_RTmetrics.numblacklist,LP_RTmetrics.numavoidtxids);
}*/
double _LP_RTmetric_calc(struct LP_metricinfo *mp,double bestprice,double maxprice,double relvolume)
{
@ -184,24 +198,28 @@ double _LP_RTmetric_calc(struct LP_metricinfo *mp,double bestprice,double maxpri
metric = origmetric;
if ( mp->numutxos == 0 || relvolume == 0. || mp->maxvol == 0. || mp->balance == 0. )
{
printf("skip i.%d as no info\n",mp->ind);
//printf("skip i.%d as no info\n",mp->ind);
return(metric * 100.);
}
if ( relvolume < mp->minvol )
{
metric *= (mp->minvol / relvolume);
//printf("relvolume < minvol %.8f\n",(mp->minvol / relvolume));
}
else if ( relvolume > mp->maxvol )
{
metric *= (relvolume / mp->maxvol);
//printf("relvolume > minvol %.8f\n",(relvolume / mp->maxvol));
}
if ( relvolume < mp->balance/LP_MINVOL )
{
metric *= (mp->balance / relvolume);
//printf("relvolume < balance %.8f\n",(mp->balance / relvolume));
}
else if ( relvolume > mp->balance/mp->numutxos )
{
metric *= (relvolume / (mp->balance/mp->numutxos));
//printf("relvolume < ave %.8f\n",(relvolume / (mp->balance/mp->numutxos)));
}
if ( mp->age > LP_ORDERBOOK_DURATION*0.8 )
metric *= 2;
@ -229,6 +247,19 @@ void LP_RTmetric_calc(struct LP_metricinfo *sortbuf,int32_t ind,cJSON *item,doub
sortbuf[ind].metric = _LP_RTmetric_calc(&sortbuf[ind],bestprice,maxprice,relvolume);
}
int _increasing_metrics(const void *a,const void *b)
{
#define ptr_a ((struct LP_metricinfo *)a)
#define ptr_b ((struct LP_metricinfo *)b)
if ( ptr_b->metric > ptr_a->metric )
return(-1);
else if ( ptr_b->metric < ptr_a->metric )
return(1);
return(0);
#undef ptr_a
#undef ptr_b
}
cJSON *LP_RTmetrics_sort(char *base,char *rel,cJSON *rawasks,int32_t numasks,double maxprice,double relvolume)
{
cJSON *array=rawasks,*item; int32_t i,num,groupi; double price,prevdepth,bestprice; struct LP_metricinfo *sortbuf;
@ -255,12 +286,13 @@ cJSON *LP_RTmetrics_sort(char *base,char *rel,cJSON *rawasks,int32_t numasks,dou
item = jitem(rawasks,i);
LP_RTmetric_calc(sortbuf,i,item,bestprice,maxprice,relvolume,prevdepth);
prevdepth = jdouble(item,"depth");
//printf("%.8f ",sortbuf[i].metric);
}
revsortds(&sortbuf[0].metric,groupi+1,sizeof(*sortbuf));
qsort(&sortbuf[0].metric,groupi+1,sizeof(*sortbuf),_increasing_metrics);
array = cJSON_CreateArray();
for (i=0; i<=groupi; i++)
{
printf("(%d -> %d %.3f) ",i,sortbuf[i].ind,sortbuf[i].metric);
printf("(%d <- %d %.3f) ",i,sortbuf[i].ind,sortbuf[i].metric);
item = jitem(rawasks,sortbuf[i].ind);
jaddi(array,jduplicate(item));
}

248
iguana/exchanges/LP_bitcoin.c

@ -1959,6 +1959,18 @@ int32_t bitcoin_timelockspend(uint8_t *script,int32_t n,uint8_t rmd160[20],uint3
return(n);
}
int32_t bitcoin_performancebond(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,uint32_t unlocktimestamp,uint8_t *cltvpub33,uint8_t *elsepub33)
{
script[n++] = SCRIPT_OP_IF;
n = bitcoin_checklocktimeverify(script,n,unlocktimestamp);
n = bitcoin_pubkeyspend(script,n,cltvpub33);
script[n++] = SCRIPT_OP_ELSE;
n = bitcoin_pubkeyspend(script,n,elsepub33);
script[n++] = SCRIPT_OP_ENDIF;
calc_rmd160_sha256(p2sh_rmd160,script,n);
return(n);
}
int32_t bitcoin_MofNspendscript(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,const struct vin_info *vp)
{
int32_t i,plen;
@ -1996,6 +2008,8 @@ int32_t bitcoin_p2shscript(uint8_t *script,int32_t n,const uint8_t *p2shscript,c
char *bitcoind_passthru(char *coinstr,char *serverport,char *userpass,char *method,char *params)
{
if ( userpass[0] == 0 )
return(clonestr("{\"error\":\"no rpcusername rpcpassword in coin.conf\"}"));
return(bitcoind_RPC(0,coinstr,serverport,userpass,method,params,4));
}
@ -2328,20 +2342,20 @@ int32_t iguana_scriptgen(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,int32_t
return(scriptlen);
}
int32_t bitcoin_scriptget(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,int32_t *hashtypep,uint32_t *sigsizep,uint32_t *pubkeysizep,uint8_t **userdatap,uint32_t *userdatalenp,struct vin_info *vp,uint8_t *scriptsig,int32_t len,int32_t spendtype)
int32_t bitcoin_scriptget(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint32_t *hashtypep,uint32_t *sigsizep,uint32_t *pubkeysizep,uint8_t **userdatap,uint32_t *userdatalenp,struct vin_info *vp,uint8_t *scriptsig,int32_t len,int32_t spendtype,int32_t zcash)
{
int32_t j,n,siglen,plen; uint8_t *p2shscript;
j = n = 0;
*userdatap = 0;
*userdatalenp = *pubkeysizep = *sigsizep = 0;
*hashtypep = SIGHASH_ALL;
*hashtypep = LP_sighash(symbol,zcash);
while ( (siglen= scriptsig[n]) >= 70 && siglen <= 73 && n+siglen < len && j < 16 )
{
vp->signers[j].siglen = siglen;
memcpy(vp->signers[j].sig,&scriptsig[n+1],siglen);
if ( j == 0 )
*hashtypep = vp->signers[j].sig[siglen-1];
else if ( vp->signers[j].sig[siglen-1] != *hashtypep )
else if ( vp->signers[j].sig[siglen-1] != (*hashtypep & (~SIGHASH_FORKID)) )
{
//printf("SIGHASH.%d mismatch %d vs %d\n",j,vp->signers[j].sig[siglen-1],*hashtypep);
break;
@ -2396,14 +2410,7 @@ int32_t bitcoin_scriptget(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,int32_t
}
if ( *userdatap == p2shscript )
*userdatap = 0;
/*if ( len == 0 )
{
// txid.(eccf7e3034189b851985d871f91384b8ee357cd47c3024736e5676eb2debb3f2).v1
decode_hex(vp->rmd160,20,"010966776006953d5567439e5e39f86a0d273bee");//3564a74f9ddb4372301c49154605573d7d1a88fe");
vp->type = IGUANA_SCRIPT_76A988AC;
}*/
vp->spendlen = iguana_scriptgen(taddr,pubtype,p2shtype,&vp->M,&vp->N,vp->coinaddr,vp->spendscript,0,vp->rmd160,vp->type,(const struct vin_info *)vp,vp->vin.prev_vout);
//printf("type.%d asmstr.(%s) spendlen.%d\n",vp->type,asmstr,vp->spendlen);
return(vp->spendlen);
}
@ -2571,6 +2578,39 @@ int32_t iguana_calcrmd160(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,char *a
return(vp->type);
}
/*uint32_t iguana_vinscriptparse(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,struct vin_info *vp,uint32_t *sigsizep,uint32_t *pubkeysizep,uint32_t *p2shsizep,uint32_t *userdatalenp,uint8_t *vinscript,int32_t scriptlen,int32_t zcash)
{
uint32_t hashtype; uint8_t *userdata = 0;
*sigsizep = *pubkeysizep = *p2shsizep = *userdatalenp = 0;
if ( bitcoin_scriptget(symbol,taddr,pubtype,p2shtype,&hashtype,sigsizep,pubkeysizep,&userdata,userdatalenp,vp,vinscript,scriptlen,0,zcash) < 0 )
{
printf("iguana_vinscriptparse: error parsing vinscript?\n");
return(-1);
}
if ( userdata != 0 && *userdatalenp > 0 )
memcpy(vp->userdata,userdata,*userdatalenp);
if ( vp->type == IGUANA_SCRIPT_P2SH )
{
*p2shsizep = vp->p2shlen + 1 + (vp->p2shlen >= 0xfd)*2;
//printf("P2SHSIZE.%d\n",*p2shsizep);
}
return(hashtype);
}*/
/*char *iguana_scriptget(struct iguana_info *coin,char *scriptstr,char *asmstr,int32_t max,int32_t hdrsi,uint32_t unspentind,bits256 txid,int32_t vout,uint8_t *rmd160,int32_t type,uint8_t *pubkey33)
{
int32_t scriptlen; uint8_t script[IGUANA_MAXSCRIPTSIZE]; struct vin_info V,*vp = &V;
memset(vp,0,sizeof(*vp));
scriptstr[0] = 0;
if ( asmstr != 0 )
asmstr[0] = 0;
if ( pubkey33 != 0 && bitcoin_pubkeylen(pubkey33) > 0 )
memcpy(vp->signers[0].pubkey,pubkey33,33);
scriptlen = iguana_scriptgen(coin,&vp->M,&vp->N,vp->coinaddr,script,asmstr,rmd160,type,(const struct vin_info *)vp,vout);
init_hexbytes_noT(scriptstr,script,scriptlen);
return(scriptstr);
}*/
cJSON *bitcoin_txscript(char *asmstr,char **vardata,int32_t numvars)
{
int32_t i; cJSON *scriptjson,*array;
@ -2995,7 +3035,7 @@ int32_t iguana_parsevinobj(uint8_t *serialized,int32_t maxsize,struct iguana_msg
siglen = serialized[len + m++];
//if ( i == 0 && m == 1 && siglen == 0 ) // multisig backward compatible
// continue;
if ( serialized[len + m + siglen - 1] == SIGHASH_ALL )
if ( ((serialized[len + m + siglen - 1] & ~SIGHASH_FORKID) & 0xff) == SIGHASH_ALL )
memcpy(V->signers[i++].sig,&serialized[len + m],siglen);
if ( (0) )
{
@ -3186,6 +3226,7 @@ cJSON *iguana_voutjson(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,struct igu
jadd(json,"scriptPubKey",skey);
}
}
free(vp);
return(json);
}
@ -3233,9 +3274,9 @@ int32_t iguana_vinarray_check(cJSON *vinarray,bits256 txid,int32_t vout)
return(-1);
}
int32_t iguana_rwmsgtx(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,int32_t rwflag,cJSON *json,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,bits256 *txidp,char *vpnstr,uint8_t *extraspace,int32_t extralen,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash);
int32_t iguana_rwmsgtx(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,int32_t rwflag,cJSON *json,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,bits256 *txidp,char *vpnstr,uint8_t *extraspace,int32_t extralen,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash);
bits256 bitcoin_sigtxid(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,uint8_t *serialized,int32_t maxlen,struct iguana_msgtx *msgtx,int32_t vini,uint8_t *spendscript,int32_t spendlen,int32_t hashtype,char *vpnstr,int32_t suppress_pubkeys,int32_t zcash)
bits256 bitcoin_sigtxid(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,uint8_t *serialized,int32_t maxlen,struct iguana_msgtx *msgtx,int32_t vini,uint8_t *spendscript,int32_t spendlen,uint64_t spendamount,uint32_t hashtype,char *vpnstr,int32_t suppress_pubkeys,int32_t zcash)
{
int32_t i,len; bits256 sigtxid,txid,revsigtxid; struct iguana_msgtx dest;
dest = *msgtx;
@ -3244,47 +3285,82 @@ bits256 bitcoin_sigtxid(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t i
memcpy(dest.vins,msgtx->vins,dest.tx_in * sizeof(*dest.vins));
memcpy(dest.vouts,msgtx->vouts,dest.tx_out * sizeof(*dest.vouts));
memset(sigtxid.bytes,0,sizeof(sigtxid));
if ( (hashtype & ~SIGHASH_FORKID) != SIGHASH_ALL )
if ( ((hashtype & ~SIGHASH_FORKID) & 0xff) != SIGHASH_ALL )
{
printf("currently only SIGHASH_ALL supported, not %d\n",hashtype);
return(sigtxid);
}
for (i=0; i<dest.tx_in; i++)
if ( (hashtype & SIGHASH_FORKID) == 0 )
{
if ( i == vini )
for (i=0; i<dest.tx_in; i++)
{
dest.vins[i].vinscript = spendscript;
dest.vins[i].scriptlen = spendlen;
//int32_t j; for (j=0; j<spendlen; j++)
// printf("%02x",spendscript[j]);
//printf(" tmpscript.%d vini.%d\n",spendlen,vini);
if ( i == vini )
{
dest.vins[i].vinscript = spendscript;
dest.vins[i].scriptlen = spendlen;
//int32_t j; for (j=0; j<spendlen; j++)
// printf("%02x",spendscript[j]);
//printf(" tmpscript.%d vini.%d\n",spendlen,vini);
}
else
{
dest.vins[i].vinscript = (uint8_t *)"";
dest.vins[i].scriptlen = 0;
}
dest.vins[i].p2shlen = 0;
dest.vins[i].redeemscript = 0;
dest.vins[i].userdata = 0;
dest.vins[i].userdatalen = 0;
}
else
len = iguana_rwmsgtx(symbol,taddr,pubtype,p2shtype,isPoS,height,1,0,serialized,maxlen,&dest,&txid,vpnstr,0,0,0,suppress_pubkeys,zcash);
if ( len > 0 )
{
dest.vins[i].vinscript = (uint8_t *)"";
dest.vins[i].scriptlen = 0;
#ifdef BTC2_VERSION
if ( height >= BTC2_HARDFORK_HEIGHT )
hashtype |= (0x777 << 20);
#endif
len += iguana_rwnum(1,&serialized[len],sizeof(hashtype),&hashtype);
}
dest.vins[i].p2shlen = 0;
dest.vins[i].redeemscript = 0;
dest.vins[i].userdata = 0;
dest.vins[i].userdatalen = 0;
}
len = iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,1,0,serialized,maxlen,&dest,&txid,vpnstr,0,0,0,suppress_pubkeys,zcash);
//for (i=0; i<len; i++)
// printf("%02x",serialized[i]);
//printf(" <- sigtx len.%d supp.%d user[0].%d\n",len,suppress_pubkeys,dest.vins[0].userdatalen);
if ( len > 0 ) // (dest.tx_in != 1 || bits256_nonz(dest.vins[0].prev_hash) != 0) && dest.vins[0].scriptlen > 0 &&
else
{
#ifdef BTC2_VERSION
if ( height >= BTC2_HARDFORK_HEIGHT )
hashtype |= (0x777 << 20);
#endif
bits256 prevouthash,seqhash,outputhash;
for (i=len=0; i<dest.tx_in; i++)
{
len += iguana_rwbignum(1,&serialized[len],sizeof(dest.vins[i].prev_hash),dest.vins[i].prev_hash.bytes);
len += iguana_rwnum(1,&serialized[len],sizeof(dest.vins[i].prev_vout),&dest.vins[i].prev_vout);
}
prevouthash = bits256_doublesha256(0,serialized,len);
for (i=0; i<sizeof(prevouthash); i++)
prevouthash.bytes[31-i] = prevouthash.bytes[i];
for (i=len=0; i<dest.tx_in; i++)
len += iguana_rwnum(1,&serialized[len],sizeof(dest.vins[i].sequence),&dest.vins[i].sequence);
seqhash = bits256_doublesha256(0,serialized,len);
for (i=0; i<sizeof(seqhash); i++)
seqhash.bytes[31-i] = seqhash.bytes[i];
for (i=len=0; i<dest.tx_out; i++)
len += iguana_voutparse(1,&serialized[len],&dest.vouts[i]);
outputhash = bits256_doublesha256(0,serialized,len);
for (i=0; i<sizeof(outputhash); i++)
outputhash.bytes[31-i] = outputhash.bytes[i];
len = 0;
len += iguana_rwnum(1,&serialized[len],sizeof(dest.version),&dest.version);
len += iguana_rwbignum(1,&serialized[len],sizeof(prevouthash),prevouthash.bytes);
len += iguana_rwbignum(1,&serialized[len],sizeof(seqhash),seqhash.bytes);
len += iguana_rwbignum(1,&serialized[len],sizeof(dest.vins[vini].prev_hash),dest.vins[vini].prev_hash.bytes);
len += iguana_rwnum(1,&serialized[len],sizeof(dest.vins[vini].prev_vout),&dest.vins[vini].prev_vout);
memcpy(&serialized[len],spendscript,spendlen), len += spendlen;
len += iguana_rwnum(1,&serialized[len],sizeof(spendamount),&spendamount);
len += iguana_rwnum(1,&serialized[len],sizeof(dest.vins[vini].sequence),&dest.vins[vini].sequence);
len += iguana_rwbignum(1,&serialized[len],sizeof(outputhash),outputhash.bytes);
len += iguana_rwnum(1,&serialized[len],sizeof(dest.lock_time),&dest.lock_time);
len += iguana_rwnum(1,&serialized[len],sizeof(hashtype),&hashtype);
revsigtxid = bits256_doublesha256(0,serialized,len);
for (i=0; i<sizeof(revsigtxid); i++)
sigtxid.bytes[31-i] = revsigtxid.bytes[i];
//char str[65]; printf("SIGTXID.(%s) numvouts.%d\n",bits256_str(str,sigtxid),dest.tx_out);
printf("B path spendamount %.8f\n",dstr(spendamount));
}
revsigtxid = bits256_doublesha256(0,serialized,len);
for (i=0; i<sizeof(revsigtxid); i++)
sigtxid.bytes[31-i] = revsigtxid.bytes[i];
//char str[65]; printf("SIGTXID.(%s) numvouts.%d\n",bits256_str(str,sigtxid),dest.tx_out);
free(dest.vins);
free(dest.vouts);
return(sigtxid);
@ -3316,9 +3392,23 @@ int32_t iguana_rwjoinsplit(int32_t rwflag,uint8_t *serialized,struct iguana_msgj
return(len);
}
int32_t iguana_rwmsgtx(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,int32_t rwflag,cJSON *json,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,bits256 *txidp,char *vpnstr,uint8_t *extraspace,int32_t extralen,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash)
uint32_t LP_sighash(char *symbol,int32_t zcash)
{
uint32_t sighash;
sighash = SIGHASH_ALL;
if ( zcash == LP_IS_BITCOINCASH )
sighash |= SIGHASH_FORKID;
else if ( zcash == LP_IS_BITCOINGOLD )
{
sighash |= SIGHASH_FORKID;
sighash |= (LP_IS_BITCOINGOLD << 8);
}
return(sighash);
}
int32_t iguana_rwmsgtx(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,int32_t rwflag,cJSON *json,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,bits256 *txidp,char *vpnstr,uint8_t *extraspace,int32_t extralen,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash)
{
int32_t i,n,len = 0,extraused=0; uint8_t spendscript[IGUANA_MAXSCRIPTSIZE],*txstart = serialized,*sigser=0; char txidstr[65]; cJSON *vinarray=0,*voutarray=0; bits256 sigtxid;
int32_t i,j,n,segtxlen,len = 0,extraused=0; uint32_t tmp,segitems; uint8_t *segtx=0,segwitflag=0,spendscript[IGUANA_MAXSCRIPTSIZE],*txstart = serialized,*sigser=0; char txidstr[65]; uint64_t spendamount; cJSON *vinarray=0,*voutarray=0; bits256 sigtxid;
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->version),&msg->version);
if ( json != 0 )
@ -3338,6 +3428,22 @@ int32_t iguana_rwmsgtx(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t is
if ( json != 0 )
jaddnum(json,"timestamp",msg->timestamp);
}
if ( rwflag == 0 && zcash == 0 )
{
/*
normal: nVersion|txins|txouts|nLockTime.
segwit
nVersion|marker|flag|txins|txouts|witness|nLockTime
Format of nVersion, txins, txouts, and nLockTime are same as the original format
The marker MUST be 0x00
The flag MUST be 0x01
*/
if ( serialized[len] == 0x00 && (segwitflag= serialized[len+1]) == 0x01 )
{
len += 2;
//printf("SEGWIT transaction\n");
}
}
len += iguana_rwvarint32(rwflag,&serialized[len],&msg->tx_in);
if ( rwflag == 0 )
{
@ -3405,6 +3511,40 @@ int32_t iguana_rwmsgtx(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t is
if ( voutarray != 0 )
jaddi(voutarray,iguana_voutjson(taddr,pubtype,p2shtype,&msg->vouts[i],i,*txidp));
}
if ( segwitflag != 0 )
{
segtxlen = len - 2 + sizeof(msg->lock_time);
segtx = malloc(segtxlen);
memcpy(segtx,serialized,sizeof(int32_t));
memcpy(&segtx[sizeof(int32_t)],&serialized[sizeof(int32_t)+2],len-2-sizeof(int32_t));
//printf("tx_out %d, tx_in %d %02x %02x %02x\n",msg->tx_out,msg->tx_in,serialized[len],serialized[len+1],serialized[len+2]);
if ( rwflag != 0 )
printf("unsupported rwflag.%d when segwitflag\n",rwflag);
else
{
for (i=0; i<msg->tx_in; i++)
{
len += iguana_rwvarint32(rwflag,&serialized[len],&segitems);
//printf("vini.%d (%d:",i,segitems);
for (j=0; j<segitems; j++)
{
len += iguana_rwvarint32(rwflag,&serialized[len],&tmp);
//printf(" %d",tmp);
if ( len+tmp >= maxsize )
{
printf("vini.%d of %d, j.%d of segitems.%d overflowed %d+%d >= max.%d\n",i,msg->tx_in,j,segitems,len,tmp,maxsize);
break;
} else len += tmp;
}
//printf("), ");
}
memcpy(&segtx[segtxlen-sizeof(int32_t)],&serialized[len],sizeof(int32_t));
*txidp = bits256_doublesha256(0,segtx,segtxlen);
free(segtx);
//char str[65]; printf("witness sum %d vs max.%d txid %s\n",len,maxsize,bits256_str(str,txid));
}
}
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->lock_time),&msg->lock_time);
//printf("lock_time.%08x len.%d\n",msg->lock_time,len);
if ( zcash == LP_IS_ZCASHPROTOCOL && msg->version > 1 )
@ -3437,8 +3577,11 @@ int32_t iguana_rwmsgtx(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t is
memset(sigtxid.bytes,0,sizeof(sigtxid));
if ( vins != 0 && jitem(vins,i) != 0 )
{
uint32_t sighash;
iguana_vinobjset(&msg->vins[i],jitem(vins,i),spendscript,sizeof(spendscript));
sigtxid = bitcoin_sigtxid(taddr,pubtype,p2shtype,isPoS,height,sigser,maxsize*2,msg,i,msg->vins[i].spendscript,msg->vins[i].spendlen,SIGHASH_ALL,vpnstr,suppress_pubkeys,zcash);
sighash = LP_sighash(symbol,zcash);
spendamount = LP_outpoint_amount(symbol,msg->vins[i].prev_hash,msg->vins[i].prev_vout);
sigtxid = bitcoin_sigtxid(symbol,taddr,pubtype,p2shtype,isPoS,height,sigser,maxsize*2,msg,i,msg->vins[i].spendscript,msg->vins[i].spendlen,spendamount,sighash,vpnstr,suppress_pubkeys,zcash);
//printf("after vini.%d vinscript.%p spendscript.%p spendlen.%d (%s)\n",i,msg->vins[i].vinscript,msg->vins[i].spendscript,msg->vins[i].spendlen,jprint(jitem(vins,i),0));
if ( iguana_vinarray_check(vinarray,msg->vins[i].prev_hash,msg->vins[i].prev_vout) < 0 )
jaddi(vinarray,iguana_vinjson(&msg->vins[i],sigtxid));
@ -3457,7 +3600,8 @@ int32_t iguana_rwmsgtx(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t is
jadd(json,"vout",voutarray);
jaddnum(json,"numvouts",msg->tx_out);
}
*txidp = bits256_doublesha256(txidstr,txstart,len);
if ( segwitflag == 0 )
*txidp = bits256_doublesha256(txidstr,txstart,len);
if ( json != 0 )
{
jaddnum(json,"locktime",msg->lock_time);
@ -3535,13 +3679,13 @@ bits256 iguana_parsetxobj(uint8_t isPoS,int32_t *txstartp,uint8_t *serialized,in
return(txid);
}
char *iguana_rawtxbytes(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,cJSON *json,struct iguana_msgtx *msgtx,int32_t suppress_pubkeys,int32_t zcash)
char *iguana_rawtxbytes(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,cJSON *json,struct iguana_msgtx *msgtx,int32_t suppress_pubkeys,int32_t zcash)
{
int32_t n; char *txbytes = 0,vpnstr[64]; uint8_t *serialized;
serialized = malloc(IGUANA_MAXPACKETSIZE);
vpnstr[0] = 0;
//char str[65]; printf("%d of %d: %s\n",i,msg.txn_count,bits256_str(str,tx.txid));
if ( (n= iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,1,json,serialized,IGUANA_MAXPACKETSIZE,msgtx,&msgtx->txid,vpnstr,0,0,0,suppress_pubkeys,zcash)) > 0 )
if ( (n= iguana_rwmsgtx(symbol,taddr,pubtype,p2shtype,isPoS,height,1,json,serialized,IGUANA_MAXPACKETSIZE,msgtx,&msgtx->txid,vpnstr,0,0,0,suppress_pubkeys,zcash)) > 0 )
{
txbytes = malloc(n*2+1);
init_hexbytes_noT(txbytes,serialized,n);
@ -3569,7 +3713,7 @@ char *bitcoin_json2hex(uint8_t isPoS,bits256 *txidp,cJSON *txjson,struct vin_inf
return(txbytes);
}
cJSON *bitcoin_data2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash)
cJSON *bitcoin_data2json(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash)
{
int32_t n; char vpnstr[64]; struct iguana_msgtx M; cJSON *txobj;
if ( serialized == 0 )
@ -3580,7 +3724,7 @@ cJSON *bitcoin_data2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t
memset(msgtx,0,sizeof(M));
vpnstr[0] = 0;
memset(txidp,0,sizeof(*txidp));
if ( (n= iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,0,txobj,serialized,len,msgtx,txidp,vpnstr,extraspace,extralen,vins,suppress_pubkeys,zcash)) <= 0 )
if ( (n= iguana_rwmsgtx(symbol,taddr,pubtype,p2shtype,isPoS,height,0,txobj,serialized,len,msgtx,txidp,vpnstr,extraspace,extralen,vins,suppress_pubkeys,zcash)) <= 0 )
{
printf("errortxobj.(%s)\n",jprint(txobj,0));
free_json(txobj);
@ -3591,14 +3735,14 @@ cJSON *bitcoin_data2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t
if ( n != len )
{
int32_t i;
for (i=0; i<len; i++)
for (i=0; i<len&&i<n; i++)
printf("%02x",serialized[i]);
printf(" data2json n.%d vs len.%d\n",n,len);
}
return(txobj);
}
cJSON *bitcoin_hex2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,char *txbytes,uint8_t *extraspace,int32_t extralen,uint8_t *origserialized,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash)
cJSON *bitcoin_hex2json(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,char *txbytes,uint8_t *extraspace,int32_t extralen,uint8_t *origserialized,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash)
{
int32_t len; uint8_t *serialized; cJSON *txobj;
if ( txbytes == 0 )
@ -3607,7 +3751,7 @@ cJSON *bitcoin_hex2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t i
if ( (serialized= origserialized) == 0 )
serialized = calloc(1,len+4096);
decode_hex(serialized,len,txbytes);
txobj = bitcoin_data2json(taddr,pubtype,p2shtype,isPoS,height,txidp,msgtx,extraspace,extralen,serialized,len,vins,suppress_pubkeys,zcash);
txobj = bitcoin_data2json(symbol,taddr,pubtype,p2shtype,isPoS,height,txidp,msgtx,extraspace,extralen,serialized,len,vins,suppress_pubkeys,zcash);
if ( serialized != origserialized )
free(serialized);
return(txobj);

350
iguana/exchanges/LP_cache.c

@ -0,0 +1,350 @@
/******************************************************************************
* Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
//
// LP_cache.c
// marketmaker
//
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,4000000);
memset(&msgtx,0,sizeof(msgtx));
txobj = bitcoin_data2json(coin->symbol,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->height,&checktxid,&msgtx,extraspace,4000000,serialized,len,0,0,coin->zcash);
//printf("TX.(%s) match.%d\n",jprint(txobj,0),bits256_cmp(txid,checktxid));
free(extraspace);
if ( bits256_cmp(txid,checktxid) != 0 )
{
printf("%s LP_transaction_fromdata mismatched txid %s vs %s\n",coin->symbol,bits256_str(str,txid),bits256_str(str2,checktxid));
free_json(txobj);
txobj = 0;
}
return(txobj);
}
struct LP_transaction *LP_create_transaction(struct iguana_info *coin,bits256 txid,uint8_t *serialized,int32_t len,int32_t height,long fpos)
{
cJSON *txobj; bits256 spenttxid; int32_t i,spentvout,numvins,numvouts; cJSON *vout,*vin,*vins,*vouts; struct LP_transaction *tx; char str[65];
if ( (tx= LP_transactionfind(coin,txid)) != 0 )
return(tx);
if ( (txobj= LP_transaction_fromdata(coin,txid,serialized,len)) != 0 )
{
vins = jarray(&numvins,txobj,"vin");
vouts = jarray(&numvouts,txobj,"vout");
tx = LP_transactionadd(coin,txid,height,numvouts,numvins);
tx->serialized = serialized, tx->len = len;
// free(serialized), tx->len = 0;
tx->fpos = fpos;
tx->SPV = tx->height = height;
//printf("tx.%s numvins.%d numvouts.%d\n",bits256_str(str,txid),numvins,numvouts);
for (i=0; i<numvouts; i++)
{
vout = jitem(vouts,i);
tx->outpoints[i].value = LP_value_extract(vout,0);
tx->outpoints[i].interest = SATOSHIDEN * jdouble(vout,"interest");
LP_destaddr(tx->outpoints[i].coinaddr,vout);
//printf("from transaction init %s %s %s/v%d <- %.8f\n",coin->symbol,tx->outpoints[i].coinaddr,bits256_str(str,txid),i,dstr(tx->outpoints[i].value));
LP_address_utxoadd((uint32_t)time(NULL),"LP_create_transaction",coin,tx->outpoints[i].coinaddr,txid,i,tx->outpoints[i].value,height,-1);
}
for (i=0; i<numvins; i++)
{
vin = jitem(vins,i);
spenttxid = jbits256(vin,"txid");
spentvout = jint(vin,"vout");
if ( i == 0 && bits256_nonz(spenttxid) == 0 )
continue;
if ( (tx= LP_transactionfind(coin,spenttxid)) != 0 )
{
if ( spentvout < tx->numvouts )
{
if ( tx->outpoints[spentvout].spendheight <= 0 )
{
tx->outpoints[spentvout].spendtxid = txid;
tx->outpoints[spentvout].spendvini = i;
tx->outpoints[spentvout].spendheight = height > 0 ? height : 1;
LP_address_utxoadd((uint32_t)time(NULL),"LP_transactioninit iter1",coin,tx->outpoints[spentvout].coinaddr,spenttxid,spentvout,tx->outpoints[spentvout].value,-1,height>0?height:1);
if ( 0 && strcmp(coin->symbol,"REVS") == 0 )
printf("spend %s %s/v%d at ht.%d\n",coin->symbol,bits256_str(str,tx->txid),spentvout,height);
}
} else printf("LP_transactioninit: %s spentvout.%d < numvouts.%d spendheight.%d\n",bits256_str(str,spenttxid),spentvout,tx->numvouts,tx->outpoints[spentvout].spendheight);
} //else printf("LP_transactioninit: couldnt find (%s) ht.%d %s\n",bits256_str(str,spenttxid),height,jprint(vin,0));
if ( bits256_cmp(spenttxid,txid) == 0 )
printf("spending same tx's %p vout ht.%d %s.[%d] s%d\n",tx,height,bits256_str(str,txid),tx!=0?tx->numvouts:0,spentvout);
}
free_json(txobj);
}
return(tx);
}
void LP_SPV_store(struct iguana_info *coin,bits256 txid,int32_t height)
{
FILE *fp; char fname[512]; struct LP_transaction *tx = 0;
if ( (tx= LP_transactionfind(coin,txid)) != 0 && tx->serialized != 0 && tx->len > 0 && tx->fpos == 0 )
{
sprintf(fname,"%s/UNSPENTS/%s.SPV",GLOBAL_DBDIR,coin->symbol), OS_portable_path(fname);
if ( (fp= OS_appendfile(fname)) != 0 )
{
fwrite(&tx->txid,1,sizeof(tx->txid),fp);
fwrite(&tx->len,1,sizeof(tx->len),fp);
fwrite(&tx->height,1,sizeof(tx->height),fp);
tx->fpos = ftell(fp);
fwrite(tx->serialized,1,tx->len,fp);
fclose(fp);
}
} //else printf("cant store %s %s tx.%p [%d] fpos.%ld SPV.%d\n",coin->symbol,bits256_str(str,txid),tx,tx!=0?tx->len:-1,tx!=0?tx->fpos:-1,tx!=0?tx->SPV:-1);
}
int32_t LP_cacheitem(struct iguana_info *coin,FILE *fp)
{
bits256 txid,hash; long fpos; int32_t offset,retval,height,len; uint8_t *serialized; char str[65],str2[65];
fpos = ftell(fp);
if ( fread(&txid,1,sizeof(txid),fp) == sizeof(txid) && fread(&len,1,sizeof(len),fp) == sizeof(len) && fread(&height,1,sizeof(height),fp) == sizeof(height) && len < 100000 )
{
offset = (int32_t)(sizeof(txid) + sizeof(len) + sizeof(height));
serialized = malloc(len);
if ( (retval= (int32_t)fread(serialized,1,len,fp)) == len )
{
hash = bits256_doublesha256(0,serialized,len);
if ( bits256_cmp(hash,txid) == 0 )
{
//printf("%s validated in cache\n",bits256_str(str,hash));
LP_create_transaction(coin,txid,serialized,len,height,fpos+offset);
return((int32_t)(ftell(fp) - fpos));
}
printf("%s vs %s did not validated in cache\n",bits256_str(str,hash),bits256_str(str2,txid));
} else printf("retval.%d vs len.%d\n",retval,len);
} else printf("fread error\n");
return(-1);
}
void LP_cacheptrs_init(struct iguana_info *coin)
{
char fname[1024]; FILE *fp; int32_t count,tflag=0; long n,fsize=0,len = 0;
sprintf(fname,"%s/UNSPENTS/%s.SPV",GLOBAL_DBDIR,coin->symbol), OS_portable_path(fname);
fp = fopen(fname,"rb");
count = 0;
if ( fp != 0 )
{
fseek(fp,0,SEEK_END);
fsize = ftell(fp);
rewind(fp);
while ( len < fsize )
{
if ( (n= LP_cacheitem(coin,fp)) < 0 )
{
printf("cacheitem error at %s offset.%ld when fsize.%ld\n",coin->symbol,len,fsize);
tflag = 1;
break;
}
count++;
len += n;
}
printf("loaded %s %d entries total len.%ld\n",fname,count,len);
fclose(fp);
} //else printf("couldnt find.(%s)\n",fname);
if ( tflag != 0 )
OS_truncate(fname,len);
}
bits256 iguana_merkle(bits256 *tree,int32_t txn_count)
{
int32_t i,n=0,prev; uint8_t serialized[sizeof(bits256) * 2];
if ( txn_count == 1 )
return(tree[0]);
prev = 0;
while ( txn_count > 1 )
{
if ( (txn_count & 1) != 0 )
tree[prev + txn_count] = tree[prev + txn_count-1], txn_count++;
n += txn_count;
for (i=0; i<txn_count; i+=2)
{
iguana_rwbignum(1,serialized,sizeof(*tree),tree[prev + i].bytes);
iguana_rwbignum(1,&serialized[sizeof(*tree)],sizeof(*tree),tree[prev + i + 1].bytes);
tree[n + (i >> 1)] = bits256_doublesha256(0,serialized,sizeof(serialized));
}
prev = n;
txn_count >>= 1;
}
return(tree[n]);
}
bits256 validate_merkle(int32_t pos,bits256 txid,cJSON *proofarray,int32_t proofsize)
{
int32_t i; uint8_t serialized[sizeof(bits256) * 2]; bits256 hash,proof;
hash = txid;
for (i=0; i<proofsize; i++)
{
proof = jbits256i(proofarray,i);
if ( (pos & 1) == 0 )
{
iguana_rwbignum(1,&serialized[0],sizeof(hash),hash.bytes);
iguana_rwbignum(1,&serialized[sizeof(hash)],sizeof(proof),proof.bytes);
}
else
{
iguana_rwbignum(1,&serialized[0],sizeof(proof),proof.bytes);
iguana_rwbignum(1,&serialized[sizeof(hash)],sizeof(hash),hash.bytes);
}
hash = bits256_doublesha256(0,serialized,sizeof(serialized));
pos >>= 1;
}
return(hash);
}
bits256 LP_merkleroot(struct iguana_info *coin,struct electrum_info *ep,int32_t height)
{
cJSON *hdrobj; bits256 merkleroot;
memset(merkleroot.bytes,0,sizeof(merkleroot));
if ( coin->cachedmerkleheight == height )
return(coin->cachedmerkle);
if ( (hdrobj= electrum_getheader(coin->symbol,ep,&hdrobj,height)) != 0 )
{
if ( jobj(hdrobj,"merkle_root") != 0 )
{
merkleroot = jbits256(hdrobj,"merkle_root");
if ( bits256_nonz(merkleroot) != 0 )
{
coin->cachedmerkle = merkleroot;
coin->cachedmerkleheight = height;
}
}
free_json(hdrobj);
} else printf("couldnt get header for ht.%d\n",height);
return(merkleroot);
}
int32_t LP_merkleproof(struct iguana_info *coin,char *coinaddr,struct electrum_info *ep,bits256 txid,int32_t height)
{
struct LP_transaction *tx=0; cJSON *merkobj,*merkles,*retjson; bits256 roothash,merkleroot; int32_t m,ht=0,SPV = 0;
if ( height <= 0 )
return(0);
if ( (tx= LP_transactionfind(coin,txid)) == 0 && strcmp(coinaddr,coin->smartaddr) == 0 )
{
if ( (retjson= electrum_transaction(&ht,coin->symbol,ep,&retjson,txid,0)) != 0 )
free_json(retjson);
}
if ( tx != 0 )
{
if ( tx->height == 0 )
{
if ( height != 0 )
tx->height = height;
else if ( ht != 0 )
tx->height = ht;
height = tx->height;
}
if ( tx->SPV > 0 )
return(tx->SPV);
}
if ( (merkobj= electrum_getmerkle(coin->symbol,ep,&merkobj,txid,height)) != 0 )
{
char str[65],str2[65],str3[65];
SPV = 0;
memset(roothash.bytes,0,sizeof(roothash));
if ( (merkles= jarray(&m,merkobj,"merkle")) != 0 )
{
roothash = validate_merkle(jint(merkobj,"pos"),txid,merkles,m);
merkleroot = LP_merkleroot(coin,ep,height);
if ( bits256_nonz(merkleroot) != 0 )
{
if ( bits256_cmp(merkleroot,roothash) == 0 )
{
SPV = height;
LP_SPV_store(coin,txid,height);
if ( tx != 0 )
{
tx->SPV = height;
if ( strcmp(coinaddr,coin->smartaddr) != 0 && tx->serialized != 0 )
{
free(tx->serialized);
tx->serialized = 0;
tx->len = 0;
}
}
//printf("validated MERK %s ht.%d -> %s root.(%s)\n",bits256_str(str,txid),height,jprint(merkobj,0),bits256_str(str2,roothash));
}
else
{
SPV = -1;
printf("ERROR MERK %s ht.%d -> %s root.(%s) vs %s\n",bits256_str(str,txid),height,jprint(merkobj,0),bits256_str(str2,roothash),bits256_str(str3,merkleroot));
}
} else SPV = 0;
}
if ( SPV < 0 )
{
printf("MERKLE DIDNT VERIFY.%s %s ht.%d (%s)\n",coin->symbol,bits256_str(str,txid),height,jprint(merkobj,0));
if ( jobj(merkobj,"error") != 0 )
SPV = 0; // try again later
}
free_json(merkobj);
}
return(SPV);
}
char *LP_unspents_filestr(char *symbol,char *addr)
{
char fname[1024]; long fsize;
sprintf(fname,"%s/UNSPENTS/%s_%s",GLOBAL_DBDIR,symbol,addr), OS_portable_path(fname);
return(OS_filestr(&fsize,fname));
}
void LP_unspents_cache(char *symbol,char *addr,char *arraystr,int32_t updatedflag)
{
char fname[1024]; FILE *fp=0;
sprintf(fname,"%s/UNSPENTS/%s_%s",GLOBAL_DBDIR,symbol,addr), OS_portable_path(fname);
//printf("unspents cache.(%s) for %s %s, updated.%d\n",fname,symbol,addr,updatedflag);
if ( updatedflag == 0 && (fp= fopen(fname,"rb")) == 0 )
updatedflag = 1;
else if ( fp != 0 )
fclose(fp);
if ( updatedflag != 0 && (fp= fopen(fname,"wb")) != 0 )
{
fwrite(arraystr,1,strlen(arraystr),fp);
fclose(fp);
}
}
uint64_t LP_unspents_load(char *symbol,char *addr)
{
char *arraystr; uint64_t balance = 0; int32_t i,n; bits256 zero; cJSON *retjson,*item; struct iguana_info *coin;
if ( (coin= LP_coinfind(symbol)) != 0 )
{
if ( (arraystr= LP_unspents_filestr(symbol,addr)) != 0 )
{
if ( (retjson= cJSON_Parse(arraystr)) != 0 )
{
//printf("PROCESS UNSPENTS %s\n",arraystr);
if ( (n= cJSON_GetArraySize(retjson)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(retjson,i);
balance += j64bits(item,"value");
}
}
memset(zero.bytes,0,sizeof(zero));
electrum_process_array(coin,coin->electrum,addr,retjson,1,zero,zero);
free_json(retjson);
}
free(arraystr);
}
}
return(balance);
}

136
iguana/exchanges/LP_coins.c

@ -23,9 +23,12 @@ char *portstrs[][3] = { { "BTC", "8332" }, { "KMD", "7771" } };
uint16_t LP_rpcport(char *symbol)
{
int32_t i;
for (i=0; i<sizeof(portstrs)/sizeof(*portstrs); i++)
if ( strcmp(portstrs[i][0],symbol) == 0 )
return(atoi(portstrs[i][1]));
if ( symbol != 0 && symbol[0] != 0 )
{
for (i=0; i<sizeof(portstrs)/sizeof(*portstrs); i++)
if ( strcmp(portstrs[i][0],symbol) == 0 )
return(atoi(portstrs[i][1]));
}
return(0);
}
@ -96,7 +99,34 @@ void LP_statefname(char *fname,char *symbol,char *assetname,char *str,char *name
{
if ( confpath != 0 && confpath[0] != 0 )
{
strcpy(fname,confpath);
#if defined(NATIVE_WINDOWS)
// need to do something with "confpath":"`${process.env.HOME}`/.muecore/mue.conf" under Windows
char *ht = "`${process.env.HOME}`", *ht_start, *p_ht;
char ht_symbol[2];
ht_start = strstr(confpath, ht);
if (ht_start) {
ht_start = ht_start + strlen(ht);
sprintf(fname, "%s\\", LP_getdatadir());
p_ht = ht_start;
if (p_ht[0] == '/' && p_ht[1] == '.') {
p_ht += 2;
//printf("%s\n", p_ht);
while (p_ht[0] != '\0') {
if (p_ht[0] == '/') strcat(fname, "\\"); else
{
ht_symbol[0] = p_ht[0]; ht_symbol[1] = '\0';
strcat(fname, ht_symbol);
}
p_ht++;
}
//printf("%s\n", fname);
}
} else strcpy(fname, confpath);
#else
strcpy(fname,confpath);
#endif
return;
}
sprintf(fname,"%s",LP_getdatadir());
@ -116,7 +146,7 @@ void LP_statefname(char *fname,char *symbol,char *assetname,char *str,char *name
else if ( name != 0 )
{
char name2[64];
#ifdef __APPLE__
#if defined(__APPLE__) || defined(NATIVE_WINDOWS)
int32_t len;
strcpy(name2,name);
name2[0] = toupper(name2[0]);
@ -161,7 +191,7 @@ uint16_t LP_userpass(char *userpass,char *symbol,char *assetname,char *confroot,
sprintf(confname,"%s.conf",confroot);
if ( 0 )
printf("%s (%s) %s confname.(%s) confroot.(%s)\n",symbol,assetname,name,confname,confroot);
#ifdef __APPLE__
#if defined(__APPLE__) || defined(NATIVE_WINDOWS)
int32_t len;
confname[0] = toupper(confname[0]);
len = (int32_t)strlen(confname);
@ -184,7 +214,7 @@ uint16_t LP_userpass(char *userpass,char *symbol,char *assetname,char *confroot,
cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif)
{
struct electrum_info *ep; uint64_t balance; char wifstr[128],ipaddr[64]; uint8_t tmptype; bits256 checkkey; cJSON *item = cJSON_CreateObject();
struct electrum_info *ep; bits256 zero; int32_t notarized; uint64_t balance; char wifstr[128],ipaddr[64]; uint8_t tmptype; bits256 checkkey; cJSON *item = cJSON_CreateObject();
jaddstr(item,"coin",coin->symbol);
if ( showwif != 0 )
{
@ -197,8 +227,12 @@ cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif)
jadd(item,"installed",coin->userpass[0] == 0 ? jfalse() : jtrue());
if ( coin->userpass[0] != 0 )
{
jaddnum(item,"height",LP_getheight(coin));
balance = LP_smartbalance(coin);
jaddnum(item,"height",LP_getheight(&notarized,coin));
if ( notarized > 0 )
jaddnum(item,"notarized",notarized);
if ( coin->electrum != 0 )
balance = LP_unspents_load(coin->symbol,coin->smartaddr);
else balance = LP_RTsmartbalance(coin);
jaddnum(item,"balance",dstr(balance));
jaddnum(item,"KMDvalue",dstr(LP_KMDvalue(coin,balance)));
}
@ -224,19 +258,33 @@ cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif)
jaddnum(item,"pubtype",coin->pubtype);
jaddnum(item,"p2shtype",coin->p2shtype);
jaddnum(item,"wiftype",coin->wiftype);
jaddnum(item,"txfee",coin->txfee);
jaddnum(item,"txfee",strcmp(coin->symbol,"BTC") != 0 ? coin->txfee : LP_txfeecalc(coin,0,0));
if ( strcmp(coin->symbol,"KMD") == 0 )
{
memset(zero.bytes,0,sizeof(zero));
if ( strcmp(coin->smartaddr,coin->instantdex_address) != 0 )
{
LP_instantdex_depositadd(coin->smartaddr,zero);
strcpy(coin->instantdex_address,coin->smartaddr);
}
jaddnum(item,"zcredits",dstr(LP_myzcredits()));
jadd(item,"zdebits",LP_myzdebits());
}
return(item);
}
struct iguana_info *LP_conflicts_find(struct iguana_info *refcoin)
{
struct iguana_info *coin=0,*tmp;
HASH_ITER(hh,LP_coins,coin,tmp)
if ( refcoin != 0 )
{
if ( coin->inactive != 0 || coin->electrum != 0 || coin == refcoin )
continue;
if ( strcmp(coin->serverport,refcoin->serverport) == 0 )
break;
HASH_ITER(hh,LP_coins,coin,tmp)
{
if ( coin->inactive != 0 || coin->electrum != 0 || coin == refcoin )
continue;
if ( strcmp(coin->serverport,refcoin->serverport) == 0 )
break;
}
}
return(coin);
}
@ -254,31 +302,37 @@ cJSON *LP_coinsjson(int32_t showwif)
char *LP_getcoin(char *symbol)
{
int32_t numenabled,numdisabled; struct iguana_info *coin,*tmp; cJSON *item=0,*retjson;
numenabled = numdisabled = 0;
retjson = cJSON_CreateObject();
HASH_ITER(hh,LP_coins,coin,tmp)
if ( symbol != 0 && symbol[0] != 0 )
{
if ( strcmp(symbol,coin->symbol) == 0 )
item = LP_coinjson(coin,0);
if ( coin->inactive == 0 )
numenabled++;
else numdisabled++;
numenabled = numdisabled = 0;
HASH_ITER(hh,LP_coins,coin,tmp)
{
if ( strcmp(symbol,coin->symbol) == 0 )
item = LP_coinjson(coin,0);
if ( coin->inactive == 0 )
numenabled++;
else numdisabled++;
}
jaddstr(retjson,"result","success");
jaddnum(retjson,"enabled",numenabled);
jaddnum(retjson,"disabled",numdisabled);
if ( item == 0 )
item = cJSON_CreateObject();
jadd(retjson,"coin",item);
}
jaddstr(retjson,"result","success");
jaddnum(retjson,"enabled",numenabled);
jaddnum(retjson,"disabled",numdisabled);
if ( item == 0 )
item = cJSON_CreateObject();
jadd(retjson,"coin",item);
return(jprint(retjson,1));
}
struct iguana_info *LP_coinsearch(char *symbol)
{
struct iguana_info *coin;
portable_mutex_lock(&LP_coinmutex);
HASH_FIND(hh,LP_coins,symbol,strlen(symbol),coin);
portable_mutex_unlock(&LP_coinmutex);
struct iguana_info *coin = 0;
if ( symbol != 0 && symbol[0] != 0 )
{
portable_mutex_lock(&LP_coinmutex);
HASH_FIND(hh,LP_coins,symbol,strlen(symbol),coin);
portable_mutex_unlock(&LP_coinmutex);
}
return(coin);
}
@ -339,6 +393,11 @@ uint16_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *asse
coin->zcash = LP_IS_BITCOINCASH;
//printf("set coin.%s <- LP_IS_BITCOINCASH %d\n",symbol,coin->zcash);
}
else if ( strcmp(symbol,"BTG") == 0 )
{
coin->zcash = LP_IS_BITCOINGOLD;
printf("set coin.%s <- LP_IS_BITCOINGOLD %d\n",symbol,coin->zcash);
}
return(port);
}
@ -389,9 +448,9 @@ struct iguana_info *LP_coinfind(char *symbol)
if ( (coin= LP_coinadd(&cdata)) != 0 )
{
coin->inactive = isinactive * (uint32_t)time(NULL);
if ( strcmp(symbol,"KMD") == 0 )
/*if ( strcmp(symbol,"KMD") == 0 )
coin->inactive = 0;
else if ( strcmp(symbol,"BTC") == 0 )
else*/ if ( strcmp(symbol,"BTC") == 0 )
{
coin->inactive = (uint32_t)time(NULL) * !IAMLP;
printf("BTC inactive.%u\n",coin->inactive);
@ -450,3 +509,12 @@ struct iguana_info *LP_coincreate(cJSON *item)
return(0);
}
void LP_otheraddress(char *destcoin,char *otheraddr,char *srccoin,char *coinaddr)
{
uint8_t addrtype,rmd160[20]; struct iguana_info *src,*dest;
if ( (src= LP_coinfind(srccoin)) != 0 && (dest= LP_coinfind(destcoin)) != 0 )
{
bitcoin_addr2rmd160(src->taddr,&addrtype,rmd160,coinaddr);
bitcoin_address(otheraddr,dest->taddr,dest->pubtype,rmd160,20);
} else printf("couldnt find %s or %s\n",srccoin,destcoin);
}

420
iguana/exchanges/LP_commands.c

@ -34,10 +34,12 @@ char *LP_numutxos()
char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port
{
char *method,*ipaddr,*userpass,*base,*rel,*coin,*retstr = 0; uint16_t argport=0,pushport,subport; int32_t changed,otherpeers,flag = 0; struct LP_peerinfo *peer; cJSON *retjson,*reqjson = 0; struct iguana_info *ptr;
//printf("stats_JSON(%s)\n",jprint(argjson,0));
char *method,*userpass,*base,*rel,*coin,*retstr = 0; int32_t changed,flag = 0; cJSON *retjson,*reqjson = 0; struct iguana_info *ptr;
method = jstr(argjson,"method");
if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 && (method == 0 || strcmp(method,"electrum") != 0) )
if ( method != 0 && (strcmp(method,"addr_unspents") == 0 || strcmp(method,"uitem") == 0 || strcmp(method,"postutxos") == 0) )
return(0);
//printf("stats_JSON.(%s)\n",jprint(argjson,0));
/*if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 && (method == 0 || strcmp(method,"electrum") != 0) )
{
if ( strcmp(ipaddr,"127.0.0.1") != 0 && argport >= 1000 )
{
@ -50,31 +52,34 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r
{
if ( 0 && (otherpeers= jint(argjson,"numpeers")) > peer->numpeers )
peer->numpeers = otherpeers;
/*if ( 0 && (othernumutxos= jint(argjson,"numutxos")) > peer->numutxos )
{
printf("change.(%s) numutxos.%d -> %d mynumutxos.%d\n",peer->ipaddr,peer->numutxos,othernumutxos,LP_mypeer != 0 ? LP_mypeer->numutxos:0);
peer->numutxos = othernumutxos;
}*/
if ( peer->sessionid == 0 )
peer->sessionid = juint(argjson,"session");
//printf("peer.(%s) found (%d %d) (%d %d) (%s)\n",peer->ipaddr,peer->numpeers,peer->numutxos,otherpeers,othernumutxos,jprint(argjson,0));
} else LP_addpeer(LP_mypeer,LP_mypubsock,ipaddr,argport,pushport,subport,jint(argjson,"numpeers"),jint(argjson,"numutxos"),juint(argjson,"session"));
}
}
}*/
if ( method == 0 )
{
if ( is_cJSON_Array(argjson) != 0 )
printf("RAWARRAY command? %s\n",jprint(argjson,0));
if ( flag == 0 || jobj(argjson,"result") != 0 )
printf("stats_JSON no method: (%s) (%s:%u)\n",jprint(argjson,0),ipaddr,argport);
printf("stats_JSON no method: (%s)\n",jprint(argjson,0));
return(0);
}
/*if ( strcmp(method,"hello") == 0 )
{
//printf("got hello from %s:%u\n",ipaddr!=0?ipaddr:"",argport);
return(0);
}
else*/ if ( strcmp(method,"sendmessage") == 0 && jobj(argjson,"userpass") == 0 )
if ( strcmp(method,"hello") == 0 )
{
//int32_t i; cJSON *array = cJSON_CreateArray();
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"status","got hello");
//for (i=0; i<10000; i++)
// jaddinum(array,i);
//jadd(retjson,"array",array);
return(jprint(retjson,1));
//printf("got hello from %s:%u\n",ipaddr!=0?ipaddr:"",argport);
//return(clonestr("{\"result\":\"success\",\"status\":\"got hello\"}"));
}
/*else if ( strcmp(method,"sendmessage") == 0 && jobj(argjson,"userpass") == 0 )
{
static char *laststr;
char *newstr; bits256 pubkey = jbits256(argjson,"pubkey");
@ -91,35 +96,35 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r
retstr = clonestr(laststr);
}
} else retstr = clonestr("{\"error\":\"duplicate message\"}");
}
}*/
//else if ( strcmp(method,"nn_tests") == 0 )
// return(clonestr("{\"result\":\"success\"}"));
else if ( strcmp(method,"help") == 0 )
return(clonestr("{\"result\":\" \
available localhost RPC commands: \n \
pricearray(base, rel, starttime=0, endtime=-1, timescale=60) -> [timestamp, avebid, aveask, highbid, lowask]\n\
setprice(base, rel, price)\n\
autoprice(base, rel, minprice, margin, refbase, refrel, factor, offset)*\n\
setprice(base, rel, price, broadcast=1)\n\
autoprice(base, rel, fixed, minprice, margin, refbase, refrel, factor, offset)*\n\
goal(coin=*, val=<autocalc>)\n\
myprice(base, rel)\n\
enable(coin)\n\
disable(coin)\n\
notarizations(coin)\n\
parselog()\n\
statsdisp(starttime=0, endtime=0, gui="", pubkey="")\n\
statsdisp(starttime=0, endtime=0, gui="", pubkey="", base="", rel="")\n\
tradesarray(base, rel, starttime=<now>-timescale*1024, endtime=<now>, timescale=60) -> [timestamp, high, low, open, close, relvolume, basevolume, aveprice, numtrades]\n\
pricearray(base, rel, starttime=0, endtime=0, timescale=60) -> [timestamp, avebid, aveask, highbid, lowask]\n\
getrawtransaction(coin, txid)\n\
inventory(coin)\n\
bestfit(rel, relvolume)\n\
inventory(coin, reset=0, [passphrase=])\n\
lastnonce()\n\
buy(base, rel, price, relvolume, timeout=10, duration=3600, nonce, pubkey="")\n\
sell(base, rel, price, basevolume, timeout=10, duration=3600, nonce, pubkey="")\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\
swapstatus(pending=0)\n\
swapstatus(coin, limit=10)\n\
swapstatus(base, rel, limit=10)\n\
swapstatus(requestid, quoteid)\n\
recentswaps(limit=3)\n\
notarizations(coin)\n\
public API:\n \
getcoins()\n\
getcoin(coin)\n\
@ -130,23 +135,39 @@ listunspent(coin, address)\n\
setconfirms(coin, numconfirms, maxconfirms=6)\n\
trust(pubkey, trust) # positive to trust, 0 for normal, negative to blacklist\n\
balance(coin, address)\n\
balances(address)\n\
fundvalue(address="", holdings=[], divisor=0)\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\
deletemessages(firsti=0, num=100)\n\
getprices()\n\
getprice(base, rel)\n\
//sendmessage(base=coin, rel="", pubkey=zero, <argjson method2>)\n\
//getmessages(firsti=0, num=100)\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\
bot_list()\n\
bot_statuslist()\n\
bot_buy(base, rel, maxprice, relvolume) -> botid\n\
bot_sell(base, rel, minprice, basevolume) -> botid\n\
bot_settings(botid, newprice, newvolume)\n\
bot_status(botid)\n\
bot_stop(botid)\n\
bot_pause(botid)\n\
instantdex_deposit(weeks, amount, broadcast=1)\n\
instantdex_claim()\n\
\"}"));
//sell(base, rel, price, basevolume, timeout=10, duration=3600)\n\
base = jstr(argjson,"base");
rel = jstr(argjson,"rel");
coin = jstr(argjson,"coin");
if ( (base= jstr(argjson,"base")) == 0 )
base = "";
if ((rel= jstr(argjson,"rel")) == 0 )
rel = "";
if ( (coin= jstr(argjson,"coin")) == 0 )
coin = "";
if ( G.USERPASS[0] != 0 && strcmp(remoteaddr,"127.0.0.1") == 0 && port != 0 ) // protected localhost
{
if ( G.USERPASS_COUNTER == 0 )
@ -163,6 +184,7 @@ stop()\n\
jdelete(argjson,"userpass");
if ( strcmp(method,"passphrase") == 0 )
{
char coinaddr[64];
G.USERPASS_COUNTER = 1;
if ( LP_passphrase_init(jstr(argjson,"passphrase"),jstr(argjson,"gui")) < 0 )
return(clonestr("{\"error\":\"couldnt change passphrase\"}"));
@ -171,25 +193,40 @@ stop()\n\
jaddstr(retjson,"result","success");
jaddstr(retjson,"userpass",G.USERPASS);
jaddbits256(retjson,"mypubkey",G.LP_mypub25519);
bitcoin_address(coinaddr,0,60,G.LP_myrmd160,20);
jaddstr(retjson,"KMD",coinaddr);
bitcoin_address(coinaddr,0,0,G.LP_myrmd160,20);
jaddstr(retjson,"BTC",coinaddr);
jaddstr(retjson,"NXT",G.LP_NXTaddr);
jadd(retjson,"coins",LP_coinsjson(LP_showwif));
return(jprint(retjson,1));
}
}
else if ( strcmp(method,"sendmessage") == 0 )
else if ( strcmp(method,"instantdex_deposit") == 0 )
{
if ( jobj(argjson,"method2") == 0 )
if ( (ptr= LP_coinsearch("KMD")) != 0 )
{
LP_broadcast_message(LP_mypubsock,base!=0?base:jstr(argjson,"coin"),rel,jbits256(argjson,"pubkey"),jprint(argjson,0));
if ( jint(argjson,"weeks") <= 0 || jdouble(argjson,"amount") < 10. )
return(clonestr("{\"error\":\"instantdex_deposit needs to have weeks and amount\"}"));
else return(LP_instantdex_deposit(ptr,juint(argjson,"weeks"),jdouble(argjson,"amount"),jobj(argjson,"broadcast") != 0 ? jint(argjson,"broadcast") : 1));
}
return(clonestr("{\"result\":\"success\"}"));
return(clonestr("{\"error\":\"cant find KMD\"}"));
}
else if ( strcmp(method,"recentswaps") == 0 )
else if ( strcmp(method,"instantdex_claim") == 0 )
{
return(LP_recent_swaps(jint(argjson,"limit")));
if ( (ptr= LP_coinsearch("KMD")) != 0 )
{
return(LP_instantdex_claim(ptr));
}
return(clonestr("{\"error\":\"cant find KMD\"}"));
}
else if ( strcmp(method,"stop") == 0 )
/*else if ( strcmp(method,"sendmessage") == 0 )
{
printf("DEBUG stop\n");
exit(0);
if ( jobj(argjson,"method2") == 0 )
{
LP_broadcast_message(LP_mypubsock,base!=0?base:coin,rel,jbits256(argjson,"pubkey"),jprint(argjson,0));
}
return(clonestr("{\"result\":\"success\"}"));
}
else if ( strcmp(method,"getmessages") == 0 )
{
@ -201,18 +238,36 @@ stop()\n\
{
LP_deletemessages(jint(argjson,"firsti"),jint(argjson,"num"));
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,"millis") == 0 )
{
LP_millistats_update(0);
return(clonestr("{\"result\":\"success\"}"));
}
else if ( strcmp(method,"getprices") == 0 )
return(LP_prices());
else if ( strcmp(method,"getpeers") == 0 )
return(LP_peers());
else if ( strcmp(method,"getcoins") == 0 )
return(jprint(LP_coinsjson(0),1));
else if ( strcmp(method,"notarizations") == 0 )
{
int32_t height,bestheight;
if ( (ptr= LP_coinsearch(coin)) != 0 )
{
height = LP_notarization_latest(&bestheight,ptr);
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"coin",coin);
jaddnum(retjson,"lastnotarization",height);
jaddnum(retjson,"bestheight",bestheight);
jaddnum(retjson,"lastnotarization",ptr->notarized);
jaddnum(retjson,"bestheight",ptr->height);
return(jprint(retjson,1));
} else return(clonestr("{\"error\":\"cant find coin\"}"));
}
@ -220,16 +275,9 @@ stop()\n\
{
return(LP_portfolio());
}
else if ( strcmp(method,"parselog") == 0 )
{
bits256 zero; int32_t n = LP_statslog_parse();
memset(zero.bytes,0,sizeof(zero));
return(LP_statslog_disp(n,2000000000,2000000000,"",zero));
}
else if ( strcmp(method,"statsdisp") == 0 )
{
int32_t n = LP_statslog_parse();
return(LP_statslog_disp(n,juint(argjson,"starttime"),juint(argjson,"endtime"),jstr(argjson,"gui"),jbits256(argjson,"pubkey")));
return(jprint(LP_statslog_disp(juint(argjson,"starttime"),juint(argjson,"endtime"),jstr(argjson,"gui"),jbits256(argjson,"pubkey"),jstr(argjson,"base"),jstr(argjson,"rel")),1));
}
else if ( strcmp(method,"secretaddresses") == 0 )
{
@ -242,16 +290,55 @@ stop()\n\
{
uint32_t requestid,quoteid;
if ( (requestid= juint(argjson,"requestid")) != 0 && (quoteid= juint(argjson,"quoteid")) != 0 )
return(basilisk_swapentry(requestid,quoteid));
else if ( coin != 0 && coin[0] != 0 )
return(basilisk_swapentry(requestid,quoteid,1));
else if ( coin[0] != 0 )
return(basilisk_swapentries(coin,0,jint(argjson,"limit")));
else if ( base != 0 && base[0] != 0 && rel != 0 && rel[0] != 0 )
else if ( base[0] != 0 && rel[0] != 0 )
return(basilisk_swapentries(base,rel,jint(argjson,"limit")));
else return(basilisk_swaplist(0,0));
else return(basilisk_swaplist(0,0,0,jint(argjson,"pending")));
}
else if ( strcmp(method,"dynamictrust") == 0 )
{
struct LP_address *ap; char *coinaddr;
if ( (ptr= LP_coinsearch("KMD")) != 0 && (coinaddr= jstr(argjson,"address")) != 0 )
{
//LP_zeroconf_deposits(ptr);
if ( (ap= LP_addressfind(ptr,coinaddr)) != 0 )
{
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"address",coinaddr);
jaddnum(retjson,"zcredits",dstr(ap->instantdex_credits));
return(jprint(retjson,1));
}
}
return(clonestr("{\"error\":\"cant find address\"}"));
}
if ( base != 0 && rel != 0 )
else if ( (retstr= LP_istradebots_command(ctx,pubsock,method,argjson)) != 0 )
return(retstr);
if ( base[0] != 0 && rel[0] != 0 )
{
double price,bid,ask;
if ( strcmp(method,"autoprice") == 0 )
{
if ( LP_autoprice(ctx,base,rel,argjson) < 0 )
return(clonestr("{\"error\":\"couldnt set autoprice\"}"));
else return(clonestr("{\"result\":\"success\"}"));
}
else if ( strcmp(method,"pricearray") == 0 )
{
uint32_t firsttime;
if ( base[0] != 0 && rel[0] != 0 )
{
if ( (firsttime= juint(argjson,"starttime")) < time(NULL)-30*24*3600 )
firsttime = (uint32_t)(time(NULL)-30*24*3600);
return(jprint(LP_pricearray(base,rel,firsttime,juint(argjson,"endtime"),jint(argjson,"timescale")),1));
} else return(clonestr("{\"error\":\"pricearray needs base and rel\"}"));
}
else if ( strcmp(method,"tradesarray") == 0 )
{
return(jprint(LP_tradesarray(base,rel,juint(argjson,"starttime"),juint(argjson,"endtime"),jint(argjson,"timescale")),1));
}
if ( IAMLP == 0 && LP_isdisabled(base,rel) != 0 )
return(clonestr("{\"error\":\"at least one of coins disabled\"}"));
price = jdouble(argjson,"price");
@ -261,18 +348,12 @@ stop()\n\
return(clonestr("{\"error\":\"couldnt set price\"}"));
//else if ( LP_mypriceset(&changed,rel,base,1./price) < 0 )
// return(clonestr("{\"error\":\"couldnt set price\"}"));
else return(LP_pricepings(ctx,myipaddr,LP_mypubsock,base,rel,price * LP_profitratio));
}
else if ( strcmp(method,"autoprice") == 0 )
{
if ( LP_autoprice(base,rel,argjson) < 0 )
return(clonestr("{\"error\":\"couldnt set autoprice\"}"));
else if ( price == 0. || jobj(argjson,"broadcast") == 0 || jint(argjson,"broadcast") != 0 )
return(LP_pricepings(ctx,myipaddr,LP_mypubsock,base,rel,price * LP_profitratio));
else return(clonestr("{\"result\":\"success\"}"));
}
else if ( strcmp(method,"pricearray") == 0 )
{
return(jprint(LP_pricearray(base,rel,juint(argjson,"starttime"),juint(argjson,"endtime"),jint(argjson,"timescale")),1));
}
else if ( strcmp(method,"orderbook") == 0 )
return(LP_orderbook(base,rel,jint(argjson,"duration")));
else if ( strcmp(method,"myprice") == 0 )
{
if ( LP_myprice(&bid,&ask,base,rel) > SMALLVAL )
@ -290,7 +371,7 @@ stop()\n\
//*
if ( price > SMALLVAL )
{
return(LP_autobuy(ctx,myipaddr,pubsock,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui"),juint(argjson,"nonce"),jbits256(argjson,"pubkey")));
return(LP_autobuy(ctx,myipaddr,pubsock,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui"),juint(argjson,"nonce"),jbits256(argjson,"destpubkey"),0));
} else return(clonestr("{\"error\":\"no price set\"}"));
}
else if ( strcmp(method,"sell") == 0 )
@ -298,18 +379,18 @@ stop()\n\
//*
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"),juint(argjson,"nonce"),jbits256(argjson,"pubkey")));
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"),jbits256(argjson,"destpubkey"),0));
} else return(clonestr("{\"error\":\"no price set\"}"));
}
}
else if ( rel != 0 && strcmp(method,"bestfit") == 0 )
/*else if ( rel[0] != 0 && strcmp(method,"bestfit") == 0 )
{
double relvolume;
if ( (relvolume= jdouble(argjson,"relvolume")) > SMALLVAL )
return(LP_bestfit(rel,relvolume));
else return(clonestr("{\"error\":\"no relvolume set\"}"));
}
else if ( (coin= jstr(argjson,"coin")) != 0 )
}*/
else if ( coin[0] != 0 )
{
if ( strcmp(method,"enable") == 0 )
{
@ -319,14 +400,28 @@ stop()\n\
if ( ptr->userpass[0] == 0 )
{
cJSON *retjson = cJSON_CreateObject();
jaddstr(retjson,"error","couldnt find coin locally installed");
jaddstr(retjson,"error",LP_DONTCHANGE_ERRMSG0);
jaddstr(retjson,"coin",coin);
return(jprint(retjson,1));
}
if ( LP_conflicts_find(ptr) == 0 )
{
ptr->inactive = 0;
cJSON *array = cJSON_CreateArray();
cJSON *array; int32_t notarized;
if ( LP_getheight(&notarized,ptr) <= 0 )
{
ptr->inactive = (uint32_t)time(NULL);
return(clonestr("{\"error\":\"coin cant be activated till synced\"}"));
}
else
{
if ( ptr->smartaddr[0] != 0 )
LP_unspents_load(coin,ptr->smartaddr);
LP_unspents_load(coin,ptr->smartaddr);
if ( strcmp(ptr->symbol,"KMD") == 0 )
LP_importaddress("KMD",BOTS_BONDADDRESS);
}
array = cJSON_CreateArray();
jaddi(array,LP_coinjson(ptr,0));
return(jprint(array,1));
} else return(clonestr("{\"error\":\"coin port conflicts with existing coin\"}"));
@ -343,6 +438,34 @@ stop()\n\
return(jprint(array,1));
} else return(clonestr("{\"error\":\"couldnt find coin\"}"));
}
else if ( strcmp(method,"listunspent") == 0 )
{
if ( (ptr= LP_coinsearch(coin)) != 0 )
{
char *coinaddr; bits256 zero;
memset(zero.bytes,0,sizeof(zero));
if ( (coinaddr= jstr(argjson,"address")) != 0 )
{
if ( coinaddr[0] != 0 )
{
LP_address(ptr,coinaddr);
if ( strcmp(coinaddr,ptr->smartaddr) == 0 && bits256_nonz(G.LP_privkey) != 0 )
{
LP_listunspent_issue(coin,coinaddr,2,zero,zero);
//LP_privkey_init(-1,ptr,G.LP_privkey,G.LP_mypub25519);
}
return(jprint(LP_listunspent(coin,coinaddr,zero,zero),1));
}
}
return(clonestr("{\"error\":\"no address specified\"}"));
} else return(clonestr("{\"error\":\"cant find coind\"}"));
}
else if ( strcmp(method,"balance") == 0 )
{
if ( (ptr= LP_coinsearch(coin)) != 0 )
return(jprint(LP_address_balance(ptr,jstr(argjson,"address"),1),1));
else return(clonestr("{\"error\":\"cant find coind\"}"));
}
else if ( strcmp(method,"electrum") == 0 )
{
if ( (ptr= LP_coinsearch(coin)) != 0 )
@ -357,7 +480,7 @@ stop()\n\
}
else if ( strcmp(method,"getrawtransaction") == 0 )
{
return(jprint(LP_gettx(coin,jbits256(argjson,"txid")),0));
return(jprint(LP_gettx(coin,jbits256(argjson,"txid"),0),1));
}
else if ( strcmp(method,"withdraw") == 0 )
{
@ -404,14 +527,23 @@ stop()\n\
else return(clonestr("{\"error\":\"cant find coind\"}"));
}
if ( LP_isdisabled(coin,0) != 0 )
return(clonestr("{\"error\":\"coin is disabled\"}"));
{
retjson = cJSON_CreateObject();
jaddstr(retjson,"error",LP_DONTCHANGE_ERRMSG1);
return(jprint(retjson,1));
}
if ( strcmp(method,"inventory") == 0 )
{
struct iguana_info *ptr;
if ( (ptr= LP_coinfind(coin)) != 0 )
{
//privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,ptr,"",USERPASS_WIFSTR);
//LP_utxopurge(0);
LP_address(ptr,ptr->smartaddr);
if ( jint(argjson,"reset") != 0 )
{
ptr->privkeydepth = 0;
LP_address_utxo_reset(ptr);
LP_passphrase_init(jstr(argjson,"passphrase"),G.gui);
}
if ( bits256_nonz(G.LP_privkey) != 0 )
LP_privkey_init(-1,ptr,G.LP_privkey,G.LP_mypub25519);
else printf("no LP_privkey\n");
@ -419,9 +551,11 @@ stop()\n\
jaddstr(retjson,"result","success");
jaddstr(retjson,"coin",coin);
jaddnum(retjson,"timestamp",time(NULL));
jadd(retjson,"alice",LP_inventory(coin));
jadd(retjson,"alice",cJSON_Parse("[]"));
//jadd(retjson,"alice",LP_inventory(coin));
//jadd(retjson,"bob",LP_inventory(coin,1));
LP_smartutxos_push(ptr);
//LP_smartutxos_push(ptr);
LP_address_utxo_reset(ptr);
return(jprint(retjson,1));
}
}
@ -458,55 +592,85 @@ stop()\n\
}
argjson = reqjson;
}
if ( strcmp(method,"getdPoW") == 0 )
retstr = clonestr("{\"result\":\"success\"}");
}
else
{
if ( strcmp(method,"tradesarray") == 0 )
{
return(jprint(LP_tradesarray(base,rel,juint(argjson,"starttime"),juint(argjson,"endtime"),jint(argjson,"timescale")),1));
}
else if ( strcmp(method,"getdPoW") == 0 )
{
if ( (ptr= LP_coinfind(jstr(argjson,"coin"))) != 0 )
LP_dPoW_broadcast(ptr);
retstr = clonestr("{\"result\":\"success\"}");
}
}
// received response
if ( strcmp(method,"postprice") == 0 )
if ( strcmp(method,"swapstatus") == 0 )
return(LP_swapstatus_recv(argjson));
else if ( strcmp(method,"gettradestatus") == 0 )
return(LP_gettradestatus(j64bits(argjson,"aliceid"),juint(argjson,"requestid"),juint(argjson,"quoteid")));
else if ( strcmp(method,"postprice") == 0 )
return(LP_postprice_recv(argjson));
else if ( strcmp(method,"postutxos") == 0 )
return(LP_postutxos_recv(argjson));
else if ( strcmp(method,"uitem") == 0 )
return(LP_uitem_recv(argjson));
else if ( strcmp(method,"dPoW") == 0 )
return(LP_dPoW_recv(argjson));
else if ( strcmp(method,"notify") == 0 )
return(LP_notify_recv(argjson));
else if ( strcmp(method,"getpeers") == 0 )
retstr = clonestr("{\"error\":\"deprecated\"}");
else if ( strcmp(method,"balances") == 0 )
return(jprint(LP_balances(jstr(argjson,"address")),1));
else if ( strcmp(method,"fundvalue") == 0 )
return(jprint(LP_fundvalue(argjson),1));
else if ( strcmp(method,"getprice") == 0 )
{
double price,bid,ask;
ask = LP_price(base,rel);
if ( (bid= LP_price(rel,base)) > SMALLVAL )
bid = 1./bid;
price = _pairaved(bid,ask);
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"base",base);
jaddstr(retjson,"rel",rel);
jaddnum(retjson,"timestamp",time(NULL));
jaddnum(retjson,"bid",bid);
jaddnum(retjson,"ask",ask);
jaddnum(retjson,"price",price);
return(jprint(retjson,1));
}
/*else if ( strcmp(method,"getpeers") == 0 )
{
char *tmpstr;
if ( (tmpstr= jstr(argjson,"LPnode")) != 0 )
LP_addpeer(LP_mypeer,LP_mypubsock,tmpstr,RPC_port,RPC_port+10,RPC_port+20,1,G.LP_sessionid);
if ( IAMLP != 0 )
{
printf("send peers list %s\n",LP_peers());
bits256 zero; memset(zero.bytes,0,sizeof(zero));
LP_reserved_msg(0,"","",zero,LP_peers());
}
retstr = clonestr("{\"result\":\"success\"}");
}*/
// end received response
// public access, even from http
else if ( strcmp(method,"tradestatus") == 0 )
{
LP_tradecommand_log(argjson);
printf("GOT TRADESTATUS! %s\n",jprint(argjson,0));
printf("%-4d tradestatus | aliceid.%llu RT.%d %d\n",(uint32_t)time(NULL) % 3600,(long long)j64bits(argjson,"aliceid"),LP_RTcount,LP_swapscount);
retstr = clonestr("{\"result\":\"success\"}");
}
else if ( strcmp(method,"balance") == 0 )
{
if ( (ptr= LP_coinsearch(jstr(argjson,"coin"))) != 0 )
return(jprint(LP_address_balance(ptr,jstr(argjson,"address"),1),1));
else return(clonestr("{\"error\":\"cant find coind\"}"));
}
else if ( strcmp(method,"pricearray") == 0 )
{
uint32_t firsttime;
if ( base != 0 && rel != 0 )
{
if ( (firsttime= juint(argjson,"firsttime")) < time(NULL)-30*24*3600 )
firsttime = (uint32_t)(time(NULL)-30*24*3600);
return(jprint(LP_pricearray(base,rel,firsttime,juint(argjson,"lasttime"),jint(argjson,"timescale")),1));
} else return(clonestr("{\"error\":\"pricearray needs base and rel\"}"));
}
else if ( strcmp(method,"getprices") == 0 )
return(LP_prices());
else if ( strcmp(method,"orderbook") == 0 )
return(LP_orderbook(base,rel,jint(argjson,"duration")));
else if ( strcmp(method,"getpeers") == 0 )
return(LP_peers());
else if ( strcmp(method,"getcoins") == 0 )
return(jprint(LP_coinsjson(0),1));
else if ( strcmp(method,"wantnotify") == 0 )
{
bits256 pub; static uint32_t lastnotify;
pub = jbits256(argjson,"pub");
//char str[65]; printf("got wantnotify.(%s) vs %s\n",jprint(argjson,0),bits256_str(str,G.LP_mypub25519));
if ( bits256_cmp(pub,G.LP_mypub25519) == 0 && time(NULL) > lastnotify+30 )
if ( bits256_cmp(pub,G.LP_mypub25519) == 0 && time(NULL) > lastnotify+60 )
{
lastnotify = (uint32_t)time(NULL);
//printf("wantnotify for me!\n");
@ -514,36 +678,10 @@ stop()\n\
}
retstr = clonestr("{\"result\":\"success\"}");
}
else if ( strcmp(method,"listunspent") == 0 )
{
if ( (ptr= LP_coinsearch(jstr(argjson,"coin"))) != 0 )
{
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_privkey) != 0 )
{
printf("network invoked\n");
LP_privkey_init(-1,ptr,G.LP_privkey,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,"addr_unspents") == 0 )
{
//printf("GOT ADDR_UNSPENTS %s %s\n",jstr(argjson,"coin"),jstr(argjson,"address"));
if ( (ptr= LP_coinsearch(jstr(argjson,"coin"))) != 0 )
if ( (ptr= LP_coinsearch(coin)) != 0 )
{
char *coinaddr;
if ( (coinaddr= jstr(argjson,"address")) != 0 )
@ -554,6 +692,8 @@ stop()\n\
if ( strcmp(coinaddr,ptr->smartaddr) == 0 && bits256_nonz(G.LP_privkey) != 0 )
{
//printf("ADDR_UNSPENTS %s %s is my address being asked for!\n",ptr->symbol,coinaddr);
if ( ptr->lastpushtime > 0 && ptr->addr_listunspent_requested > (uint32_t)time(NULL)-10 )
ptr->lastpushtime -= LP_ORDERBOOK_DURATION*0.1;
ptr->addr_listunspent_requested = (uint32_t)time(NULL);
}
}

283
iguana/exchanges/LP_include.h

@ -21,10 +21,20 @@
#ifndef LP_INCLUDE_H
#define LP_INCLUDE_H
#ifdef FROMGUI
#define printf(...)
#endif
#define LP_MAJOR_VERSION "0"
#define LP_MINOR_VERSION "1"
#define LP_BUILD_NUMBER "17701"
#define LP_BARTERDEX_VERSION 1
#define LP_MAGICBITS 1
#ifdef FROM_JS
#include <emscripten.h>
#define sleep(x) emscripten_sleep((x) * 1000)
void emscripten_usleep(int32_t x);
#define sleep(x) emscripten_usleep((x) * 1000000)
void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping
#define usleep(x) emscripten_usleep(x)
// ./autogen.sh
// emconfigure ./configure CFLAGS="-s PTHREAD_POOL_SIZE=8 -s USE_PTHREADS=1 -O2"
@ -34,26 +44,36 @@ void emscripten_usleep(int32_t x);
#endif
//#define LP_STRICTPEERS
#define LP_BARTERDEX_VERSION 0
#define LP_MAGICBITS 8
#define LP_MAXVINS 64
#define LP_HTTP_TIMEOUT 3 // 1 is too small due to edge cases of time(NULL)
#define LP_AUTOTRADE_TIMEOUT 15
#define ELECTRUM_TIMEOUT 10
#define LP_ELECTRUM_MAXERRORS 3
#define LP_AUTOTRADE_TIMEOUT 60
#define LP_RESERVETIME 600 //(LP_AUTOTRADE_TIMEOUT * 2)
#define ELECTRUM_TIMEOUT 7
#define LP_ELECTRUM_KEEPALIVE 60
#define LP_ELECTRUM_MAXERRORS 777
#define LP_MEMPOOL_TIMEINCR 10
#define LP_SCREENWIDTH 1024
#define LP_MIN_PEERS 8
#define LP_MAX_PEERS 32
#define LP_MAXDESIRED_UTXOS (IAMLP != 0 ? 256 : 64)
#define LP_MINDESIRED_UTXOS (IAMLP != 0 ? 64 : 16)
#define LP_DUSTCOMBINE_THRESHOLD 1000000
// RTmetrics
#define LP_RTMETRICS_TOPGROUP 1.01
#define LP_MAXPENDING_SWAPS 13
//#define LP_MAXPENDING_SWAPS 13
#define LP_CLIENT_STATSPARSE (90 * 1024 * 1024)
#define LP_COMMAND_SENDSOCK NN_PUSH
#define LP_COMMAND_RECVSOCK NN_PULL
#define DPOW_MIN_ASSETCHAIN_SIGS 11
#define LP_ENCRYPTED_MAXSIZE (4096 + 2 + crypto_box_NONCEBYTES + crypto_box_ZEROBYTES)
#define LP_ENCRYPTED_MAXSIZE (16384 + 2 + crypto_box_NONCEBYTES + crypto_box_ZEROBYTES)
#define LP_MAXPUBKEY_ERRORS 3
#define LP_MAXPUBKEY_ERRORS 10
#define PSOCK_KEEPALIVE 3600
#define MAINLOOP_PERSEC 100
#define MAX_PSOCK_PORT 60000
@ -68,7 +88,7 @@ void emscripten_usleep(int32_t x);
#define LP_SWAPSTEP_TIMEOUT 30
#define LP_MIN_TXFEE 10000
#define LP_MINVOL 20
#define LP_MINCLIENTVOL 1000
#define LP_MINCLIENTVOL 200
#define LP_MINSIZE_TXFEEMULT 10
#define LP_REQUIRED_TXFEE 0.8
@ -83,14 +103,18 @@ void emscripten_usleep(int32_t x);
#define JUMBLR_RMD160 "5177f8b427e5f47342a4b8ab5dac770815d4389e"
#define TIERNOLAN_RMD160 "daedddd8dbe7a2439841ced40ba9c3d375f98146"
#define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu"
#define INSTANTDEX_BTCD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf"
#define INSTANTDEX_KMD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf"
#define BOTS_BONDADDRESS "RNdqHx26GWy9bk8MtmH1UiXjQcXE4RKK2P"
#define BOTS_BONDPUBKEY33 "03e641d22e1ff5a7d45c8880537e0b0a114d7b9fee2c18a6b4a8a80b6285292990"
#define LP_WEEKMULTBAD (7 * 24 * 2600)
#define LP_WEEKMULT (7 * 24 * 3600)
#define LP_FIRSTWEEKTIME 1510790400 // must be 0 mod LP_WEEKMULT
//#define BASILISK_DISABLEWAITTX
//#define BASILISK_DISABLESENDTX
#define LP_RPCPORT 7783
#define LP_PROPAGATION_SLACK 100 // txid ordering is not enforced, so getting extra recent txid
#define LP_RESERVETIME 60
#define LP_AVETXSIZE 256
#define LP_CACHEDURATION 60
#define BASILISK_DEFAULT_NUMCONFIRMS 1
@ -100,15 +124,29 @@ void emscripten_usleep(int32_t x);
#define LP_IS_ZCASHPROTOCOL 1
#define LP_IS_BITCOINCASH 2
#define LP_IS_BITCOINGOLD 79
#define SIGHASH_FORKID 0x40
#define ZKSNARK_PROOF_SIZE 296
#define ZCASH_SOLUTION_ELEMENTS 1344
#define LP_REQUEST 0
#define LP_RESERVED 1
#define LP_CONNECT 2
#define LP_CONNECTED 3
#define LP_DONTCHANGE_ERRMSG0 "couldnt find coin locally installed"
#define LP_DONTCHANGE_ERRMSG1 "coin is disabled"
extern char GLOBAL_DBDIR[];
extern int32_t IAMLP;
struct iguana_msgvin { bits256 prev_hash; uint8_t *vinscript,*userdata,*spendscript,*redeemscript; uint32_t prev_vout,sequence; uint16_t scriptlen,p2shlen,userdatalen,spendlen; };
struct iguana_msgvin
{
bits256 prev_hash;
uint8_t *vinscript,*userdata,*spendscript,*redeemscript;
uint32_t prev_vout,sequence; uint16_t scriptlen,p2shlen,userdatalen,spendlen;
};
struct iguana_msgvout { uint64_t value; uint32_t pk_scriptlen; uint8_t *pk_script; };
@ -137,25 +175,25 @@ struct vin_signer { bits256 privkey; char coinaddr[64]; uint8_t siglen,sig[80],r
struct vin_info
{
struct iguana_msgvin vin; uint64_t amount; cJSON *extras; bits256 sigtxid;
int32_t M,N,validmask,spendlen,type,p2shlen,numpubkeys,numsigs,height,hashtype,userdatalen,suppress_pubkeys,ignore_cltverr;
uint32_t sequence,unspentind; struct vin_signer signers[16]; char coinaddr[65];
int32_t M,N,validmask,spendlen,type,p2shlen,numpubkeys,numsigs,height,userdatalen,suppress_pubkeys,ignore_cltverr;
uint32_t sequence,unspentind,hashtype; struct vin_signer signers[16]; char coinaddr[65];
uint8_t rmd160[20],spendscript[10000],p2shscript[10000],userdata[10000];
};
struct basilisk_swapmessage
/*struct basilisk_swapmessage
{
bits256 srchash,desthash;
uint32_t crc32,msgbits,quoteid,datalen;
uint8_t *data;
};
};*/
struct basilisk_swap;
struct basilisk_rawtxinfo
{
char destaddr[64],coinstr[16];
char destaddr[64];
bits256 txid,signedtxid,actualtxid;
uint64_t amount,change,inputsum;
int64_t amount,change,inputsum;
int32_t redeemlen,datalen,completed,vintype,vouttype,numconfirms,spendlen,secretstart,suppress_pubkeys;
uint32_t locktime,crcs[2];
uint8_t addrtype,pubkey33[33],rmd160[20];
@ -164,20 +202,19 @@ struct basilisk_rawtxinfo
struct basilisk_request
{
uint32_t requestid,timestamp,quoteid,quotetime; // 0 to 15
uint64_t srcamount,unused; // 16 to 31
int64_t srcamount,unused; // 16 to 31
bits256 srchash; // 32 to 63
bits256 desthash;
char src[8],dest[8];
char src[68],dest[68];
uint64_t destamount;
int32_t optionhours,DEXselector;
};
struct basilisk_rawtx
{
char name[32];
char name[32],symbol[65];
struct iguana_msgtx msgtx;
struct basilisk_rawtxinfo I;
struct iguana_info *coin;
char vinstr[8192],p2shaddr[64];
cJSON *vins;
bits256 utxotxid; int32_t utxovout;
@ -187,11 +224,11 @@ struct basilisk_rawtx
struct basilisk_swapinfo
{
struct basilisk_request req;
char bobstr[64],alicestr[64];
char bobstr[128],alicestr[128];
bits256 myhash,otherhash,orderhash;
uint32_t statebits,otherstatebits,started,expiration,finished,dead,reftime,putduration,callduration;
int32_t bobconfirms,aliceconfirms,iambob,reclaimed,bobspent,alicespent,pad,aliceistrusted,bobistrusted,otheristrusted,otherstrust,alicemaxconfirms,bobmaxconfirms;
uint64_t alicesatoshis,bobsatoshis,bobinsurance,aliceinsurance,Atxfee,Btxfee;
int64_t alicesatoshis,bobsatoshis,bobinsurance,aliceinsurance,Atxfee,Btxfee;
bits256 myprivs[2],mypubs[2],otherpubs[2],pubA0,pubA1,pubB0,pubB1,privAm,pubAm,privBn,pubBn;
uint32_t crcs_mypub[2],crcs_mychoosei[2],crcs_myprivs[2],crcs_mypriv[2];
@ -206,12 +243,45 @@ struct basilisk_swapinfo
uint8_t userdata_bobrefund[256],userdata_bobrefundlen;
};
struct LP_outpoint { bits256 spendtxid; uint64_t value,interest; int32_t spendvini,spendheight; char coinaddr[64]; };
#define BASILISK_ALICESPEND 0
#define BASILISK_BOBSPEND 1
#define BASILISK_BOBPAYMENT 2
#define BASILISK_ALICEPAYMENT 3
#define BASILISK_BOBDEPOSIT 4
#define BASILISK_OTHERFEE 5
#define BASILISK_MYFEE 6
#define BASILISK_BOBREFUND 7
#define BASILISK_BOBRECLAIM 8
#define BASILISK_ALICERECLAIM 9
#define BASILISK_ALICECLAIM 10
//0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0
char *txnames[] = { "alicespend", "bobspend", "bobpayment", "alicepayment", "bobdeposit", "otherfee", "myfee", "bobrefund", "bobreclaim", "alicereclaim", "aliceclaim" };
struct LP_swap_remember
{
bits256 pubA0,pubB0,pubB1,privAm,privBn,paymentspent,Apaymentspent,depositspent,myprivs[2],txids[sizeof(txnames)/sizeof(*txnames)];
uint64_t Atxfee,Btxfee,srcamount,destamount,aliceid;
int64_t values[sizeof(txnames)/sizeof(*txnames)];
uint32_t finishtime,tradeid,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],Predeemscript[1024],Dredeemscript[1024],pubkey33[33],other33[33];
char Agui[65],Bgui[65],gui[65],src[65],dest[65],destaddr[64],Adestaddr[64],Sdestaddr[64],alicepaymentaddr[64],bobpaymentaddr[64],bobdepositaddr[64],alicecoin[65],bobcoin[65],*txbytes[sizeof(txnames)/sizeof(*txnames)];
};
struct LP_outpoint
{
bits256 spendtxid;
uint64_t value,interest;
int32_t spendvini,spendheight;
char coinaddr[64];
};
struct LP_transaction
{
UT_hash_handle hh;
bits256 txid; int32_t height,numvouts,numvins,len; //uint32_t timestamp;
bits256 txid;
long fpos;
int32_t height,numvouts,numvins,len,SPV;
uint8_t *serialized;
struct LP_outpoint outpoints[];
};
@ -221,16 +291,18 @@ struct iguana_info
UT_hash_handle hh;
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 lastutxosync,addr_listunspent_requested,lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,obooktime;
int32_t numutxos,notarized,longestchain,firstrefht,firstscanht,lastscanht,bussock,height; uint16_t busport;
uint32_t dPoWtime,loadedcache,electrumlist,lastunspent,importedprivkey,lastpushtime,lastutxosync,addr_listunspent_requested,lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,obooktime;
uint8_t pubtype,p2shtype,isPoS,wiftype,wiftaddr,taddr,noimportprivkey_flag,userconfirms,isassetchain,maxconfirms;
char symbol[16],smartaddr[64],userpass[1024],serverport[128];
char symbol[128],smartaddr[64],userpass[1024],serverport[128],instantdex_address[64];
// portfolio
double price_kmd,force,perc,goal,goalperc,relvolume,rate;
void *electrum; void *ctx;
uint64_t maxamount,kmd_equiv,balanceA,balanceB,valuesumA,valuesumB;
uint8_t pubkey33[33],zcash;
bits256 cachedtxid; uint8_t *cachedtxiddata; int32_t cachedtxidlen;
int32_t privkeydepth;
bits256 cachedtxid,notarizationtxid; uint8_t *cachedtxiddata; int32_t cachedtxidlen;
bits256 cachedmerkle,notarizedhash; int32_t cachedmerkleheight;
};
struct _LP_utxoinfo { bits256 txid; uint64_t value; int32_t vout,height; };
@ -241,7 +313,7 @@ struct LP_utxobob { struct _LP_utxoinfo utxo,deposit; };
struct LP_utxoalice { struct _LP_utxoinfo utxo,fee; };
struct LP_utxoswap { bits256 otherpubkey; void *swap; uint64_t satoshis; };
//struct LP_utxoswap { bits256 otherpubkey; uint64_t satoshis; };
struct LP_utxoinfo
{
@ -249,11 +321,12 @@ struct LP_utxoinfo
bits256 pubkey;
struct _LP_utxoinfo payment,deposit,fee;
struct LP_utxostats T;
struct LP_utxoswap S;
int64_t swap_satoshis;
//struct LP_utxoswap S;
int32_t iambob,iamlp;
uint8_t key[sizeof(bits256) + sizeof(int32_t)];
uint8_t key2[sizeof(bits256) + sizeof(int32_t)];
char coin[16],coinaddr[64],gui[16];//spendscript[256];
char coin[65],coinaddr[64],gui[16];//spendscript[256];
};
struct LP_address_utxo
@ -261,6 +334,7 @@ struct LP_address_utxo
struct LP_address_utxo *next,*prev;
struct _LP_utxoinfo U;
int32_t SPV,spendheight;
//uint32_t timestamp;
};
struct LP_address
@ -268,19 +342,19 @@ struct LP_address
UT_hash_handle hh;
struct LP_address_utxo *utxos;
bits256 pubkey;
int64_t balance,total;
int64_t balance,total,instantdex_credits;
uint32_t timestamp,n,unspenttime;
int32_t unspentheight;
char coinaddr[40];
uint8_t pubsecp[33],pad;
uint8_t pubsecp[33],didinstantdex;
};
struct LP_peerinfo
{
UT_hash_handle hh;
uint64_t ip_port;
uint32_t ipbits,errortime,errors,numpeers,needping,lasttime,connected,lastutxos,lastpeers,diduquery,good,sessionid;
int32_t pushsock,subsock;
uint32_t recvtime,numrecv,ipbits,errortime,errors,numpeers,needping,lasttime,connected,lastutxos,lastpeers,diduquery,good,sessionid;
int32_t pushsock,subsock,isLP;
uint16_t port;
char ipaddr[64];
};
@ -289,43 +363,96 @@ struct LP_quoteinfo
{
struct basilisk_request R;
bits256 srchash,desthash,txid,txid2,desttxid,feetxid,privkey;
int64_t othercredits;
uint64_t satoshis,txfee,destsatoshis,desttxfee,aliceid;
uint32_t timestamp,quotetime; int32_t vout,vout2,destvout,feevout,pair;
char srccoin[16],coinaddr[64],destcoin[16],destaddr[64],gui[64];
uint32_t timestamp,quotetime,tradeid;
int32_t vout,vout2,destvout,feevout,pair;
char srccoin[65],coinaddr[64],destcoin[65],destaddr[64],gui[64];
};
struct LP_endpoint { int32_t pair; char ipaddr[64]; uint16_t port; };
struct basilisk_swap
{
void *ctx; struct iguana_info bobcoin,alicecoin; struct LP_utxoinfo *utxo;
void *ctx; //struct LP_utxoinfo *utxo;
struct LP_endpoint N;
void (*balancingtrade)(struct basilisk_swap *swap,int32_t iambob);
int32_t subsock,pushsock,connected,aliceunconf,depositunconf,paymentunconf; uint32_t lasttime,aborted;
int32_t subsock,pushsock,connected,aliceunconf,depositunconf,paymentunconf;
uint32_t lasttime,aborted,tradeid;
FILE *fp;
bits256 persistent_privkey,persistent_pubkey;
struct basilisk_swapinfo I;
struct basilisk_rawtx bobdeposit,bobpayment,alicepayment,myfee,otherfee,aliceclaim,alicespend,bobreclaim,bobspend,bobrefund,alicereclaim;
bits256 privkeys[INSTANTDEX_DECKSIZE];
struct basilisk_swapmessage *messages; int32_t nummessages,sentflag;
//struct basilisk_swapmessage *messages; int32_t nummessages,sentflag;
char Bdeposit[64],Bpayment[64];
uint64_t aliceid,otherdeck[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2];
uint8_t persistent_pubkey33[33],persistent_other33[33],changermd160[20],pad[15],verifybuf[100000];
};
struct LP_pubkey_quote
{
struct LP_pubkey_quote *next,*prev;
float price;
uint32_t maxutxo,aveutxo;
uint8_t baseind,relind,numutxos,scale;
};
struct LP_swapstats
{
UT_hash_handle hh;
struct LP_quoteinfo Q;
bits256 bobdeposit,alicepayment,bobpayment,paymentspent,Apaymentspent,depositspent;
int32_t bobdeposit_ht,alicepayment_ht,bobpayment_ht,paymentspent_ht,Apaymentspent_ht,depositspent_ht;
double qprice;
uint64_t aliceid;
int32_t bobneeds_dPoW,aliceneeds_dPoW;
uint32_t ind,methodind,finished,expired,lasttime,dPoWfinished;
char alicegui[32],bobgui[32];
};
struct LP_pubswap { struct LP_pubswap *next,*prev; struct LP_swapstats *swap; };
#define LP_MAXPRICEINFOS 256
struct LP_pubkeyinfo
struct LP_pubkey_info
{
UT_hash_handle hh;
bits256 pubkey;
float matrix[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS];
uint32_t timestamps[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS],timestamp,numerrors;
struct LP_pubkey_quote *quotes;
struct LP_pubswap *bobswaps,*aliceswaps;
int64_t dynamictrust,unconfcredits;
uint32_t timestamp,numerrors,lasttime,slowresponse;
int32_t istrusted;
uint8_t rmd160[20],sig[65],pubsecp[33],siglen;
};
int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *pubp,cJSON *item);
struct electrum_info
{
queue_t sendQ,pendingQ;
portable_mutex_t mutex,txmutex;
struct electrum_info *prev;
int32_t bufsize,sock,*heightp,numerrors;
struct iguana_info *coin;
uint32_t stratumid,lasttime,keepalive,pending,*heighttimep;
char ipaddr[64],symbol[66];
uint16_t port;
uint8_t buf[];
};
struct LP_trade
{
struct LP_trade *next,*prev;
UT_hash_handle hh;
uint64_t aliceid;
int64_t besttrust,bestunconfcredits;
double bestprice;
uint32_t negotiationdone,bestresponse,connectsent,firsttime,lasttime,firstprocessed,lastprocessed,newtime;
char pairstr[64],funcid,iambob;
struct LP_quoteinfo Qs[4],Q;
};
uint32_t LP_sighash(char *symbol,int32_t zcash);
int32_t LP_pubkey_sigcheck(struct LP_pubkey_info *pubp,cJSON *item);
int32_t LP_pubkey_sigadd(cJSON *item,uint32_t timestamp,bits256 priv,bits256 pub,uint8_t *rmd160,uint8_t *pubsecp);
int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson);
struct LP_address *LP_address(struct iguana_info *coin,char *coinaddr);
@ -333,33 +460,44 @@ void LP_swap_coinaddr(struct iguana_info *coin,char *coinaddr,uint64_t *valuep,u
void basilisk_dontforget_update(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx);
uint32_t basilisk_requestid(struct basilisk_request *rp);
uint32_t basilisk_quoteid(struct basilisk_request *rp);
struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp);
struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp,int32_t dynamictrust);
char *bitcoind_passthru(char *coinstr,char *serverport,char *userpass,char *method,char *params);
uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx,uint32_t nextbits,int32_t suppress_swapsend);
//double LP_query(char *method,struct LP_quoteinfo *qp,char *base,char *rel,bits256 mypub);
int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys);
void LP_quotesinit(char *base,char *rel);
int32_t LP_forward(void *ctx,char *myipaddr,int32_t pubsock,bits256 pubkey,char *jsonstr,int32_t freeflag);
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);
int64_t LP_kmdvalue(char *symbol,int64_t satoshis);
int64_t LP_komodo_interest(bits256 txid,int64_t value);
void LP_availableset(struct LP_utxoinfo *utxo);
void LP_availableset(bits256 txid,int32_t vout);
int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2);
int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsock,int32_t pullsock);
uint16_t LP_psock_get(char *connectaddr,char *connectaddr2,char *publicaddr,int32_t ispaired);
int64_t LP_listunspent_parseitem(struct iguana_info *coin,bits256 *txidp,int32_t *voutp,int32_t *heightp,cJSON *item);
void LP_unspents_cache(char *symbol,char *addr,char *arraystr,int32_t updatedflag);
uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired);
//void LP_utxo_clientpublish(struct LP_utxoinfo *utxo);
int32_t LP_coinbus(uint16_t coin_busport);
int32_t LP_nanomsg_recvs(void *ctx);
uint64_t LP_smartbalance(struct iguana_info *coin);
int32_t LP_getheight(struct iguana_info *coin);
int32_t LP_reserved_msg(char *base,char *rel,bits256 pubkey,char *msg);
int32_t LP_numconfirms(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t mempool);
void LP_aliceid(uint32_t tradeid,uint64_t aliceid,char *event,uint32_t requestid,uint32_t quoteid);
cJSON *LP_cache_transaction(struct iguana_info *coin,bits256 txid,uint8_t *serialized,int32_t len);
cJSON *LP_transaction_fromdata(struct iguana_info *coin,bits256 txid,uint8_t *serialized,int32_t len);
uint64_t LP_RTsmartbalance(struct iguana_info *coin);
int32_t LP_getheight(int32_t *notarizedp,struct iguana_info *coin);
int32_t LP_reserved_msg(int32_t priority,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);
int32_t LP_merkleproof(struct iguana_info *coin,char *coinaddr,struct electrum_info *ep,bits256 txid,int32_t height);
cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr,bits256 reftxid);
cJSON *LP_myzdebits();
int32_t _LP_utxos_remove(bits256 txid,int32_t vout);
int32_t LP_utxos_remove(bits256 txid,int32_t vout);
struct LP_transaction *LP_transactionadd(struct iguana_info *coin,bits256 txid,int32_t height,int32_t numvouts,int32_t numvins);
void LP_tradebot_finished(uint32_t tradeid,uint32_t requestid,uint32_t quoteid);
uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee,int32_t txlen);
struct LP_address *_LP_address(struct iguana_info *coin,char *coinaddr);
struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr);
@ -367,30 +505,47 @@ struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr);
int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,struct iguana_msgtx *msgtx,char **signedtxp,bits256 *signedtxidp,struct vin_info *V,int32_t numinputs,char *rawtx,cJSON *vins,cJSON *privkeysjson,int32_t zcash);
//void LP_butxo_swapfields_set(struct LP_utxoinfo *butxo);
struct LP_address_utxo *LP_address_utxofind(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout);
int64_t LP_myzcredits();
void LP_instantdex_depositadd(char *coinaddr,bits256 txid);
int64_t LP_instantdex_creditcalc(struct iguana_info *coin,int32_t dispflag,bits256 txid,char *refaddr);
int32_t LP_destaddr(char *destaddr,cJSON *item);
int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t duration);
char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey);
cJSON *LP_statslog_disp(uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey,char *refbase,char *refrel);
uint32_t LP_heighttime(char *symbol,int32_t height);
uint64_t LP_unspents_load(char *symbol,char *addr);
int32_t LP_validSPV(char *symbol,char *coinaddr,bits256 txid,int32_t vout);
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();
char *basilisk_swapentry(uint32_t requestid,uint32_t quoteid);
uint64_t LP_KMDvalue(struct iguana_info *coin,uint64_t balance);
int32_t LP_address_utxoadd(char *debug,struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight);
double LP_CMCbtcprice(double *price_usdp,char *symbol);
char *basilisk_swapentry(uint32_t requestid,uint32_t quoteid,int32_t forceflag);
int64_t LP_KMDvalue(struct iguana_info *coin,int64_t balance);
int32_t LP_address_utxoadd(uint32_t timestamp,char *debug,struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight);
void LP_smartutxos_push(struct iguana_info *coin);
void LP_cacheptrs_init(struct iguana_info *coin);
cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrumret);
cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout);
void LP_postutxos(char *symbol,char *coinaddr);
int32_t LP_listunspent_both(char *symbol,char *coinaddr,int32_t fullflag);
uint16_t LP_randpeer(char *destip);
cJSON *bitcoin_data2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash);
void LP_tradebot_pauseall();
void LP_portfolio_reset();
uint32_t LP_atomic_locktime(char *base,char *rel);
struct LP_pubkey_info *LP_pubkeyfind(bits256 pubkey);
char *issue_LP_psock(char *destip,uint16_t destport,int32_t ispaired);
char *LP_unspents_filestr(char *symbol,char *addr);
cJSON *bitcoin_data2json(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash);
//int32_t LP_butxo_findeither(bits256 txid,int32_t vout);
cJSON *LP_listunspent(char *symbol,char *coinaddr);
cJSON *LP_listunspent(char *symbol,char *coinaddr,bits256 reftxid,bits256 reftxid2);
int32_t LP_gettx_presence(char *symbol,bits256 expectedtxid);
double LP_getestimatedrate(struct iguana_info *coin);
struct LP_utxoinfo *_LP_utxofind(int32_t iambob,bits256 txid,int32_t vout);
struct LP_utxoinfo *_LP_utxo2find(int32_t iambob,bits256 txid,int32_t vout);
int64_t LP_dynamictrust(int64_t credits,bits256 pubkey,int64_t kmdvalue);
struct LP_address *LP_addressfind(struct iguana_info *coin,char *coinaddr);
int64_t LP_outpoint_amount(char *symbol,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);

650
iguana/exchanges/LP_instantdex.c

@ -0,0 +1,650 @@
/******************************************************************************
* Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
//
// LP_instantdex.c
// marketmaker
//
void LP_instantdex_txidaddfname(char *fname,char *afname,char *coinaddr)
{
if ( coinaddr == 0 || coinaddr[0] == 0 )
{
sprintf(fname,"%s/instantdex.json",GLOBAL_DBDIR);
sprintf(afname,"%s/instantdex_append.json",GLOBAL_DBDIR);
}
else
{
sprintf(fname,"%s/instantdex_%s.json",GLOBAL_DBDIR,coinaddr);
sprintf(afname,"%s/instantdex_%s_append.json",GLOBAL_DBDIR,coinaddr);
}
}
cJSON *LP_instantdex_txids(int32_t appendonly,char *coinaddr)
{
char *filestr,fname[1024],afname[1024]; long fsize; cJSON *retjson=0;
LP_instantdex_txidaddfname(fname,afname,coinaddr);
if ( (filestr= OS_filestr(&fsize,appendonly != 0 ? afname : fname)) != 0 )
{
retjson = cJSON_Parse(filestr);
free(filestr);
} else printf("couldnt open (%s) or (%s)\n",fname,afname);
return(retjson);
}
void LP_instantdex_filewrite(int32_t appendfile,cJSON *array,char *coinaddr)
{
FILE *fp; char *filestr,fname[1024],afname[1024];
LP_instantdex_txidaddfname(fname,afname,coinaddr);
if ( (fp= fopen(appendfile == 0 ? fname : afname,"wb")) != 0 )
{
filestr = jprint(array,0);
fwrite(filestr,1,strlen(filestr)+1,fp);
fclose(fp);
free(filestr);
}
}
void LP_instantdex_deposituniq(FILE *fp,bits256 txid)
{
int32_t i,n; bits256 prevtxid; char str[65];
n = (int32_t)(ftell(fp) / sizeof(txid));
for (i=0; i<n; i++)
{
fseek(fp,sizeof(prevtxid) * i,SEEK_SET);
fread(&prevtxid,1,sizeof(prevtxid),fp);
if ( bits256_cmp(prevtxid,txid) == 0 )
{
//printf("%s duplicate of deposits[%d]\n",bits256_str(str,prevtxid),i);
break;
}
}
if ( i == n )
{
fwrite(&txid,1,sizeof(txid),fp);
printf("uniq %s, ftell.%ld\n",bits256_str(str,txid),ftell(fp));
} else fseek(fp,n * sizeof(txid),SEEK_SET);
}
void LP_instantdex_filescreate(char *coinaddr)
{
char fname[512]; FILE *fp; bits256 txid; int32_t i,n; cJSON *array,*newarray,*txobj;
sprintf(fname,"%s/deposits.%s",GLOBAL_DBDIR,coinaddr), OS_compatible_path(fname);
if ( (fp= fopen(fname,"rb")) != 0 )
{
array = cJSON_CreateArray();
newarray = cJSON_CreateArray();
fseek(fp,0,SEEK_END);
n = (int32_t)(ftell(fp) / sizeof(txid));
for (i=0; i<n; i++)
{
fseek(fp,sizeof(txid) * i,SEEK_SET);
fread(&txid,1,sizeof(txid),fp);
jaddibits256(array,txid);
if ( (txobj= LP_gettxout("KMD",coinaddr,txid,0)) != 0 )
free_json(txobj);
else
{
char str[65]; printf("%s/v%d is already spent\n",bits256_str(str,txid),0);
continue;
}
jaddibits256(newarray,txid);
}
fclose(fp);
LP_instantdex_filewrite(0,newarray,coinaddr);
free_json(newarray);
LP_instantdex_filewrite(1,array,coinaddr);
free_json(array);
}
}
void LP_instantdex_depositadd(char *coinaddr,bits256 txid)
{
FILE *fp; struct iguana_info *coin; char fname[512],*addr; bits256 prevtxid; cJSON *array; int32_t i,n,iter;
coin = LP_coinfind("KMD");
sprintf(fname,"%s/deposits.%s",GLOBAL_DBDIR,coinaddr), OS_compatible_path(fname);
if ( (fp= fopen(fname,"rb+")) == 0 )
{
if ( (fp= fopen(fname,"wb+")) != 0 )
{
for (iter=0; iter<4; iter++)
{
if ( iter < 2 )
addr = coinaddr;
else addr = "";
if ( coin != 0 && (array= LP_instantdex_txids(iter&1,addr)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
prevtxid = jbits256i(array,i);
//char str[65]; printf("instantdex iter.%d i.%d check %s\n",iter,i,bits256_str(str,prevtxid));
if ( LP_instantdex_creditcalc(coin,0,prevtxid,coinaddr) > 0 )
{
LP_instantdex_deposituniq(fp,prevtxid);
fflush(fp);
}
}
}
free_json(array);
}
}
}
} else fseek(fp,0,SEEK_END);
if ( fp != 0 && bits256_nonz(txid) != 0 )
{
LP_instantdex_deposituniq(fp,txid);
fclose(fp);
}
LP_instantdex_filescreate(coinaddr);
}
int32_t LP_deposit_addr(char *p2shaddr,uint8_t *script,uint8_t taddr,uint8_t p2shtype,uint32_t timestamp,uint8_t *pubsecp33)
{
uint8_t elsepub33[33],p2sh_rmd160[20]; int32_t n;
decode_hex(elsepub33,33,BOTS_BONDPUBKEY33);
n = bitcoin_performancebond(p2sh_rmd160,script,0,timestamp,pubsecp33,elsepub33);
bitcoin_address(p2shaddr,taddr,p2shtype,script,n);
return(n);
}
char *LP_instantdex_deposit(struct iguana_info *coin,int32_t weeks,double amount,int32_t broadcast)
{
char p2shaddr[64],*retstr,*hexstr; uint8_t script[512]; int32_t weeki,scriptlen; cJSON *argjson,*retjson,*array,*item,*obj; uint32_t timestamp; bits256 txid,sendtxid; uint64_t amount64;
if ( strcmp(coin->symbol,"KMD") != 0 )
return(clonestr("{\"error\":\"instantdex deposit must be in KMD\"}"));
if ( amount < 10.0 )
return(clonestr("{\"error\":\"minimum instantdex deposit is 10 KMD\"}"));
if ( weeks <= 0 || weeks > 52 )
return(clonestr("{\"error\":\"weeks must be between 1 and 52\"}"));
if ( weeks > 0 )
{
timestamp = (uint32_t)time(NULL);
timestamp /= LP_WEEKMULT;
timestamp += weeks+2;
timestamp *= LP_WEEKMULT;
weeki = (timestamp - LP_FIRSTWEEKTIME) / LP_WEEKMULT;
if ( weeks >= 10000 )
return(clonestr("{\"error\":\"numweeks must be less than 10000\"}"));
} else timestamp = (uint32_t)time(NULL) + 300, weeki = 0;
scriptlen = LP_deposit_addr(p2shaddr,script,coin->taddr,coin->p2shtype,timestamp,G.LP_pubsecp);
argjson = cJSON_CreateObject();
array = cJSON_CreateArray();
item = cJSON_CreateObject();
jaddnum(item,p2shaddr,amount);
jaddi(array,item);
item = cJSON_CreateObject();
amount64 = (amount * SATOSHIDEN) / 1000;
amount64 = (amount64 / 10000) * 10000 + weeki;
jaddnum(item,BOTS_BONDADDRESS,dstr(amount64));
jaddi(array,item);
item = cJSON_CreateObject();
jaddnum(item,coin->smartaddr,0.0001);
jaddi(array,item);
jadd(argjson,"outputs",array);
//printf("deposit.(%s)\n",jprint(argjson,0));
if ( (retstr= LP_withdraw(coin,argjson)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( jobj(retjson,"result") != 0 )
jdelete(retjson,"result");
jaddstr(retjson,"address",p2shaddr);
jaddnum(retjson,"expiration",timestamp);
jaddnum(retjson,"deposit",amount);
if ( (obj= jobj(retjson,"complete")) != 0 && is_cJSON_True(obj) != 0 && (hexstr= jstr(retjson,"hex")) != 0 )
{
txid = jbits256(retjson,"txid");
if ( broadcast != 0 )
{
if (bits256_nonz(txid) != 0 )
{
sendtxid = LP_broadcast("deposit","KMD",hexstr,txid);
if ( bits256_cmp(sendtxid,txid) != 0 )
{
jaddstr(retjson,"error","broadcast txid mismatch");
jaddbits256(retjson,"broadcast",sendtxid);
free(retstr);
return(jprint(retjson,1));
}
else
{
jaddstr(retjson,"result","success");
jaddbits256(retjson,"broadcast",sendtxid);
LP_instantdex_depositadd(coin->smartaddr,txid);
free(retstr);
return(jprint(retjson,1));
}
}
else
{
jaddstr(retjson,"error","couldnt broadcast since no txid created");
free(retstr);
return(jprint(retjson,1));
}
}
else
{
jaddstr(retjson,"result","success");
free(retstr);
return(jprint(retjson,1));
}
}
else
{
jaddstr(retjson,"error","couldnt create deposit txid");
free(retstr);
return(jprint(retjson,1));
}
free_json(retjson);
}
free(retstr);
}
return(clonestr("{\"error\":\"error with LP_withdraw for instantdex deposit\"}"));
}
int64_t LP_claimtx(void *ctx,struct iguana_info *coin,bits256 *claimtxidp,bits256 utxotxid,int32_t utxovout,uint64_t satoshis,char *vinaddr,uint32_t claimtime,uint8_t *redeemscript,int32_t redeemlen)
{
uint8_t userdata[2]; char *signedtx; bits256 signedtxid,sendtxid; int32_t isbots,userdatalen; int64_t destamount,sum = 0;
if ( strcmp(coin->smartaddr,BOTS_BONDADDRESS) == 0 )
isbots = 1;
else isbots = 0;
userdata[0] = (isbots == 0) ? 0x51 : 0;
userdatalen = 1;
utxovout = 0;
memset(claimtxidp,0,sizeof(*claimtxidp));
char str[65]; printf("LP_claimtx satoshis %.8f %s/v%d\n",dstr(satoshis),bits256_str(str,utxotxid),utxovout);
if ( (signedtx= basilisk_swap_bobtxspend(&signedtxid,10000,"instantdexclaim",coin->symbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,ctx,G.LP_privkey,0,redeemscript,redeemlen,userdata,userdatalen,utxotxid,utxovout,coin->smartaddr,G.LP_pubsecp,0,claimtime,&destamount,0,0,vinaddr,1,coin->zcash)) != 0 )
{
printf("signedtx.(%s)\n",signedtx);
sendtxid = LP_broadcast("claim","KMD",signedtx,signedtxid);
if ( bits256_cmp(sendtxid,signedtxid) == 0 )
{
*claimtxidp = sendtxid;
sum += (satoshis - coin->txfee);
}
else printf("error sending %s\n",bits256_str(str,signedtxid));
free(signedtx);
} else printf("error claiming instantdex deposit %s/v%d %.8f\n",bits256_str(str,utxotxid),utxovout,dstr(satoshis));
return(sum);
}
int32_t LP_claim_submit(void *ctx,cJSON *txids,int64_t *sump,struct iguana_info *coin,bits256 utxotxid)
{
uint8_t redeemscript[512]; bits256 claimtxid; cJSON *txjson,*vout0,*vout1,*vout2,*vouts,*item; int32_t numvouts; char str[65],vinaddr[64],destaddr[64],checkaddr[64]; int32_t j,utxovout,flagi = 0,redeemlen,weeki,iter; int64_t weeksatoshis,satoshis; uint32_t expiration,claimtime;
if ( (txjson= LP_gettx(coin->symbol,utxotxid,1)) != 0 )
{
if ( (vouts= jarray(&numvouts,txjson,"vout")) != 0 && numvouts >= 3 )
{
vout0 = jitem(vouts,0);
LP_destaddr(vinaddr,vout0);
satoshis = LP_value_extract(vout0,1);
vout2 = jitem(vouts,2);
LP_destaddr(destaddr,vout2);
if ( strcmp(destaddr,coin->smartaddr) == 0 )
{
vout1 = jitem(vouts,1);
weeksatoshis = LP_value_extract(vout1,0);
weeki = (int32_t)(weeksatoshis % 10000);
for (iter=0; iter<2; iter++)
for (j=-168; j<=168; j++)
{
if ( iter == 1 )
expiration = ((weeki * LP_WEEKMULTBAD + j*3600) + LP_FIRSTWEEKTIME);
else expiration = ((weeki * LP_WEEKMULT + j*3600) + LP_FIRSTWEEKTIME);
redeemlen = LP_deposit_addr(checkaddr,redeemscript,coin->taddr,coin->p2shtype,expiration,G.LP_pubsecp);
if ( strcmp(checkaddr,vinaddr) == 0 )
{
flagi = 1;
claimtime = (uint32_t)time(NULL)-777;
item = cJSON_CreateObject();
jaddbits256(item,"txid",utxotxid);
jaddnum(item,"deposit",dstr(LP_value_extract(vout0,0)));
if ( coin->electrum == 0 )
jaddnum(item,"interest",dstr(satoshis)-dstr(LP_value_extract(vout0,0)));
else jaddnum(item,"interest",dstr(LP_komodo_interest(utxotxid,satoshis)));
if ( claimtime <= expiration )
{
printf("iter.%d j.%d claimtime.%u vs %u, wait %d seconds to %s claim %.8f\n",iter,j,claimtime,expiration,(int32_t)expiration-claimtime,bits256_str(str,utxotxid),dstr(satoshis));
jaddnum(item,"waittime",(int32_t)expiration-claimtime);
jaddi(txids,item);
break;
}
else
{
utxovout = 0;
*sump += LP_claimtx(ctx,coin,&claimtxid,utxotxid,utxovout,satoshis,vinaddr,claimtime,redeemscript,redeemlen);
if ( bits256_nonz(claimtxid) != 0 )
{
jaddbits256(item,"claimtxid",claimtxid);
jaddi(txids,item);
}
}
} //else printf("expiration.%u j.%d checkaddr.(%s) != vinaddr.%s\n",expiration,j,checkaddr,vinaddr);
if ( flagi != 0 )
break;
}
} else printf("vout2 dest.(%s) != %s\n",destaddr,coin->smartaddr);
} else printf("numvouts %d != 3\n",numvouts);
free_json(txjson);
} else printf("cant get transaction flagi.%d\n",flagi);
return(flagi);
}
char *LP_instantdex_claim(struct iguana_info *coin)
{
static void *ctx; static int32_t firsttime = 1;
int32_t i,n; cJSON *array,*txids,*newarray,*retjson; int64_t sum; bits256 utxotxid;
if ( ctx == 0 )
ctx = bitcoin_ctx();
if ( strcmp(coin->symbol,"KMD") != 0 )
return(clonestr("{\"error\":\"instantdex deposit must be in KMD\"}"));
sum = 0;
txids = cJSON_CreateArray();
newarray = cJSON_CreateArray();
if ( (array= LP_instantdex_txids(firsttime,coin->smartaddr)) != 0 )
{
printf("claiming from.(%s)\n",jprint(array,0));
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
utxotxid = jbits256i(array,i);
//char str[65]; printf("%s\n",bits256_str(str,utxotxid));
if ( LP_claim_submit(ctx,txids,&sum,coin,utxotxid) == 0 )
jaddibits256(newarray,utxotxid);
}
}
free_json(array);
}
firsttime = 0;
if ( cJSON_GetArraySize(newarray) > 0 )
LP_instantdex_filewrite(0,newarray,coin->smartaddr);
free_json(newarray);
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddnum(retjson,"claimed",dstr(sum));
jadd(retjson,"txids",txids);
return(jprint(retjson,1));
}
int64_t LP_instantdex_credit(int32_t dispflag,char *coinaddr,int64_t satoshis,int32_t weeki,char *p2shaddr,bits256 txid)
{
uint32_t timestamp; struct LP_address *ap; struct iguana_info *coin = LP_coinfind("KMD");
if ( coin != 0 )
{
timestamp = LP_FIRSTWEEKTIME + weeki*LP_WEEKMULT;
if ( (ap= LP_address(coin,coinaddr)) != 0 && time(NULL) < timestamp-60*3600 )
{
ap->instantdex_credits += satoshis;
ap->didinstantdex = 1;
if ( 0 && dispflag != 0 )
printf("InstantDEX credit.(%s) %.8f weeki.%d (%s) -> sum %.8f\n",coinaddr,dstr(satoshis),weeki,p2shaddr,dstr(ap->instantdex_credits));
return(satoshis);
} else printf("null ap.%p or expired %ld\n",ap,time(NULL) - (timestamp-60*3600));
}
return(0);
}
int64_t LP_instantdex_creditcalc(struct iguana_info *coin,int32_t dispflag,bits256 txid,char *refaddr)
{
cJSON *txjson,*vouts,*txobj,*item; int64_t satoshis=0,amount64; int32_t weeki,numvouts; char destaddr[64],p2shaddr[64];
if ( (txjson= LP_gettx(coin->symbol,txid,0)) != 0 )
{
// vout0 deposit, vout1 botsfee, vout2 smartaddress
if ( (vouts= jarray(&numvouts,txjson,"vout")) > 0 && numvouts >= 3 && LP_destaddr(destaddr,jitem(vouts,2)) == 0 )
{
if ( refaddr != 0 && strcmp(refaddr,destaddr) != 0 )
{
printf("LP_instantdex_creditcalc for (%s) but deposit sent for (%s)\n",refaddr,destaddr);
}
else
{
amount64 = LP_value_extract(jitem(vouts,1),0);
weeki = (amount64 % 10000);
item = jitem(vouts,0);
satoshis = LP_value_extract(item,0);
//char str[65]; printf("%s %s funded %.8f weeki.%d (%s)\n",bits256_str(str,txid),destaddr,dstr(satoshis),weeki,jprint(item,0));
if ( LP_destaddr(p2shaddr,item) == 0 )
{
if ( (txobj= LP_gettxout(coin->symbol,p2shaddr,txid,0)) != 0 )
{
free_json(txobj);
LP_instantdex_credit(dispflag,destaddr,satoshis,weeki,p2shaddr,txid);
} else printf("already spent\n");
} else printf("error getting p2shaddr.(%s)\n",p2shaddr);
}
}
free_json(txjson);
}
return(satoshis);
}
#ifdef bruteforce
void LP_instantdex_deposits(struct iguana_info *coin)
{
static int dispflag = 1;
cJSON *array,*item; int32_t i,n,height,vout; bits256 txid; struct LP_address *ap,*tmp;
if ( coin->electrum != 0 )//&& coin->electruminstantdex != 0 )
return;
HASH_ITER(hh,coin->addresses,ap,tmp)
{
ap->instantdex_credits = 0;
}
if ( (array= LP_listreceivedbyaddress("KMD",BOTS_BONDADDRESS)) != 0 )
{
//printf("instantdex.(%s)\n",jprint(array,0));
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
if ( coin->electrum != 0 )
{
item = jitem(array,i);
LP_listunspent_parseitem(coin,&txid,&vout,&height,item);
} else txid = jbits256i(array,i);
LP_instantdex_creditcalc(coin,dispflag,txid,0);
}
}
free_json(array);
}
dispflag = 0;
}
#endif
int64_t LP_dynamictrust(int64_t credits,bits256 pubkey,int64_t kmdvalue)
{
struct LP_pubswap *ptr,*tmp; struct LP_swapstats *sp; struct LP_pubkey_info *pubp; struct LP_address *ap; char coinaddr[64]; struct iguana_info *coin; int64_t swaps_kmdvalue = 0;
if ( (coin= LP_coinfind("KMD")) != 0 && (pubp= LP_pubkeyfind(pubkey)) != 0 )
{
bitcoin_address(coinaddr,coin->taddr,coin->pubtype,pubp->pubsecp,33);
DL_FOREACH_SAFE(pubp->bobswaps,ptr,tmp)
{
if ( (sp= ptr->swap) != 0 && LP_swap_finished(sp,1) == 0 )
swaps_kmdvalue += LP_kmdvalue(sp->Q.srccoin,sp->Q.satoshis);
}
DL_FOREACH_SAFE(pubp->aliceswaps,ptr,tmp)
{
if ( (sp= ptr->swap) != 0 && LP_swap_finished(sp,1) == 0 )
swaps_kmdvalue += LP_kmdvalue(sp->Q.destcoin,sp->Q.destsatoshis);
}
if ( credits == 0 && (ap= LP_address(coin,coinaddr)) != 0 )
credits = ap->instantdex_credits;
if ( credits != 0 && (swaps_kmdvalue+kmdvalue) > credits )
{
if ( 0 )
{
DL_FOREACH_SAFE(pubp->bobswaps,ptr,tmp)
{
if ( (sp= ptr->swap) != 0 && LP_swap_finished(sp,1) == 0 )
printf("unfinished bob %llu r%u-r%u src.%s %.8f dest.%s %.8f -> price %.8f value %.8f\n",(long long)sp->aliceid,sp->Q.R.requestid,sp->Q.R.quoteid,sp->Q.srccoin,dstr(sp->Q.satoshis),sp->Q.destcoin,dstr(sp->Q.destsatoshis),(double)sp->Q.destsatoshis/(sp->Q.satoshis+1),dstr(LP_kmdvalue(sp->Q.destcoin,sp->Q.destsatoshis)));
}
DL_FOREACH_SAFE(pubp->aliceswaps,ptr,tmp)
{
if ( (sp= ptr->swap) != 0 && LP_swap_finished(sp,1) == 0 )
printf("unfinished alice %llu r%u-r%u src.%s %.8f dest.%s %.8f -> price %.8f value %.8f\n",(long long)sp->aliceid,sp->Q.R.requestid,sp->Q.R.quoteid,sp->Q.srccoin,dstr(sp->Q.satoshis),sp->Q.destcoin,dstr(sp->Q.destsatoshis),(double)sp->Q.destsatoshis/(sp->Q.satoshis+1),dstr(LP_kmdvalue(sp->Q.destcoin,sp->Q.destsatoshis)));
}
}
printf("REJECT: %s instantdex_credits %.8f vs (%.8f + current %.8f)\n",coinaddr,dstr(credits),dstr(swaps_kmdvalue),dstr(kmdvalue));
}
if ( 0 && credits != 0 )
printf("%s %s othercredits %.8f debits %.8f + %.8f -> %.8f\n",coin->symbol,coinaddr,dstr(credits),dstr(swaps_kmdvalue),dstr(kmdvalue),dstr(credits - (swaps_kmdvalue+kmdvalue)));
return(credits - (swaps_kmdvalue+kmdvalue));
}
return(0);
}
int64_t LP_instantdex_proofcheck(char *coinaddr,cJSON *proof,int32_t num)
{
uint8_t rmd160[20],addrtype; int64_t credits=0; int32_t i,j; bits256 prevtxid,txid; char othersmartaddr[64]; struct iguana_info *coin; struct LP_address *ap = 0;
if ( (coin= LP_coinfind("KMD")) != 0 )
{
bitcoin_addr2rmd160(0,&addrtype,rmd160,coinaddr);
bitcoin_address(othersmartaddr,0,60,rmd160,20);
printf("proofcheck addrtype.%d (%s) -> %s\n",addrtype,coinaddr,othersmartaddr);
if ((ap= LP_address(coin,othersmartaddr)) != 0 )
{
ap->instantdex_credits = 0;
for (i=0; i<num; i++)
{
txid = jbits256i(proof,i);
for (j=0; j<i; j++)
{
prevtxid = jbits256i(proof,j);
if ( bits256_cmp(prevtxid,txid) == 0 )
break;
}
if ( j == i )
LP_instantdex_creditcalc(coin,1,txid,othersmartaddr);
}
credits = ap->instantdex_credits;
ap->didinstantdex = 1;
if ( ap->instantdex_credits > 0 )
printf("validated instantdex %s.[%d] proof.(%s) credits %.8f\n",othersmartaddr,num,jprint(proof,0),dstr(ap->instantdex_credits));
} //else printf("cant find ap.%p or already did %d %.8f\n",ap,ap!=0?ap->didinstantdex:-1,ap!=0?dstr(ap->instantdex_credits):-1);
}
return(credits);
}
int64_t LP_myzcredits()
{
cJSON *proof; struct iguana_info *coin; int64_t zcredits;
if ( (coin= LP_coinfind("KMD")) != 0 )
{
if ( (proof= LP_instantdex_txids(0,coin->smartaddr)) != 0 )
{
zcredits = LP_instantdex_proofcheck(coin->smartaddr,proof,cJSON_GetArraySize(proof));
free_json(proof);
return(zcredits);
}
}
return(0);
}
cJSON *LP_swapstats_item(struct LP_swapstats *sp,int32_t iambob)
{
struct iguana_info *bob,*alice; int32_t flag = 0; char *retstr,*swapstr; bits256 zero; cJSON *item,*reqjson,*swapjson;
item = cJSON_CreateObject();
jaddnum(item,"iambob",iambob);
jaddnum(item,"aliceid",sp->aliceid);
jaddnum(item,"requestid",sp->Q.R.requestid);
jaddnum(item,"quoteid",sp->Q.R.quoteid);
jaddstr(item,"base",sp->Q.srccoin);
jaddnum(item,"satoshis",sp->Q.satoshis);
jaddstr(item,"rel",sp->Q.destcoin);
jaddnum(item,"destsatoshis",sp->Q.destsatoshis);
jaddnum(item,"price",sp->Q.destsatoshis/((double)sp->Q.satoshis+1));
if ( LP_swap_finished(sp,1) == 0 )
{
jaddnum(item,"finished",sp->finished);
if ( sp->bobneeds_dPoW != 0 && (bob= LP_coinfind(sp->Q.srccoin)) != 0 )
{
jaddnum(item,"bobneeds_dPoW",sp->bobneeds_dPoW);
jaddnum(item,"bob_dPoWheight",bob->notarized);
if ( sp->bobneeds_dPoW == 1 )
flag = 1;
if ( bob->notarized == 0 )
LP_dPoW_request(bob);
}
if ( sp->aliceneeds_dPoW != 0 && (alice= LP_coinfind(sp->Q.destcoin)) != 0 )
{
jaddnum(item,"aliceneeds_dPoW",sp->aliceneeds_dPoW);
jaddnum(item,"alice_dPoWheight",alice->notarized);
if ( sp->aliceneeds_dPoW == 1 )
flag = 1;
if ( alice->notarized == 0 )
LP_dPoW_request(alice);
}
if ( flag != 0 )
{
reqjson = cJSON_CreateObject();
jaddstr(reqjson,"method","gettradestatus");
jadd64bits(reqjson,"aliceid",sp->aliceid);
memset(zero.bytes,0,sizeof(zero));
LP_reserved_msg(0,"","",zero,jprint(reqjson,1));
if ( (swapstr= basilisk_swapentry(sp->Q.R.requestid,sp->Q.R.quoteid,0)) != 0 )
{
if ( (swapjson= cJSON_Parse(swapstr)) != 0 )
{
if ( (retstr= LP_swapstatus_recv(swapjson)) != 0 )
free(retstr);
free_json(swapjson);
}
free(swapstr);
}
}
}
return(item);
}
cJSON *LP_myzdebits()
{
struct LP_pubswap *ptr,*tmp; struct LP_pubkey_info *pubp; struct LP_swapstats *sp; int64_t kmdvalue,swaps_kmdvalue = 0; struct iguana_info *coin; cJSON *retjson,*array,*item;
array = cJSON_CreateArray();
if ( (coin= LP_coinfind("KMD")) != 0 )
{
if ( (pubp= LP_pubkeyfind(G.LP_mypub25519)) != 0 )
{
DL_FOREACH_SAFE(pubp->bobswaps,ptr,tmp)
{
if ( (sp= ptr->swap) != 0 && LP_swap_finished(sp,1) == 0 )
{
kmdvalue = LP_kmdvalue(sp->Q.srccoin,sp->Q.satoshis);
item = LP_swapstats_item(sp,1);
jaddnum(item,"kmdvalue",dstr(kmdvalue));
jaddi(array,item);
swaps_kmdvalue += kmdvalue;
}
}
DL_FOREACH_SAFE(pubp->aliceswaps,ptr,tmp)
{
if ( (sp= ptr->swap) != 0 && LP_swap_finished(sp,1) == 0 )
{
kmdvalue = LP_kmdvalue(sp->Q.destcoin,sp->Q.destsatoshis);
item = LP_swapstats_item(sp,0);
jaddnum(item,"kmdvalue",dstr(kmdvalue));
jaddi(array,item);
swaps_kmdvalue += kmdvalue;
}
}
}
}
retjson = cJSON_CreateObject();
jadd(retjson,"swaps",array);
jaddnum(retjson,"pendingswaps",dstr(swaps_kmdvalue));
return(retjson);
}

928
iguana/exchanges/LP_nativeDEX.c

File diff suppressed because it is too large

149
iguana/exchanges/LP_network.c

@ -29,7 +29,7 @@ struct psock
uint16_t Numpsocks,Psockport = MIN_PSOCK_PORT;
#ifdef FROM_JS
/*
int32_t nn_socket(int domain, int protocol)
{
return(0);
@ -69,6 +69,7 @@ int32_t nn_shutdown(int s, int how)
int32_t nn_send(int s, const void *buf, size_t len, int flags)
{
printf("JS cant nn_send (%s)\n",(char *)buf);
return(0);
}
@ -90,24 +91,24 @@ const char *nn_strerror(int errnum)
int32_t nn_poll(struct nn_pollfd *fds, int nfds, int timeout)
{
return(0);
}*/
}
#endif
char *nanomsg_transportname(int32_t bindflag,char *str,char *ipaddr,uint16_t port)
{
sprintf(str,"ws://%s:%u",bindflag == 0 ? ipaddr : "*",port);
sprintf(str,"tcp://%s:%u",bindflag == 0 ? ipaddr : "*",port);
return(str);
}
char *nanomsg_transportname2(int32_t bindflag,char *str,char *ipaddr,uint16_t port)
/*char *nanomsg_transportname2(int32_t bindflag,char *str,char *ipaddr,uint16_t port)
{
sprintf(str,"tcp://%s:%u",bindflag == 0 ? ipaddr : "*",port+10);
sprintf(str,"ws://%s:%u",bindflag == 0 ? ipaddr : "*",port+10);
return(str);
}
/*int32_t _LP_send(int32_t sock,void *msg,int32_t sendlen,int32_t freeflag)
int32_t _LP_send(int32_t sock,void *msg,int32_t sendlen,int32_t freeflag)
{
int32_t sentbytes;
if ( sock < 0 )
@ -139,7 +140,7 @@ struct LP_queue
{
struct LP_queue *next,*prev;
int32_t sock,peerind,msglen;
uint32_t starttime,crc32;
uint32_t starttime,crc32,notready;
uint8_t msg[];
} *LP_Q;
int32_t LP_Qenqueued,LP_Qerrors,LP_Qfound;
@ -182,11 +183,11 @@ bits256 LP_calc_magic(uint8_t *msg,int32_t len)
sum += (OS_milliseconds() - millis);
nsum += n;
counter++;
if ( n > maxn || (rand() % 100) == 0 )
if ( n > maxn || (LP_rand() % 10000) == 0 )
{
if ( n > maxn )
{
printf("LP_calc_magic maxn.%d <- %d\n",maxn,n);
printf("LP_calc_magic maxn.%d <- %d | ",maxn,n);
maxn = n;
}
printf("millis %.3f ave %.3f, aveiters %.1f\n",OS_milliseconds() - millis,sum/counter,(double)nsum/counter);
@ -236,7 +237,7 @@ int32_t LP_crc32find(int32_t *duplicatep,int32_t ind,uint32_t crc32)
break;
}
if ( i >= sizeof(crcs)/sizeof(*crcs) )
i = (rand() % (sizeof(crcs)/sizeof(*crcs)));
i = (LP_rand() % (sizeof(crcs)/sizeof(*crcs)));
return(i);
}
else
@ -264,87 +265,17 @@ int32_t LP_peerindsock(int32_t *peerindp)
return(-1);
}
void queue_loop(void *arg)
{
struct LP_queue *ptr,*tmp; int32_t sentbytes,nonz,flag,duplicate,n=0;
while ( 1 )
{
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;
DL_FOREACH_SAFE(LP_Q,ptr,tmp)
{
n++;
flag = 0;
if ( ptr->sock >= 0 )
{
if ( LP_sockcheck(ptr->sock) > 0 )
{
bits256 magic;
magic = LP_calc_magic(ptr->msg,(int32_t)(ptr->msglen - sizeof(bits256)));
memcpy(&ptr->msg[ptr->msglen - sizeof(bits256)],&magic,sizeof(magic));
if ( (sentbytes= nn_send(ptr->sock,ptr->msg,ptr->msglen,0)) != ptr->msglen )
printf("%d LP_send sent %d instead of %d\n",n,sentbytes,ptr->msglen);
ptr->sock = -1;
if ( ptr->peerind > 0 )
ptr->starttime = (uint32_t)time(NULL);
else flag = 1;
} //else printf("sock not ready to send.%d\n",ptr->msglen);
}
else if ( 0 && time(NULL) > ptr->starttime+13 )
{
LP_crc32find(&duplicate,-1,ptr->crc32);
if ( duplicate > 0 )
{
LP_Qfound++;
if ( (LP_Qfound % 100) == 0 )
printf("found.%u Q.%d err.%d match.%d\n",ptr->crc32,LP_Qenqueued,LP_Qerrors,LP_Qfound);
flag = 1;
}
else if ( 0 ) // too much beyond duplicate filter when network is busy
{
printf("couldnt find.%u peerind.%d Q.%d err.%d match.%d\n",ptr->crc32,ptr->peerind,LP_Qenqueued,LP_Qerrors,LP_Qfound);
ptr->peerind++;
if ( (ptr->sock= LP_peerindsock(&ptr->peerind)) < 0 )
{
printf("%d no more peers to try at peerind.%d %p Q_LP.%p\n",n,ptr->peerind,ptr,LP_Q);
flag = 1;
LP_Qerrors++;
}
}
}
if ( flag != 0 )
{
nonz++;
portable_mutex_lock(&LP_networkmutex);
DL_DELETE(LP_Q,ptr);
portable_mutex_unlock(&LP_networkmutex);
free(ptr);
ptr = 0;
}
}
if ( arg == 0 )
break;
//if ( n != 0 )
// printf("LP_Q.[%d]\n",n);
if ( nonz == 0 )
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 maxind,peerind = 0; //sentbytes,
if ( sock0 < 0 && sock1 < 0 )
{
if ( (maxind= LP_numpeers()) > 0 )
peerind = (rand() % maxind) + 1;
peerind = (LP_rand() % maxind) + 1;
else peerind = 1;
sock0 = LP_peerindsock(&peerind);
if ( (maxind= LP_numpeers()) > 0 )
peerind = (rand() % maxind) + 1;
peerind = (LP_rand() % maxind) + 1;
else peerind = 1;
sock1 = LP_peerindsock(&peerind);
}
@ -373,9 +304,14 @@ void LP_broadcast_finish(int32_t pubsock,char *base,char *rel,uint8_t *msg,cJSON
msglen = (int32_t)strlen((char *)msg) + 1;
if ( crc32 == 0 )
crc32 = calc_crc32(0,&msg[2],msglen - 2);
#ifdef FROM_MARKETMAKER
if ( G.LP_IAMLP == 0 )
#else
if ( IAMLP == 0 )
#endif
{
free(msg);
//printf("broadcast %s\n",jstr(argjson,"method"));
jdelete(argjson,"method");
jaddstr(argjson,"method","broadcast");
if ( jobj(argjson,"timestamp") == 0 )
@ -473,8 +409,11 @@ void LP_psockloop(void *_ptr) // printouts seem to be needed for forwarding to w
{
static struct nn_pollfd *pfds;
int32_t i,n,nonz,iter,retval,sentbytes,size=0,sendsock = -1; uint32_t now; struct psock *ptr=0; void *buf=0; char keepalive[512];
strcpy(LP_psockloop_stats.name,"LP_psockloop");
LP_psockloop_stats.threshold = 200.;
while ( 1 )
{
LP_millistats_update(&LP_psockloop_stats);
now = (uint32_t)time(NULL);
if ( buf != 0 && ptr != 0 && sendsock >= 0 )
{
@ -518,13 +457,20 @@ void LP_psockloop(void *_ptr) // printouts seem to be needed for forwarding to w
}
else if ( (pfds[n].revents & POLLIN) != 0 )
{
printf("publicsock.%d %s has pollin\n",ptr->publicsock,ptr->publicaddr);
//printf("publicsock.%d %s has pollin\n",ptr->publicsock,ptr->publicaddr);
buf = 0;
if ( (size= nn_recv(ptr->publicsock,&buf,NN_MSG,0)) > 0 )
{
ptr->lasttime = now;
sendsock = ptr->sendsock;
break;
}
else if ( buf != 0 )
{
nn_freemsg(buf);
buf = 0;
size = 0;
}
}
}
n++;
@ -551,12 +497,12 @@ void LP_psockloop(void *_ptr) // printouts seem to be needed for forwarding to w
sendsock = ptr->publicsock;
break;
}
else
{
nn_freemsg(buf);
buf = 0;
size = 0;
}
}
if ( buf != 0 )
{
nn_freemsg(buf);
buf = 0;
size = 0;
}
}
}
@ -724,17 +670,18 @@ char *LP_psock(char *myipaddr,int32_t ispaired)
both are combined in LP_psock_get
*/
char *issue_LP_psock(char *destip,uint16_t destport,int32_t ispaired)
{
char url[512],*retstr;
sprintf(url,"http://%s:%u/api/stats/psock?ispaired=%d",destip,destport,ispaired);
sprintf(url,"http://%s:%u/api/stats/psock?ispaired=%d",destip,destport-1,ispaired);
//return(LP_issue_curl("psock",destip,destport,url));
retstr = issue_curlt(url,LP_HTTP_TIMEOUT*3);
printf("issue_LP_psock got (%s) from %s\n",retstr,destip);
return(retstr);
}
uint16_t LP_psock_get(char *connectaddr,char *connectaddr2,char *publicaddr,int32_t ispaired)
uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired)
{
uint16_t publicport = 0; char *retstr,*addr; cJSON *retjson; struct LP_peerinfo *peer,*tmp;
HASH_ITER(hh,LP_peerinfos,peer,tmp)
@ -749,8 +696,8 @@ uint16_t LP_psock_get(char *connectaddr,char *connectaddr2,char *publicaddr,int3
safecopy(publicaddr,addr,128);
if ( (addr= jstr(retjson,"connectaddr")) != 0 )
safecopy(connectaddr,addr,128);
if ( (addr= jstr(retjson,"connectaddr2")) != 0 )
safecopy(connectaddr2,addr,128);
//if ( (addr= jstr(retjson,"connectaddr2")) != 0 )
// safecopy(connectaddr2,addr,128);
if ( publicaddr[0] != 0 && connectaddr[0] != 0 )
publicport = juint(retjson,"publicport");
free_json(retjson);
@ -766,9 +713,9 @@ uint16_t LP_psock_get(char *connectaddr,char *connectaddr2,char *publicaddr,int3
int32_t LP_initpublicaddr(void *ctx,uint16_t *mypullportp,char *publicaddr,char *myipaddr,uint16_t mypullport,int32_t ispaired)
{
int32_t nntype,pullsock,timeout; char bindaddr[128],bindaddr2[128],connectaddr[128],connectaddr2[128];
int32_t nntype,pullsock,timeout; char bindaddr[128],connectaddr[128];
*mypullportp = mypullport;
connectaddr2[0] = 0;
//connectaddr2[0] = 0;
if ( ispaired == 0 )
{
if ( LP_canbind != 0 )
@ -779,7 +726,7 @@ int32_t LP_initpublicaddr(void *ctx,uint16_t *mypullportp,char *publicaddr,char
{
nanomsg_transportname(0,publicaddr,myipaddr,mypullport);
nanomsg_transportname(1,bindaddr,myipaddr,mypullport);
nanomsg_transportname2(1,bindaddr2,myipaddr,mypullport);
//nanomsg_transportname2(1,bindaddr2,myipaddr,mypullport);
}
else
{
@ -791,7 +738,7 @@ int32_t LP_initpublicaddr(void *ctx,uint16_t *mypullportp,char *publicaddr,char
}
while ( *mypullportp == 0 )
{
if ( (*mypullportp= LP_psock_get(connectaddr,connectaddr2,publicaddr,ispaired)) != 0 )
if ( (*mypullportp= LP_psock_get(connectaddr,publicaddr,ispaired)) != 0 )
break;
sleep(10);
printf("try to get publicaddr again\n");
@ -810,8 +757,8 @@ int32_t LP_initpublicaddr(void *ctx,uint16_t *mypullportp,char *publicaddr,char
}
else
{
if ( connectaddr2[0] != 0 && nn_connect(pullsock,connectaddr2) > 0 )
printf("%s ",connectaddr2);
//if ( connectaddr2[0] != 0 && nn_connect(pullsock,connectaddr2) > 0 )
// printf("%s ",connectaddr2);
printf("nntype.%d NN_PAIR.%d connect to %s connectsock.%d\n",nntype,NN_PAIR,connectaddr,pullsock);
}
}
@ -822,8 +769,8 @@ int32_t LP_initpublicaddr(void *ctx,uint16_t *mypullportp,char *publicaddr,char
printf("bind to %s error for %s: %s\n",bindaddr,publicaddr,nn_strerror(nn_errno()));
exit(-1);
}
if ( nn_bind(pullsock,bindaddr2) >= 0 )
printf("bound to %s\n",bindaddr2);
//if ( nn_bind(pullsock,bindaddr2) >= 0 )
// printf("bound to %s\n",bindaddr2);
}
timeout = 1;
nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout));

1403
iguana/exchanges/LP_ordermatch.c

File diff suppressed because it is too large

156
iguana/exchanges/LP_peers.c

@ -31,7 +31,7 @@ struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port)
cJSON *LP_peerjson(struct LP_peerinfo *peer)
{
cJSON *item = cJSON_CreateObject();
jaddstr(item,"ipaddr",peer->ipaddr);
jaddstr(item,"isLP",peer->ipaddr);
jaddnum(item,"port",peer->port);
if ( strcmp(peer->ipaddr,LP_myipaddr) == 0 )
{
@ -49,15 +49,15 @@ char *LP_peers()
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
//if ( peer->errors < LP_MAXPEER_ERRORS )
if ( peer->isLP != 0 )
jaddi(peersjson,LP_peerjson(peer));
}
return(jprint(peersjson,1));
}
struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char *ipaddr,uint16_t port,uint16_t pushport,uint16_t subport,int32_t numpeers,int32_t numutxos,uint32_t sessionid)
struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char *ipaddr,uint16_t port,uint16_t pushport,uint16_t subport,int32_t isLP,uint32_t sessionid)
{
uint32_t ipbits; int32_t valid,pushsock,subsock,timeout; char checkip[64],subaddr2[64],pushaddr[64],pushaddr2[64],subaddr[64]; struct LP_peerinfo *peer = 0;
printf("addpeer (%s:%u) pushport.%u subport.%u\n",ipaddr,port,pushport,subport);
uint32_t ipbits; int32_t valid,pushsock,subsock,timeout; char checkip[64],pushaddr[64],subaddr[64]; struct LP_peerinfo *peer = 0;
#ifdef LP_STRICTPEERS
if ( strncmp("5.9.253",ipaddr,strlen("5.9.253")) != 0 )
return(0);
@ -68,6 +68,8 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char
{
if ( (peer= LP_peerfind(ipbits,port)) != 0 )
{
if ( isLP != 0 )
peer->isLP = isLP;
/*if ( numpeers > peer->numpeers )
peer->numpeers = numpeers;
if ( numutxos > peer->numutxos )
@ -77,6 +79,7 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char
}
else
{
//printf("addpeer (%s:%u) pushport.%u subport.%u\n",ipaddr,port,pushport,subport);
peer = calloc(1,sizeof(*peer));
if ( strcmp(peer->ipaddr,LP_myipaddr) == 0 )
peer->sessionid = G.LP_sessionid;
@ -85,24 +88,25 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char
strcpy(peer->ipaddr,ipaddr);
//peer->profitmargin = profitmargin;
peer->ipbits = ipbits;
peer->isLP = isLP;
peer->port = port;
peer->ip_port = ((uint64_t)port << 32) | ipbits;
if ( pushport != 0 && subport != 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 )
{
nanomsg_transportname(0,pushaddr,peer->ipaddr,pushport);
nanomsg_transportname2(0,pushaddr2,peer->ipaddr,pushport);
//nanomsg_transportname2(0,pushaddr2,peer->ipaddr,pushport);
valid = 0;
if ( nn_connect(pushsock,pushaddr) >= 0 )
valid++;
if ( nn_connect(pushsock,pushaddr2) >= 0 )
valid++;
//if ( nn_connect(pushsock,pushaddr2) >= 0 )
// valid++;
if ( valid > 0 )
{
timeout = 1;
nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
//maxsize = 2 * 1024 * 1024;
//nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDBUF,&maxsize,sizeof(maxsize));
printf("connected to push.(%s %s) pushsock.%d valid.%d\n",pushaddr,pushaddr2,pushsock,valid);
printf("connected to push.(%s) pushsock.%d valid.%d | ",pushaddr,pushsock,valid);
peer->connected = (uint32_t)time(NULL);
peer->pushsock = pushsock;
if ( (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 )
@ -111,20 +115,20 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char
nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout));
nn_setsockopt(subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0);
nanomsg_transportname(0,subaddr,peer->ipaddr,subport);
nanomsg_transportname2(0,subaddr2,peer->ipaddr,subport);
//nanomsg_transportname2(0,subaddr2,peer->ipaddr,subport);
valid = 0;
if ( nn_connect(subsock,subaddr) >= 0 )
valid++;
if ( nn_connect(subsock,subaddr2) >= 0 )
valid++;
//if ( nn_connect(subsock,subaddr2) >= 0 )
// valid++;
if ( valid > 0 )
{
peer->subsock = subsock;
printf("connected to sub.(%s %s) subsock.%d valid.%d\n",subaddr,subaddr2,peer->subsock,valid);
printf("connected to sub.(%s) subsock.%d valid.%d\n",subaddr,peer->subsock,valid);
}
else
{
printf("error connecting to subsock.%d (%s %s)\n",subsock,subaddr,subaddr2);
printf("error connecting to subsock.%d (%s)\n",subsock,subaddr);
nn_close(subsock);
subsock = -1;
}
@ -134,26 +138,26 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char
{
nn_close(pushsock);
pushsock = -1;
printf("error connecting to push.(%s %s)\n",pushaddr,pushaddr2);
printf("error connecting to push.(%s)\n",pushaddr);
}
} else printf("%s pushport.%u subport.%u pushsock.%d\n",ipaddr,pushport,subport,pushsock);
if ( peer->pushsock >= 0 && peer->subsock >= 0 )
{
printf("add peer %s\n",peer->ipaddr);
//printf("add peer %s\n",peer->ipaddr);
portable_mutex_lock(&LP_peermutex);
HASH_ADD(hh,LP_peerinfos,ip_port,sizeof(peer->ip_port),peer);
if ( mypeer != 0 )
{
mypeer->numpeers++;
printf("_LPaddpeer %s -> numpeers.%d mypubsock.%d other.(%d %d)\n",ipaddr,mypeer->numpeers,mypubsock,numpeers,numutxos);
printf("_LPaddpeer %s -> numpeers.%d mypubsock.%d other.(%d)\n",ipaddr,mypeer->numpeers,mypubsock,isLP);
} else peer->numpeers = 1; // will become mypeer
portable_mutex_unlock(&LP_peermutex);
if ( IAMLP != 0 && mypubsock >= 0 )
{
struct iguana_info *coin,*ctmp; bits256 zero; char busaddr[64];
memset(zero.bytes,0,sizeof(zero));
struct iguana_info *coin,*ctmp; char busaddr[64]; //
//memset(zero.bytes,0,sizeof(zero));
//LP_send(mypubsock,msg,(int32_t)strlen(msg)+1,1);
LP_reserved_msg("","",zero,jprint(LP_peerjson(peer),1));
//LP_reserved_msg(0,"","",zero,jprint(LP_peerjson(peer),1));
if ( 0 )
{
HASH_ITER(hh,LP_coins,coin,ctmp)
@ -202,67 +206,14 @@ int32_t LP_coinbus(uint16_t coin_busport)
return(bussock);
}
int32_t LP_peersparse(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now)
{
struct LP_peerinfo *peer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0;
if ( (array= cJSON_Parse(retstr)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( (argipaddr= jstr(item,"ipaddr")) != 0 && (argport= juint(item,"port")) != 0 )
{
if ( (pushport= juint(item,"push")) == 0 )
pushport = argport + 1;
if ( (subport= juint(item,"sub")) == 0 )
subport = argport + 2;
argipbits = (uint32_t)calc_ipbits(argipaddr);
if ( (peer= LP_peerfind(argipbits,argport)) == 0 )
{
peer = LP_addpeer(mypeer,mypubsock,argipaddr,argport,pushport,subport,jint(item,"numpeers"),jint(item,"numutxos"),juint(item,"session"));
}
if ( peer != 0 )
{
peer->lasttime = now;
if ( strcmp(argipaddr,destipaddr) == 0 && destport == argport && peer->numpeers != n )
peer->numpeers = n;
}
}
}
}
free_json(array);
}
return(n);
}
void LP_peersquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *myipaddr,uint16_t myport)
void LP_peer_recv(char *ipaddr,int32_t ismine)
{
char *retstr; struct LP_peerinfo *peer,*tmp; bits256 zero; uint32_t now,flag = 0;
peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport);
if ( (retstr= issue_LP_getpeers(destipaddr,destport,myipaddr,myport,mypeer!=0?mypeer->numpeers:0)) != 0 )
struct LP_peerinfo *peer;
if ( (peer= LP_peerfind((uint32_t)calc_ipbits(ipaddr),RPC_port)) != 0 )
{
//printf("got.(%s)\n",retstr);
now = (uint32_t)time(NULL);
LP_peersparse(mypeer,mypubsock,destipaddr,destport,retstr,now);
free(retstr);
if ( IAMLP != 0 )
{
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
if ( peer->lasttime != now )
{
printf("{%s:%u}.%d ",peer->ipaddr,peer->port,peer->lasttime - now);
flag++;
memset(&zero,0,sizeof(zero));
if ( (retstr= issue_LP_notify(destipaddr,destport,peer->ipaddr,peer->port,peer->numpeers,peer->sessionid,0,zero)) != 0 )
free(retstr);
}
}
if ( flag != 0 )
printf(" <- missing peers\n");
}
peer->numrecv++;
//if ( ismine != 0 )
peer->recvtime = (uint32_t)time(NULL);
}
}
@ -271,7 +222,8 @@ int32_t LP_numpeers()
struct LP_peerinfo *peer,*tmp; int32_t numpeers = 0;
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
numpeers++;
if ( peer->isLP != 0 )
numpeers++;
}
return(numpeers);
}
@ -279,23 +231,51 @@ int32_t LP_numpeers()
uint16_t LP_randpeer(char *destip)
{
struct LP_peerinfo *peer,*tmp; uint16_t port = 0; int32_t n,r,numpeers = 0;
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
numpeers++;
}
destip[0] = 0;
numpeers = LP_numpeers();
if ( numpeers > 0 )
{
r = rand() % numpeers;
r = LP_rand() % numpeers;
n = 0;
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
if ( n++ == r )
if ( peer->isLP != 0 )
{
strcpy(destip,peer->ipaddr);
port = peer->port;
break;
if ( n++ == r )
{
strcpy(destip,peer->ipaddr);
port = peer->port;
break;
}
}
}
}
return(port);
}
uint16_t LP_rarestpeer(char *destip)
{
struct LP_peerinfo *peer,*tmp,*rarest = 0; int32_t iter; uint32_t now;
now = (uint32_t)time(NULL);
destip[0] = 0;
for (iter=0; iter<2; iter++)
{
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
if ( strcmp(peer->ipaddr,LP_myipaddr) != 0 && iter == 0 && peer->recvtime < now-3600 )
continue;
if ( peer->isLP != 0 )
{
if ( rarest == 0 || peer->numrecv < rarest->numrecv )
rarest = peer;
}
}
if ( rarest != 0 )
break;
}
if ( rarest == 0 )
LP_randpeer(destip);
else strcpy(destip,rarest->ipaddr);
return(rarest != 0 ? rarest->port : RPC_port);
}

299
iguana/exchanges/LP_portfolio.c

@ -18,9 +18,52 @@
// marketmaker
//
char LP_portfolio_base[16],LP_portfolio_rel[16];
struct LP_portfoliotrade { double metric; char buycoin[65],sellcoin[65]; };
struct LP_autoprice_ref
{
char refbase[65],refrel[65],base[65],rel[65],fundbid[16],fundask[16];
double margin,factor,offset;
cJSON *fundvalue;
} LP_autorefs[100];
int32_t LP_autoprices,num_LP_autorefs;
char LP_portfolio_base[128],LP_portfolio_rel[128];
double LP_portfolio_relvolume;
void LP_portfolio_reset()
{
struct iguana_info *coin,*tmp; cJSON *fundjson; int32_t i; struct LP_autoprice_ref *ptr;
for (i=0; i<num_LP_autorefs; i++)
{
ptr = &LP_autorefs[i];
if ( (fundjson= ptr->fundvalue) != 0 )
{
ptr->fundvalue = 0;
free_json(fundjson);
}
}
memset(LP_autorefs,0,sizeof(LP_autorefs));
LP_autoprices = 0;
num_LP_autorefs = 0;
strcpy(LP_portfolio_base,"");
strcpy(LP_portfolio_rel,"");
LP_portfolio_relvolume = 0.;
HASH_ITER(hh,LP_coins,coin,tmp)
{
coin->maxamount = 0;
coin->perc = 0;
coin->goal = 0;
coin->goalperc = 0;
coin->relvolume = 0;
coin->force = 0;
coin->balanceA = 0;
coin->valuesumA = 0;
coin->balanceB = 0;
coin->valuesumB = 0;
}
}
cJSON *LP_portfolio_entry(struct iguana_info *coin)
{
cJSON *item = cJSON_CreateObject();
@ -48,9 +91,10 @@ cJSON *LP_portfolio_entry(struct iguana_info *coin)
uint64_t LP_balance(uint64_t *valuep,int32_t iambob,char *symbol,char *coinaddr)
{
cJSON *array,*item; int32_t i,n; uint64_t valuesum,satoshisum,value;
cJSON *array,*item; bits256 zero; int32_t i,n; uint64_t valuesum,satoshisum,value;
valuesum = satoshisum = 0;
if ( (array= LP_listunspent(symbol,coinaddr)) != 0 )
memset(zero.bytes,0,sizeof(zero));
if ( (array= LP_listunspent(symbol,coinaddr,zero,zero)) != 0 )
{
if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{
@ -63,7 +107,7 @@ uint64_t LP_balance(uint64_t *valuep,int32_t iambob,char *symbol,char *coinaddr)
}
free_json(array);
}
if ( (array= LP_inventory(symbol)) != 0 )
/*if ( (array= LP_inventory(symbol)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 && is_cJSON_Array(array) != 0 )
{
@ -75,8 +119,9 @@ uint64_t LP_balance(uint64_t *valuep,int32_t iambob,char *symbol,char *coinaddr)
}
}
free_json(array);
}
}*/
*valuep = valuesum;
satoshisum = valuesum;
return(satoshisum);
}
@ -94,7 +139,7 @@ char *LP_portfolio()
if ( iter == 0 )
{
//printf("from portfolio\n");
LP_privkey_init(-1,coin,G.LP_privkey,G.LP_mypub25519);
//LP_privkey_init(-1,coin,G.LP_privkey,G.LP_mypub25519);
coin->balanceA = LP_balance(&coin->valuesumA,0,coin->symbol,coin->smartaddr);
coin->balanceB = LP_balance(&coin->valuesumB,1,coin->symbol,coin->smartaddr);
if ( strcmp(coin->symbol,"KMD") != 0 )
@ -199,13 +244,6 @@ char *LP_portfolio_goal(char *symbol,double goal)
} else return(clonestr("{\"error\":\"cant set goal for inactive coin\"}"));
}
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)
{
struct LP_priceinfo *basepp,*relpp;
@ -219,57 +257,19 @@ struct LP_autoprice_ref
return(-1);
}*/
int32_t LP_autoprice(char *base,char *rel,cJSON *argjson)
{
//curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"MNZ\",\"rel\":\"KMD\",\"offset\":0.1,\"refbase\":\"KMD\",\refrel\":\"BTC\",\"factor\":15000,\"margin\":0.01}"
struct LP_priceinfo *basepp,*relpp; int32_t i; char *refbase,*refrel; double minprice,margin,offset,factor;
//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 *basepp,struct LP_priceinfo *relpp,double price,char *refbase,char *refrel)
{
static uint32_t lasttime;
double margin,minprice,newprice,oppomargin,factor,offset; double bid,ask; int32_t changed;
double margin,minprice,newprice,oppomargin,fixedprice,factor,offset; double bid,ask; int32_t changed;
margin = basepp->margins[relpp->ind];
oppomargin = relpp->margins[basepp->ind];
if ( (fixedprice= basepp->fixedprices[relpp->ind]) > SMALLVAL )
{
LP_mypriceset(&changed,relpp->symbol,basepp->symbol,fixedprice);
//printf("autoprice FIXED %s/%s <- %.8f\n",basepp->symbol,relpp->symbol,fixedprice);
LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,relpp->symbol,basepp->symbol,fixedprice);
return;
}
if ( margin != 0. || oppomargin != 0. )
{
offset = basepp->offsets[relpp->ind];
@ -293,8 +293,6 @@ void LP_autopriceset(void *ctx,int32_t dir,struct LP_priceinfo *basepp,struct LP
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);
@ -313,7 +311,7 @@ double LP_pricesparse(void *ctx,int32_t trexflag,char *retstr,struct LP_priceinf
{
//{"success":true,"message":"","result":[{"MarketName":"BTC-KMD","High":0.00040840,"Low":0.00034900,"Volume":328042.46061669,"Last":0.00037236,"BaseVolume":123.36439511,"TimeStamp":"2017-07-15T13:50:21.87","Bid":0.00035721,"Ask":0.00037069,"OpenBuyOrders":343,"OpenSellOrders":1690,"PrevDay":0.00040875,"Created":"2017-02-11T23:04:01.853"},
//{"TradePairId":4762,"Label":"WAVES/BTC","AskPrice":0.00099989,"BidPrice":0.00097350,"Low":0.00095000,"High":0.00108838,"Volume":6501.24403100,"LastPrice":0.00098028,"BuyVolume":1058994.86554882,"SellVolume":2067.87377158,"Change":-7.46,"Open":0.00105926,"Close":0.00098028,"BaseVolume":6.52057452,"BuyBaseVolume":2.33098660,"SellBaseVolume":1167.77655709},
int32_t i,j,n,iter; double price,kmdbtc,bid,ask,nxtkmd=0.; struct LP_priceinfo *coinpp,*refpp; char symbol[16],*name,*refcoin; cJSON *retjson,*array,*item;
int32_t i,j,n,iter; double price,kmdbtc,bid,ask,nxtkmd=0.; struct LP_priceinfo *coinpp,*refpp; char symbol[65],*name,*refcoin; cJSON *retjson,*array,*item;
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
//printf("got.(%s)\n",retstr);
@ -404,7 +402,7 @@ double LP_pricesparse(void *ctx,int32_t trexflag,char *retstr,struct LP_priceinf
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,*basepp,*relpp;
char *retstr,*base,*rel; cJSON *retjson,*bid,*ask,*fundjson,*argjson; uint64_t bidsatoshis,asksatoshis; int32_t i,changed; double nxtkmd,price,factor,offset,newprice,margin,price_btc,price_usd,kmd_btc,kmd_usd; 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");
@ -463,18 +461,157 @@ void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp)
}
}
}
kmd_btc = LP_CMCbtcprice(&kmd_usd,"komodo");
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);
rel = LP_autorefs[i].rel;
base = LP_autorefs[i].base;
margin = LP_autorefs[i].margin;
offset = LP_autorefs[i].offset;
factor = LP_autorefs[i].factor;
if ( (argjson= LP_autorefs[i].fundvalue) != 0 )
{
if ( (fundjson= LP_fundvalue(argjson)) != 0 )
{
if ( jint(fundjson,"missing") == 0 )
{
if ( LP_autorefs[i].fundbid[0] != 0 && (price= jdouble(fundjson,LP_autorefs[i].fundbid)) > SMALLVAL )
{
newprice = (1. / price) * (1. + margin);
LP_mypriceset(&changed,rel,base,newprice);
LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,rel,base,newprice);
//printf("fundbid %.8f margin %.8f newprice %.8f\n",price,margin,newprice);
}
if ( LP_autorefs[i].fundask[0] != 0 && (price= jdouble(fundjson,LP_autorefs[i].fundask)) > SMALLVAL )
{
newprice = (price * (1. + margin));
LP_mypriceset(&changed,base,rel,newprice);
LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,base,rel,newprice);
//printf("fundask %.8f margin %.8f newprice %.8f\n",price,margin,newprice);
}
}
free_json(fundjson);
}
}
else if ( strcmp(LP_autorefs[i].refrel,"coinmarketcap") == 0 )
{
//printf("%s/%s for %s/%s margin %.8f\n",base,rel,LP_autorefs[i].refbase,LP_autorefs[i].refrel,margin);
if ( (price_btc= LP_CMCbtcprice(&price_usd,LP_autorefs[i].refbase)) > SMALLVAL )
{
if ( strcmp(rel,"KMD") == 0 )
price = kmd_btc / price_btc;
else if ( strcmp(rel,"BTC") == 0 )
price = 1. / price_btc;
else continue;
if ( factor > 0. )
price = (price * factor) + offset;
newprice = (price * (1. + margin));
LP_mypriceset(&changed,rel,base,newprice);
LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,rel,base,newprice);
printf("price %.8f margin %.8f newprice %.8f %.8f\n",price,margin,newprice,(1. / price) * (1. + margin));
newprice = (1. / price) * (1. + margin);
LP_mypriceset(&changed,base,rel,newprice);
LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,base,rel,newprice);
}
}
else
{
basepp = LP_priceinfofind(base);
relpp = LP_priceinfofind(rel);
if ( basepp != 0 && relpp != 0 )
{
//printf("check ref-autoprice %s/%s %f %f\n",LP_autorefs[i].refbase,LP_autorefs[i].refrel,relpp->fixedprices[basepp->ind],basepp->fixedprices[relpp->ind]);
LP_autopriceset(ctx,1,basepp,relpp,0.,LP_autorefs[i].refbase,LP_autorefs[i].refrel);
}
}
}
}
int32_t LP_autoprice(void *ctx,char *base,char *rel,cJSON *argjson)
{
//curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"MNZ\",\"rel\":\"KMD\",\"offset\":0.1,\"refbase\":\"KMD\",\refrel\":\"BTC\",\"factor\":15000,\"margin\":0.01}"
struct LP_priceinfo *basepp,*relpp; int32_t i,retval = -1; char *fundvalue_bid,*fundvalue_ask,*refbase="",*refrel=""; double minprice,margin,offset,factor,fixedprice; cJSON *fundvalue;
//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");
fixedprice = jdouble(argjson,"fixed");
basepp->fixedprices[relpp->ind] = fixedprice;
basepp->minprices[relpp->ind] = minprice;
basepp->margins[relpp->ind] = margin;
basepp->offsets[relpp->ind] = offset;
basepp->factors[relpp->ind] = factor;
refbase = jstr(argjson,"refbase");
refrel = jstr(argjson,"refrel");
fundvalue_bid = jstr(argjson,"fundvalue_bid");
fundvalue_ask = jstr(argjson,"fundvalue_ask");
if ( fundvalue_bid != 0 || fundvalue_ask != 0 || fixedprice > SMALLVAL || (refbase != 0 && refrel != 0) )
{
if ( fixedprice > SMALLVAL )
{
refbase = base;
refrel = rel;
}
for (i=0; i<num_LP_autorefs; i++)
{
if ( strcmp(base,LP_autorefs[i].base) == 0 && strcmp(rel,LP_autorefs[i].rel) == 0 )
{
if ( fundvalue_bid != 0 || fundvalue_ask != 0 )
{
fundvalue = jduplicate(argjson);
jdelete(fundvalue,"method");
jaddstr(fundvalue,"method","fundvalue");
LP_autorefs[i].fundvalue = fundvalue;
safecopy(LP_autorefs[i].fundbid,fundvalue_bid,sizeof(LP_autorefs[i].fundbid));
safecopy(LP_autorefs[i].fundask,fundvalue_ask,sizeof(LP_autorefs[i].fundask));
}
LP_autorefs[i].margin = margin;
LP_autorefs[i].factor = factor;
LP_autorefs[i].offset = offset;
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) )
{
if ( fundvalue_bid != 0 || fundvalue_ask != 0 )
{
fundvalue = jduplicate(argjson);
jdelete(fundvalue,"method");
jaddstr(fundvalue,"method","fundvalue");
LP_autorefs[num_LP_autorefs].fundvalue = fundvalue;
safecopy(LP_autorefs[num_LP_autorefs].fundbid,fundvalue_bid,sizeof(LP_autorefs[num_LP_autorefs].fundbid));
safecopy(LP_autorefs[num_LP_autorefs].fundask,fundvalue_ask,sizeof(LP_autorefs[num_LP_autorefs].fundask));
}
LP_autorefs[num_LP_autorefs].margin = margin;
LP_autorefs[num_LP_autorefs].factor = factor;
LP_autorefs[num_LP_autorefs].offset = offset;
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 fixed %.8f\n",num_LP_autorefs,refbase,refrel,base,rel,factor,offset,margin,fixedprice);
num_LP_autorefs++;
}
}
LP_autoprices++;
retval = 0;
}
//LP_autoprice_iter(ctx,LP_priceinfofind("BTC"));
return(retval);
}
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)
{
char *retstr2; double bid,ask,maxprice; bits256 zero; uint32_t requestid,quoteid,iter,i; cJSON *retjson2;
char *retstr2; uint64_t txfee,desttxfee; double bid,ask,maxprice; bits256 zero; uint32_t requestid,quoteid,iter,i; cJSON *retjson2; struct LP_utxoinfo A; struct LP_address_utxo *utxos[1000]; int32_t max=(int32_t)(sizeof(utxos)/sizeof(*utxos));
LP_txfees(&txfee,&desttxfee,buy->symbol,sell->symbol);
requestid = quoteid = 0;
LP_myprice(&bid,&ask,buy->symbol,sell->symbol);
maxprice = ask;
@ -492,10 +629,11 @@ int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,str
{
if ( relvolume < dstr(LP_MIN_TXFEE) )
break;
if ( LP_utxo_bestfit(sell->symbol,SATOSHIDEN * relvolume) != 0 )
if ( LP_address_myutxopair(&A,0,utxos,max,sell,sell->symbol,txfee,relvolume,maxprice,desttxfee) == 0 )
//if ( LP_utxo_bestfit(sell->symbol,SATOSHIDEN * relvolume) != 0 )
{
memset(zero.bytes,0,sizeof(zero));
if ( (retstr2= LP_autobuy(ctx,"127.0.0.1",-1,buy->symbol,sell->symbol,maxprice,relvolume,60,24*3600,gui,LP_lastnonce+1,zero)) != 0 )
if ( (retstr2= LP_autobuy(ctx,"127.0.0.1",-1,buy->symbol,sell->symbol,maxprice,relvolume,60,24*3600,gui,LP_lastnonce+1,zero,1)) != 0 )
{
if ( (retjson2= cJSON_Parse(retstr2)) != 0 )
{
@ -516,7 +654,8 @@ int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,str
for (i=0; i<100; i++)
{
relvolume *= .99;
if ( LP_utxo_bestfit(sell->symbol,SATOSHIDEN * relvolume) != 0 )
if ( LP_address_myutxopair(&A,0,utxos,max,sell,sell->symbol,txfee,relvolume,maxprice,desttxfee) == 0 )
//if ( LP_utxo_bestfit(sell->symbol,SATOSHIDEN * relvolume) != 0 )
{
printf("i.%d relvolume %.8f from %.8f\n",i,relvolume,sell->relvolume);
break;
@ -538,8 +677,6 @@ int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,str
else return(-1);
}
struct LP_portfoliotrade { double metric; char buycoin[16],sellcoin[16]; };
int32_t LP_portfolio_order(struct LP_portfoliotrade *trades,int32_t max,cJSON *array)
{
int32_t i,j,m,n = 0; cJSON *item; struct LP_portfoliotrade coins[256];
@ -586,15 +723,19 @@ int32_t LP_portfolio_order(struct LP_portfoliotrade *trades,int32_t max,cJSON *a
return(n);
}
void prices_loop(void *arg)
void prices_loop(void *ctx)
{
char *retstr; cJSON *retjson,*array; char *buycoin,*sellcoin; struct iguana_info *buy,*sell; uint32_t requestid,quoteid; int32_t i,n,m; struct LP_portfoliotrade trades[256]; struct LP_priceinfo *btcpp; void *ctx = bitcoin_ctx();
char *retstr; cJSON *retjson,*array; char *buycoin,*sellcoin; struct iguana_info *buy,*sell; uint32_t requestid,quoteid; int32_t i,n,m; struct LP_portfoliotrade trades[256]; struct LP_priceinfo *btcpp;
strcpy(prices_loop_stats.name,"prices_loop");
prices_loop_stats.threshold = 91000.;
while ( 1 )
{
//printf("prices loop autoprices.%d autorefs.%d\n",LP_autoprices,num_LP_autorefs);
LP_millistats_update(&prices_loop_stats);
LP_tradebots_timeslice(ctx);
if ( (btcpp= LP_priceinfofind("BTC")) == 0 )
{
if ( arg == 0 )
return;
printf("prices_loop BTC not in LP_priceinfofind\n");
sleep(60);
continue;
}
@ -628,9 +769,7 @@ void prices_loop(void *arg)
}
free(retstr);
}
if ( arg == 0 )
return;
sleep(60);
sleep(30);
}
}

489
iguana/exchanges/LP_prices.c

@ -18,23 +18,29 @@
// marketmaker
//
struct LP_orderbookentry { bits256 pubkey; double price; uint64_t minsatoshis,maxsatoshis,depth; uint32_t timestamp; int32_t numutxos; char coinaddr[64]; };
struct LP_orderbookentry
{
bits256 pubkey;
double price;
int64_t avesatoshis,maxsatoshis,depth,dynamictrust;
uint32_t timestamp;
int32_t numutxos;
char coinaddr[64];
};
struct LP_priceinfo
{
char symbol[16];
char symbol[68];
uint64_t coinbits;
int32_t ind,pad;
double diagval,high[2],low[2],last[2],bid[2],ask[2]; //volume,btcvolume,prevday; // mostly bittrex info
double diagval,high[2],low[2],last[2],bid[2],ask[2];
double relvals[LP_MAXPRICEINFOS];
double myprices[LP_MAXPRICEINFOS];
double minprices[LP_MAXPRICEINFOS]; // autoprice
double fixedprices[LP_MAXPRICEINFOS]; // fixedprices
double margins[LP_MAXPRICEINFOS];
double offsets[LP_MAXPRICEINFOS];
double factors[LP_MAXPRICEINFOS];
//double maxprices[LP_MAXPRICEINFOS]; // autofill of base/rel
//double relvols[LP_MAXPRICEINFOS];
FILE *fps[LP_MAXPRICEINFOS];
} LP_priceinfos[LP_MAXPRICEINFOS];
int32_t LP_numpriceinfos;
@ -47,6 +53,98 @@ struct LP_cacheinfo
uint32_t timestamp;
} *LP_cacheinfos;
void LP_priceinfos_clear()
{
int32_t i; struct LP_priceinfo *pp;
for (i=0; i<LP_numpriceinfos; i++)
{
pp = &LP_priceinfos[i];
memset(pp->myprices,0,sizeof(pp->myprices));
memset(pp->minprices,0,sizeof(pp->minprices));
memset(pp->fixedprices,0,sizeof(pp->fixedprices));
memset(pp->margins,0,sizeof(pp->margins));
memset(pp->offsets,0,sizeof(pp->offsets));
memset(pp->factors,0,sizeof(pp->factors));
}
}
float LP_pubkey_price(int32_t *numutxosp,int64_t *avesatoshisp,int64_t *maxsatoshisp,struct LP_pubkey_info *pubp,uint32_t baseind,uint32_t relind)
{
struct LP_pubkey_quote *pq,*tmp; int32_t scale; int64_t scale64;
*numutxosp = 0;
*avesatoshisp = *maxsatoshisp = 0;
DL_FOREACH_SAFE(pubp->quotes,pq,tmp)
{
if ( baseind == pq->baseind && relind == pq->relind )
{
if ( (scale= pq->scale) == 0 )
pq->scale = scale = 6;
scale64 = 1;
while ( scale > 0 )
{
scale64 *= 10;
scale--;
}
*numutxosp = pq->numutxos;
*avesatoshisp = pq->aveutxo * scale64;
*maxsatoshisp = pq->maxutxo * scale64;
return(pq->price);
}
}
return(0);
}
void LP_pubkey_update(struct LP_pubkey_info *pubp,uint32_t baseind,uint32_t relind,float price,int64_t balance,char *utxocoin,int32_t numutxos,int64_t minutxo,int64_t maxutxo)
{
struct LP_pubkey_quote *pq,*tmp; int64_t aveutxo,scale64,ave64,max64; int32_t scale;
DL_FOREACH_SAFE(pubp->quotes,pq,tmp)
{
if ( baseind == pq->baseind && relind == pq->relind )
break;
pq = 0;
}
if ( pq == 0 )
{
pq = calloc(1,sizeof(*pq));
pq->baseind = baseind;
pq->relind = relind;
pq->scale = 6; // millions of SATOSHIS, ie. 0.01
DL_APPEND(pubp->quotes,pq); // already serialized as only path is via stats_JSON()
//printf("create pubp quotes %d/%d\n",baseind,relind);
}
//printf("%d/%d price %.8f balance %.8f %s num.%d %.8f %.8f\n",baseind,relind,price,dstr(balance),utxocoin,numutxos,dstr(minutxo),dstr(maxutxo));
pq->price = price;
if ( utxocoin != 0 && utxocoin[0] != 0 )
{
if ( (scale= pq->scale) == 0 )
pq->scale = scale = 6;
scale64 = 1;
while ( scale > 0 )
{
scale64 *= 10;
scale--;
}
if ( numutxos >= 256 )
pq->numutxos = 255;
else pq->numutxos = numutxos;
aveutxo = (balance + (scale64>>1)) / numutxos;
if ( (ave64= (aveutxo / scale64)) >= (1LL << 32) )
ave64 = (1LL << 32) - 1;
max64 = ((maxutxo + (scale64>>1)) / scale64);
if ( max64 >= (1LL << 32) )
max64 = (1LL << 32) - 1;
pq->aveutxo = (uint32_t)ave64;
pq->maxutxo = (uint32_t)max64;
if ( 0 )
{
printf("price %.8f base.%s rel.%s utxocoin.%s balance %.8f numutxos.%u %u scale64 = %llu, ave %llu, ave32 %u (%llu) max32 %u (%llu)\n",price,LP_priceinfos[baseind].symbol,LP_priceinfos[relind].symbol,utxocoin,dstr(balance),numutxos,pq->numutxos,(long long)scale64,(long long)aveutxo,pq->aveutxo,(long long)pq->aveutxo * scale64,pq->maxutxo,(long long)pq->maxutxo * scale64);
int64_t avesatoshis,maxsatoshis;
price = LP_pubkey_price(&numutxos,&avesatoshis,&maxsatoshis,pubp,baseind,relind);
printf("checkprice %.8f numutxos.%d ave %.8f max %.8f\n",price,numutxos,dstr(avesatoshis),dstr(maxsatoshis));
}
}
}
struct LP_priceinfo *LP_priceinfo(int32_t ind)
{
if ( ind < 0 || ind >= LP_MAXPRICEINFOS )
@ -140,9 +238,9 @@ struct LP_cacheinfo *LP_cachefind(char *base,char *rel,bits256 txid,int32_t vout
return(ptr);
}
struct LP_pubkeyinfo *LP_pubkey_rmd160find(uint8_t rmd160[20])
struct LP_pubkey_info *LP_pubkey_rmd160find(uint8_t rmd160[20])
{
struct LP_pubkeyinfo *pubp=0,*tmp;
struct LP_pubkey_info *pubp=0,*tmp;
portable_mutex_lock(&LP_pubkeymutex);
HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp)
{
@ -156,7 +254,7 @@ struct LP_pubkeyinfo *LP_pubkey_rmd160find(uint8_t rmd160[20])
struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr)
{
uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkeyinfo *pubp;
uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkey_info *pubp;
HASH_FIND(hh,coin->addresses,coinaddr,strlen(coinaddr),ap);
if ( ap != 0 && bits256_nonz(ap->pubkey) == 0 )
{
@ -172,7 +270,7 @@ struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr)
struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr)
{
uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkeyinfo *pubp;
uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkey_info *pubp;
ap = calloc(1,sizeof(*ap));
safecopy(ap->coinaddr,coinaddr,sizeof(ap->coinaddr));
bitcoin_addr2rmd160(coin->taddr,&addrtype,rmd160,coinaddr);
@ -186,18 +284,18 @@ struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr)
return(ap);
}
struct LP_pubkeyinfo *LP_pubkeyfind(bits256 pubkey)
struct LP_pubkey_info *LP_pubkeyfind(bits256 pubkey)
{
struct LP_pubkeyinfo *pubp=0;
struct LP_pubkey_info *pubp=0;
portable_mutex_lock(&LP_pubkeymutex);
HASH_FIND(hh,LP_pubkeyinfos,&pubkey,sizeof(pubkey),pubp);
portable_mutex_unlock(&LP_pubkeymutex);
return(pubp);
}
struct LP_pubkeyinfo *LP_pubkeyadd(bits256 pubkey)
struct LP_pubkey_info *LP_pubkeyadd(bits256 pubkey)
{
char str[65]; struct LP_pubkeyinfo *pubp=0;
char str[65]; struct LP_pubkey_info *pubp=0;
portable_mutex_lock(&LP_pubkeymutex);
HASH_FIND(hh,LP_pubkeyinfos,&pubkey,sizeof(pubkey),pubp);
if ( pubp == 0 )
@ -220,7 +318,7 @@ struct LP_pubkeyinfo *LP_pubkeyadd(bits256 pubkey)
int32_t LP_pubkey_istrusted(bits256 pubkey)
{
struct LP_pubkeyinfo *pubp;
struct LP_pubkey_info *pubp;
if ( (pubp= LP_pubkeyadd(pubkey)) != 0 )
return(pubp->istrusted != 0);
return(0);
@ -228,7 +326,7 @@ int32_t LP_pubkey_istrusted(bits256 pubkey)
char *LP_pubkey_trustset(bits256 pubkey,uint32_t trustval)
{
struct LP_pubkeyinfo *pubp;
struct LP_pubkey_info *pubp;
if ( (pubp= LP_pubkeyadd(pubkey)) != 0 )
{
pubp->istrusted = trustval;
@ -239,7 +337,7 @@ char *LP_pubkey_trustset(bits256 pubkey,uint32_t trustval)
char *LP_pubkey_trusted()
{
struct LP_pubkeyinfo *pubp,*tmp; cJSON *array = cJSON_CreateArray();
struct LP_pubkey_info *pubp,*tmp; cJSON *array = cJSON_CreateArray();
HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp)
{
if ( pubp->istrusted != 0 )
@ -248,10 +346,10 @@ char *LP_pubkey_trusted()
return(jprint(array,1));
}
uint64_t LP_unspents_metric(struct iguana_info *coin,char *coinaddr)
int64_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,0);
cJSON *array,*item; int32_t i,n; int64_t metric=0,total;
//LP_listunspent_both(coin->symbol,coinaddr,0);
if ( (array= LP_address_utxos(coin,coinaddr,1)) != 0 )
{
total = 0;
@ -264,13 +362,14 @@ uint64_t LP_unspents_metric(struct iguana_info *coin,char *coinaddr)
}
}
metric = _LP_unspents_metric(total,n);
free_json(array);
}
return(metric);
}
cJSON *LP_pubkeyjson(struct LP_pubkeyinfo *pubp)
cJSON *LP_pubkeyjson(struct LP_pubkey_info *pubp)
{
int32_t baseid,relid; char *base,hexstr[67],hexstr2[67],sigstr[256]; double price; cJSON *item,*array,*obj;
int32_t baseid,relid,numutxos; int64_t avesatoshis,maxsatoshis; char *base,hexstr[67],hexstr2[67],sigstr[256]; double price; cJSON *item,*array,*obj;
obj = cJSON_CreateObject();
array = cJSON_CreateArray();
for (baseid=0; baseid<LP_numpriceinfos; baseid++)
@ -278,7 +377,7 @@ cJSON *LP_pubkeyjson(struct LP_pubkeyinfo *pubp)
base = LP_priceinfos[baseid].symbol;
for (relid=0; relid<LP_numpriceinfos; relid++)
{
price = pubp->matrix[baseid][relid];
price = LP_pubkey_price(&numutxos,&avesatoshis,&maxsatoshis,pubp,baseid,relid);//pubp->matrix[baseid][relid];
if ( LP_pricevalid(price) > 0 )
{
item = cJSON_CreateArray();
@ -305,7 +404,7 @@ cJSON *LP_pubkeyjson(struct LP_pubkeyinfo *pubp)
char *LP_prices()
{
struct LP_pubkeyinfo *pubp,*tmp; cJSON *array = cJSON_CreateArray();
struct LP_pubkey_info *pubp,*tmp; cJSON *array = cJSON_CreateArray();
HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp)
{
jaddi(array,LP_pubkeyjson(pubp));
@ -313,79 +412,6 @@ char *LP_prices()
return(jprint(array,1));
}
void LP_prices_parse(struct LP_peerinfo *peer,cJSON *obj)
{
struct LP_pubkeyinfo *pubp; struct LP_priceinfo *basepp,*relpp; uint32_t timestamp; bits256 pubkey; cJSON *asks,*item; uint8_t rmd160[20]; int32_t i,n,relid,mismatch; char *base,*rel,*hexstr; double askprice; uint32_t now;
now = (uint32_t)time(NULL);
pubkey = jbits256(obj,"pubkey");
if ( bits256_nonz(pubkey) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 )
{
if ( (hexstr= jstr(obj,"rmd160")) != 0 && strlen(hexstr) == 2*sizeof(rmd160) )
decode_hex(rmd160,sizeof(rmd160),hexstr);
if ( memcmp(pubp->rmd160,rmd160,sizeof(rmd160)) != 0 )
mismatch = 1;
else mismatch = 0;
if ( bits256_cmp(pubkey,G.LP_mypub25519) == 0 && mismatch == 0 )
peer->needping = 0;
LP_pubkey_sigcheck(pubp,obj);
timestamp = juint(obj,"timestamp");
if ( timestamp > now )
timestamp = now;
if ( timestamp >= pubp->timestamp && (asks= jarray(&n,obj,"asks")) != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(asks,i);
base = jstri(item,0);
rel = jstri(item,1);
askprice = jdoublei(item,2);
if ( LP_pricevalid(askprice) > 0 )
{
if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 )
{
//char str[65]; printf("gotprice %s %s/%s (%d/%d) %.8f\n",bits256_str(str,pubkey),base,rel,basepp->ind,relid,askprice);
pubp->matrix[basepp->ind][relid] = askprice;
pubp->timestamps[basepp->ind][relid] = timestamp;
if ( (relpp= LP_priceinfofind(rel)) != 0 )
{
dxblend(&basepp->relvals[relpp->ind],askprice,0.9);
dxblend(&relpp->relvals[basepp->ind],1. / askprice,0.9);
}
}
}
}
}
}
}
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 )
{
#ifdef FROM_JS
printf("%s\n",retstr);
#endif
if ( (array= cJSON_Parse(retstr)) != 0 )
{
if ( is_cJSON_Array(array) && (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
LP_prices_parse(peer,jitem(array,i));
}
free_json(array);
}
free(retstr);
}
if ( peer->needping != 0 )
{
//printf("%s needs ping\n",peer->ipaddr);
}
}
double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,int32_t vout)
{
struct LP_cacheinfo *ptr;
@ -393,14 +419,14 @@ double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,i
{
if ( qp != 0 )
(*qp) = ptr->Q;
if ( ptr->price == 0. && ptr->Q.satoshis != 0 )
if ( ptr->price == 0. && ptr->Q.satoshis > ptr->Q.txfee )
{
ptr->price = (double)ptr->Q.destsatoshis / ptr->Q.satoshis;
ptr->price = (double)ptr->Q.destsatoshis / (ptr->Q.satoshis - ptr->Q.txfee);
if ( LP_pricevalid(ptr->price) <= 0 )
ptr->price = 0.;
printf("LP_pricecache: set %s/%s ptr->price %.8f\n",base,rel,ptr->price);
}
printf(">>>>>>>>>> found %s/%s %.8f\n",base,rel,ptr->price);
//printf(">>>>>>>>>> found %s/%s %.8f\n",base,rel,ptr->price);
return(ptr->price);
}
//char str[65]; printf("cachemiss %s/%s %s/v%d\n",base,rel,bits256_str(str,txid),vout);
@ -414,10 +440,10 @@ void LP_priceinfoupdate(char *base,char *rel,double price)
{
if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
//dxblend(&basepp->relvals[relpp->ind],price,0.9);
//dxblend(&relpp->relvals[basepp->ind],1. / price,0.9);
basepp->relvals[relpp->ind] = price;
relpp->relvals[basepp->ind] = 1. / price;
dxblend(&basepp->relvals[relpp->ind],price,0.9);
dxblend(&relpp->relvals[basepp->ind],1. / price,0.9);
//basepp->relvals[relpp->ind] = price;
//relpp->relvals[basepp->ind] = 1. / price;
}
}
}
@ -483,21 +509,30 @@ char *LP_myprices()
int32_t LP_mypriceset(int32_t *changedp,char *base,char *rel,double price)
{
struct LP_priceinfo *basepp,*relpp; struct LP_pubkeyinfo *pubp;
struct LP_priceinfo *basepp,*relpp; struct LP_pubkey_info *pubp;
*changedp = 0;
if ( base != 0 && rel != 0 && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
if ( fabs(basepp->myprices[relpp->ind] - price)/price > 0.001 )
if ( price == 0. || fabs(basepp->myprices[relpp->ind] - price)/price > 0.001 )
*changedp = 1;
basepp->myprices[relpp->ind] = price; // ask
if ( price == 0. )
{
relpp->minprices[basepp->ind] = 0.;
relpp->fixedprices[basepp->ind] = 0.;
relpp->margins[basepp->ind] = 0.;
relpp->offsets[basepp->ind] = 0.;
relpp->factors[basepp->ind] = 0.;
}
//printf("LP_mypriceset base.%s rel.%s <- price %.8f\n",base,rel,price);
//relpp->myprices[basepp->ind] = (1. / price); // bid
if ( (pubp= LP_pubkeyadd(G.LP_mypub25519)) != 0 )
{
pubp->timestamp = (uint32_t)time(NULL);
pubp->matrix[basepp->ind][relpp->ind] = price;
pubp->timestamps[basepp->ind][relpp->ind] = pubp->timestamp;
LP_pubkey_update(pubp,basepp->ind,relpp->ind,price,0,0,0,0,0);
//pubp->matrix[basepp->ind][relpp->ind] = price;
//pubp->timestamps[basepp->ind][relpp->ind] = pubp->timestamp;
//pubp->matrix[relpp->ind][basepp->ind] = (1. / price);
}
return(0);
@ -672,16 +707,17 @@ 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)*0.8);
jaddnum(item,"avevolume",dstr(op->avesatoshis)*0.8);
jaddnum(item,"maxvolume",dstr(op->maxsatoshis)*0.8);
jaddnum(item,"depth",dstr(op->depth)*0.8);
jaddbits256(item,"pubkey",op->pubkey);
jaddnum(item,"age",time(NULL)-op->timestamp);
jaddnum(item,"zcredits",dstr(op->dynamictrust));
}
return(item);
}
struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,double price,int32_t numutxos,uint64_t minsatoshis,uint64_t maxsatoshis,bits256 pubkey,uint32_t timestamp,uint64_t balance)
struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,double price,int32_t numutxos,int64_t avesatoshis,int64_t maxsatoshis,bits256 pubkey,uint32_t timestamp,int64_t balance,int64_t dynamictrust)
{
struct LP_orderbookentry *op;
if ( (op= calloc(1,sizeof(*op))) != 0 )
@ -689,38 +725,38 @@ struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,d
safecopy(op->coinaddr,address,sizeof(op->coinaddr));
op->price = price;
op->numutxos = numutxos;
op->minsatoshis = minsatoshis;
op->avesatoshis = avesatoshis;
op->maxsatoshis = maxsatoshis;
op->pubkey = pubkey;
op->timestamp = timestamp;
op->depth = balance;
op->dynamictrust = dynamictrust;
}
return(op);
}
void LP_pubkeys_query()
{
static uint32_t lasttime;
uint8_t zeroes[20]; bits256 zero; cJSON *reqjson; struct LP_pubkeyinfo *pubp=0,*tmp;
uint8_t zeroes[20]; bits256 zero; cJSON *reqjson; struct LP_pubkey_info *pubp=0,*tmp;
memset(zero.bytes,0,sizeof(zero));
memset(zeroes,0,sizeof(zeroes));
HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp)
{
if ( memcmp(zeroes,pubp->rmd160,sizeof(pubp->rmd160)) == 0 && time(NULL) > lasttime+30 )
if ( memcmp(zeroes,pubp->rmd160,sizeof(pubp->rmd160)) == 0 && time(NULL) > pubp->lasttime+60 )
{
lasttime = (uint32_t)time(NULL);
pubp->lasttime = (uint32_t)time(NULL);
reqjson = cJSON_CreateObject();
jaddstr(reqjson,"method","wantnotify");
jaddbits256(reqjson,"pub",pubp->pubkey);
//printf("LP_pubkeys_query %s\n",jprint(reqjson,0));
LP_reserved_msg("","",zero,jprint(reqjson,1));
LP_reserved_msg(0,"","",zero,jprint(reqjson,1));
}
}
}
int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *rel,struct LP_orderbookentry *(**arrayp),int32_t num,int32_t cachednum,int32_t duration)
{
char coinaddr[64]; uint8_t zeroes[20]; struct LP_pubkeyinfo *pubp=0,*tmp; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; struct LP_address *ap; struct iguana_info *basecoin; uint32_t oldest; double price; int32_t baseid,relid,n; uint64_t minsatoshis,maxsatoshis,balance;
char coinaddr[64]; uint8_t zeroes[20]; struct LP_pubkey_info *pubp=0,*tmp; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; struct LP_address *ap; struct iguana_info *basecoin; uint32_t oldest; double price; int32_t baseid,relid,n; int64_t maxsatoshis,balance,avesatoshis;
if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 )
baseid = basepp->ind;
else return(num);
@ -739,23 +775,23 @@ int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *
if ( pubp->timestamp < oldest )
continue;
bitcoin_address(coinaddr,basecoin->taddr,basecoin->pubtype,pubp->rmd160,sizeof(pubp->rmd160));
minsatoshis = maxsatoshis = n = 0;
avesatoshis = maxsatoshis = n = 0;
ap = 0;
if ( (price= pubp->matrix[baseid][relid]) > SMALLVAL && pubp->timestamps[baseid][relid] >= oldest )
if ( (price= LP_pubkey_price(&n,&avesatoshis,&maxsatoshis,pubp,baseid,relid)) > SMALLVAL ) //pubp->matrix[baseid][relid]) > SMALLVAL )//&& pubp->timestamps[baseid][relid] >= oldest )
{
balance = 0;
if ( (ap= LP_addressfind(basecoin,coinaddr)) != 0 )
balance = avesatoshis * n;
//if ( (ap= LP_addressfind(basecoin,coinaddr)) != 0 )
{
n = LP_address_minmax(&balance,&minsatoshis,&maxsatoshis,ap);
//n = LP_address_minmax(&balance,&minsatoshis,&maxsatoshis,ap);
if ( polarity > 0 )
{
balance *= price;
minsatoshis *= price;
avesatoshis *= price;
maxsatoshis *= price;
}
//printf("%s/%s %s n.%d ap->n.%d %.8f\n",base,rel,coinaddr,n,ap->n,dstr(ap->total));
}
if ( (op= LP_orderbookentry(coinaddr,base,rel,polarity > 0 ? price : 1./price,n,minsatoshis,maxsatoshis,pubp->pubkey,pubp->timestamps[baseid][relid],balance)) != 0 )
if ( (op= LP_orderbookentry(coinaddr,base,rel,polarity > 0 ? price : 1./price,n,avesatoshis,maxsatoshis,pubp->pubkey,pubp->timestamp,balance,pubp->dynamictrust)) != 0 )
{
*arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1));
(*arrayp)[num++] = op;
@ -768,7 +804,7 @@ int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *
char *LP_orderbook(char *base,char *rel,int32_t duration)
{
uint32_t now,i; uint64_t depth; struct LP_priceinfo *basepp=0,*relpp=0; struct LP_orderbookentry **bids = 0,**asks = 0; cJSON *retjson,*array; struct iguana_info *basecoin,*relcoin; int32_t n,numbids=0,numasks=0,cachenumbids,cachenumasks,baseid,relid,suppress_prefetch=0;
uint32_t now,i; int64_t depth,askdepth=0,biddepth=0; struct LP_priceinfo *basepp=0,*relpp=0; struct LP_orderbookentry **bids = 0,**asks = 0; cJSON *retjson,*array; struct iguana_info *basecoin,*relcoin; int32_t n,numbids=0,numasks=0,cachenumbids,cachenumasks,baseid,relid,suppress_prefetch=0;
basecoin = LP_coinfind(base);
relcoin = LP_coinfind(rel);
if ( basecoin == 0 || relcoin == 0 )
@ -815,16 +851,26 @@ char *LP_orderbook(char *base,char *rel,int32_t duration)
}
for (i=n=0; i<numbids; i++)
{
biddepth = bids[i]->depth;
jaddi(array,LP_orderbookjson(rel,bids[i]));
if ( suppress_prefetch == 0 && n < 7 && bids[i]->numutxos == 0 )
if ( suppress_prefetch == 0 && n < 3 && bids[i]->numutxos == 0 )
{
//printf("bid ping %s %s\n",rel,bids[i]->coinaddr);
LP_address(relcoin,bids[i]->coinaddr);
if ( relcoin->electrum == 0 )
/*if ( 0 && relcoin->electrum == 0 )
{
LP_listunspent_issue(rel,bids[i]->coinaddr,0);
LP_listunspent_query(rel,bids[i]->coinaddr);
//else if ( (tmpjson= LP_listunspent(rel,bids[i]->coinaddr)) != 0 )
// free_json(tmpjson);
LP_listunspent_query(rel,bids[i]->coinaddr);
}*/
n++;
}
if ( i == 0 )
{
LP_priceinfoupdate(rel,base,1. / bids[i]->price);
//printf("update %s/%s %.8f [%.8f]\n",rel,base,1./bids[i]->price,bids[i]->price);
}
free(bids[i]);
bids[i] = 0;
}
@ -832,19 +878,30 @@ char *LP_orderbook(char *base,char *rel,int32_t duration)
relcoin->lastmonitor -= 3600;
jadd(retjson,"bids",array);
jaddnum(retjson,"numbids",numbids);
jaddnum(retjson,"biddepth",dstr(biddepth));
array = cJSON_CreateArray();
for (i=n=0; i<numasks; i++)
{
askdepth = asks[i]->depth;
jaddi(array,LP_orderbookjson(base,asks[i]));
if ( suppress_prefetch == 0 && n < 7 && asks[i]->numutxos == 0 )
if ( suppress_prefetch == 0 && n < 3 && asks[i]->numutxos == 0 )
{
//printf("ask ping %s %s\n",base,asks[i]->coinaddr);
LP_address(basecoin,asks[i]->coinaddr);
if ( basecoin->electrum == 0 )
/*if ( 0 && basecoin->electrum == 0 )
{
LP_listunspent_issue(base,asks[i]->coinaddr,0);
LP_listunspent_query(base,asks[i]->coinaddr);
//else if ( (tmpjson= LP_listunspent(base,asks[i]->coinaddr)) != 0 )
// free_json(tmpjson);
LP_listunspent_query(base,asks[i]->coinaddr);
}*/
n++;
}
if ( i == 0 )
{
LP_priceinfoupdate(base,rel,asks[i]->price);
//printf("update %s/%s %.8f [%.8f]\n",base,rel,asks[i]->price,1./asks[i]->price);
}
free(asks[i]);
asks[i] = 0;
}
@ -852,6 +909,7 @@ char *LP_orderbook(char *base,char *rel,int32_t duration)
basecoin->lastmonitor -= 3600;
jadd(retjson,"asks",array);
jaddnum(retjson,"numasks",numasks);
jaddnum(retjson,"askdepth",dstr(askdepth));
jaddstr(retjson,"base",base);
jaddstr(retjson,"rel",rel);
jaddnum(retjson,"timestamp",now);
@ -862,41 +920,32 @@ char *LP_orderbook(char *base,char *rel,int32_t duration)
return(jprint(retjson,1));
}
uint64_t LP_KMDvalue(struct iguana_info *coin,uint64_t balance)
int64_t LP_KMDvalue(struct iguana_info *coin,int64_t balance)
{
cJSON *bids,*asks,*orderbook,*item; double bid=0,ask=0,price = 0.; int32_t numasks,numbids; char *retstr; uint64_t KMDvalue=0;
double price = 0.; int64_t KMDvalue=0;
if ( balance != 0 )
{
if ( strcmp(coin->symbol,"KMD") == 0 )
KMDvalue = balance;
else if ( (retstr= LP_orderbook(coin->symbol,"KMD",-1)) != 0 )
else
{
if ( (orderbook= cJSON_Parse(retstr)) != 0 )
{
if ( (asks= jarray(&numasks,orderbook,"asks")) != 0 && numasks > 0 )
{
item = jitem(asks,0);
price = ask = jdouble(item,"price");
//printf("%s/%s ask %.8f\n",coin->symbol,"KMD",ask);
}
if ( (bids= jarray(&numbids,orderbook,"bids")) != 0 && numbids > 0 )
{
item = jitem(asks,0);
bid = jdouble(item,"price");
if ( price == 0. )
price = bid;
else price = (bid + ask) * 0.5;
//printf("%s/%s bid %.8f ask %.8f price %.8f\n",coin->symbol,"KMD",bid,ask,price);
}
if ( (price= LP_price(coin->symbol,"KMD")) > SMALLVAL )
KMDvalue = price * balance;
free_json(orderbook);
}
free(retstr);
}
}
return(KMDvalue);
}
int64_t LP_kmdvalue(char *symbol,int64_t satoshis)
{
struct iguana_info *coin; int64_t kmdvalue = 0;
if ( (coin= LP_coinfind(symbol)) != 0 )
kmdvalue = LP_KMDvalue(coin,satoshis);
if ( kmdvalue == 0 )
kmdvalue = satoshis;
return(kmdvalue);
}
void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32])
{
LP_priceinfoupdate(base,rel,price);
@ -921,7 +970,7 @@ void LP_priceitemadd(cJSON *retarray,uint32_t timestamp,double avebid,double ave
cJSON *LP_pricearray(char *base,char *rel,uint32_t firsttime,uint32_t lasttime,int32_t timescale)
{
cJSON *retarray; char askfname[1024],bidfname[1024]; uint64_t bidprice64,askprice64; uint32_t bidnow,asknow,bidi,aski,lastbidi,lastaski; int32_t numbids,numasks; double bidemit,askemit,bidsum,asksum,bid,ask,highbid,lowbid,highask,lowask,bidemit2,askemit2; FILE *askfp=0,*bidfp=0;
cJSON *retarray; char askfname[1024],bidfname[1024]; int64_t bidprice64,askprice64; uint32_t bidnow,asknow,bidi,aski,lastbidi,lastaski; int32_t numbids,numasks; double bidemit,askemit,bidsum,asksum,bid,ask,highbid,lowbid,highask,lowask,bidemit2,askemit2; FILE *askfp=0,*bidfp=0;
if ( timescale <= 0 )
timescale = 60;
if ( lasttime == 0 )
@ -1030,16 +1079,16 @@ cJSON *LP_pricearray(char *base,char *rel,uint32_t firsttime,uint32_t lasttime,i
return(retarray);
}
void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price)
void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price,char *utxocoin,int32_t numrelutxos,int64_t balance,int64_t minutxo,int64_t maxutxo,int64_t unconfcredits)
{
struct LP_priceinfo *basepp,*relpp; uint32_t now; uint64_t price64; struct LP_pubkeyinfo *pubp; char str[65],fname[512]; FILE *fp;
struct LP_priceinfo *basepp,*relpp; uint32_t now; int64_t price64; struct LP_pubkey_info *pubp; char str[65],fname[512]; FILE *fp;
//printf("check PRICEFEED UPDATE.(%s/%s) %.8f %s\n",base,rel,price,bits256_str(str,pubkey));
if ( LP_pricevalid(price) > 0 && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
if ( (fp= basepp->fps[relpp->ind]) == 0 )
//if ( (fp= basepp->fps[relpp->ind]) == 0 )
{
LP_pricefname(fname,base,rel);
fp = basepp->fps[relpp->ind] = OS_appendfile(fname);
fp = OS_appendfile(fname); //basepp->fps[relpp->ind] =
}
if ( fp != 0 )
{
@ -1047,12 +1096,12 @@ void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price)
price64 = price * SATOSHIDEN;
fwrite(&now,1,sizeof(now),fp);
fwrite(&price64,1,sizeof(price64),fp);
fflush(fp);
fclose(fp);
}
if ( (fp= relpp->fps[basepp->ind]) == 0 )
//if ( (fp= relpp->fps[basepp->ind]) == 0 )
{
sprintf(fname,"%s/PRICES/%s_%s",GLOBAL_DBDIR,rel,base);
fp = relpp->fps[basepp->ind] = OS_appendfile(fname);
fp = OS_appendfile(fname); //relpp->fps[basepp->ind] =
}
if ( fp != 0 )
{
@ -1060,17 +1109,21 @@ void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price)
price64 = (1. / price) * SATOSHIDEN;
fwrite(&now,1,sizeof(now),fp);
fwrite(&price64,1,sizeof(price64),fp);
fflush(fp);
fclose(fp);
}
if ( (pubp= LP_pubkeyadd(pubkey)) != 0 )
{
if ( (rand() % 1000) == 0 )
if ( (LP_rand() % 1000) == 0 )
printf("PRICEFEED UPDATE.(%-6s/%6s) %12.8f %s %12.8f\n",base,rel,price,bits256_str(str,pubkey),1./price);
if ( unconfcredits > pubp->unconfcredits )
pubp->unconfcredits = unconfcredits;
pubp->timestamp = (uint32_t)time(NULL);
if ( fabs(pubp->matrix[basepp->ind][relpp->ind] - price) > SMALLVAL )
LP_pubkey_update(pubp,basepp->ind,relpp->ind,price,balance,utxocoin,numrelutxos,minutxo,maxutxo);
//pubp->depthinfo[basepp->ind][relpp->ind] = LP_depthinfo_compact();
//if ( fabs(pubp->matrix[basepp->ind][relpp->ind] - price) > SMALLVAL )
{
pubp->matrix[basepp->ind][relpp->ind] = price;
pubp->timestamps[basepp->ind][relpp->ind] = pubp->timestamp;
//pubp->matrix[basepp->ind][relpp->ind] = price;
//pubp->timestamps[basepp->ind][relpp->ind] = pubp->timestamp;
dxblend(&basepp->relvals[relpp->ind],price,0.9);
dxblend(&relpp->relvals[basepp->ind],1. / price,0.9);
}
@ -1080,3 +1133,105 @@ void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price)
// printf("error finding %s/%s %.8f\n",base,rel,price);
}
double LP_CMCbtcprice(double *price_usdp,char *symbol)
{
char *retstr; cJSON *ticker,*item; double price_btc = 0.;
*price_usdp = 0.;
if ( (retstr= cmc_ticker(symbol)) != 0 )
{
if ( (ticker= cJSON_Parse(retstr)) != 0 )
{
item = jitem(ticker,0);
price_btc = jdouble(item,"price_btc");
*price_usdp = jdouble(item,"price_usd");
//printf("%.8f item.(%s)\n",price_btc,jprint(item,0));
free_json(ticker);
}
free(retstr);
}
return(price_btc);
}
cJSON *LP_fundvalue(cJSON *argjson)
{
cJSON *holdings,*item,*newitem,*array,*retjson; int32_t i,iter,n,missing=0; double usdprice,divisor,btcprice,balance,btcsum,KMDholdings,numKMD; struct iguana_info *coin; char *symbol,*coinaddr; int64_t fundvalue,KMDvalue = 0;
fundvalue = 0;
KMDholdings = btcsum = 0.;
array = cJSON_CreateArray();
for (iter=0; iter<2; iter++)
{
if ( iter == 0 )
holdings = jarray(&n,argjson,"holdings");
else
{
if ( (coinaddr= jstr(argjson,"address")) != 0 )
{
holdings = LP_balances(coinaddr);
n = cJSON_GetArraySize(holdings);
} else break;
}
if ( holdings != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(holdings,i);
if ( (symbol= jstr(item,"coin")) != 0 && (balance= jdouble(item,"balance")) > SMALLVAL )
{
newitem = cJSON_CreateObject();
jaddstr(newitem,"coin",symbol);
jaddnum(newitem,"balance",balance);
if ( (coin= LP_coinfind(symbol)) != 0 && (KMDvalue= LP_KMDvalue(coin,SATOSHIDEN * balance)) > 0 )
{
jaddnum(newitem,"KMD",dstr(KMDvalue));
fundvalue += KMDvalue;
if ( strcmp(symbol,"KMD") == 0 )
KMDholdings += dstr(KMDvalue);
}
else if ( iter == 0 && (btcprice= LP_CMCbtcprice(&usdprice,symbol)) > SMALLVAL )
{
btcsum += btcprice * balance;
jaddnum(newitem,"BTC",btcprice * balance);
}
else jaddstr(newitem,"error","no price source");
jaddi(array,newitem);
} else missing++;
}
}
}
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddnum(retjson,"missing",missing);
jadd(retjson,"holdings",array);
btcprice = LP_CMCbtcprice(&usdprice,"komodo");
divisor = jdouble(argjson,"divisor");
jaddnum(retjson,"KMDholdings",KMDholdings);
if ( btcsum != 0 )
{
if ( btcprice > SMALLVAL )
{
numKMD = (btcsum / btcprice);
fundvalue += numKMD * SATOSHIDEN;
jaddnum(retjson,"KMD_BTC",btcprice);
jaddnum(retjson,"btcsum",btcsum);
numKMD += KMDholdings;
jaddnum(retjson,"btc2kmd",numKMD);
if ( divisor != 0 )
{
jaddnum(retjson,"NAV_KMD",numKMD/divisor);
jaddnum(retjson,"NAV_BTC",(btcsum + (KMDholdings * btcprice))/divisor);
jaddnum(retjson,"NAV_USD",(usdprice * numKMD)/divisor);
}
}
}
jaddnum(retjson,"fundvalue",dstr(fundvalue));
if ( divisor != 0 )
{
jaddnum(retjson,"divisor",divisor);
numKMD = dstr(fundvalue);
jaddnum(retjson,"assetNAV_KMD",numKMD/divisor);
jaddnum(retjson,"assetNAV_BTC",(btcprice * numKMD)/divisor);
jaddnum(retjson,"assetNAV_USD",(usdprice * numKMD)/divisor);
}
return(retjson);
}

337
iguana/exchanges/LP_privkey.c

@ -0,0 +1,337 @@
/******************************************************************************
* Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
//
// LP_utxos.c
// marketmaker
//
int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 myprivkey,bits256 mypub)
{
int32_t enable_utxos = 0;
char *script,destaddr[64]; cJSON *array,*item; bits256 txid,deposittxid,zero; int32_t used,i,flag=0,height,n,cmpflag,iambob,vout,depositvout; uint64_t *values=0,satoshis,txfee,biggerval,value,total = 0; int64_t targetval; //struct LP_utxoinfo *utxo;
if ( coin == 0 || (IAMLP == 0 && coin->inactive != 0) )
{
//printf("coin not active\n");
return(0);
}
if ( coin->privkeydepth > 0 )
return(0);
coin->privkeydepth++;
LP_address(coin,coin->smartaddr);
//if ( coin->inactive == 0 )
// LP_listunspent_issue(coin->symbol,coin->smartaddr,0);
memset(zero.bytes,0,sizeof(zero));
array = LP_listunspent(coin->symbol,coin->smartaddr,zero,zero);
if ( array != 0 )
{
txfee = LP_txfeecalc(coin,0,0);
if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{
coin->numutxos = n;
//printf("LP_privkey_init %s %d\n",coin->symbol,n);
for (iambob=0; iambob<=1; iambob++)
{
if ( iambob == 0 )
values = calloc(n,sizeof(*values));
else memset(values,0,n * sizeof(*values));
used = 0;
for (i=0; i<n; i++)
{
item = jitem(array,i);
value = LP_listunspent_parseitem(coin,&txid,&vout,&height,item);
satoshis = LP_txvalue(destaddr,coin->symbol,txid,vout);
if ( satoshis != 0 && satoshis != value )
printf("%s %s privkey_init value %.8f vs %.8f (%s) %.8f %.8f\n",coin->symbol,coin->smartaddr,dstr(satoshis),dstr(value),jprint(item,0),jdouble(item,"amount"),jdouble(item,"interest"));
if ( coin->electrum != 0 || LP_inventory_prevent(iambob,coin->symbol,txid,vout) == 0 )//&& height > 0 )
{
values[i] = satoshis;
//flag += LP_address_utxoadd(coin,destaddr,txid,vout,satoshis,height,-1);
} else used++;
}
//printf("array.%d\n",n);
while ( used < n-1 )
{
//for (i=0; i<n; i++)
// printf("%.8f ",dstr(values[i]));
//printf("used.%d of n.%d\n",used,n);
if ( (i= LP_maxvalue(values,n)) >= 0 )
{
item = jitem(array,i);
if ( coin->electrum == 0 )
{
deposittxid = jbits256(item,"txid");
depositvout = juint(item,"vout");
script = jstr(item,"scriptPubKey");
}
else
{
deposittxid = jbits256(item,"tx_hash");
depositvout = juint(item,"tx_pos");
script = coin->smartaddr;
}
biggerval = values[i];
values[i] = 0, used++;
if ( iambob == 0 )
targetval = (biggerval / 776) + txfee;
else targetval = (biggerval / 9) * 8 + 2*txfee;
if ( targetval < txfee*2 )
targetval = txfee*2;
//printf("iambob.%d i.%d deposit %.8f min %.8f target %.8f\n",iambob,i,dstr(biggerval),dstr((1+LP_MINSIZE_TXFEEMULT)*txfee),dstr(targetval));
if ( biggerval < (1+LP_MINSIZE_TXFEEMULT)*txfee )
continue;
i = -1;
if ( iambob != 0 )
{
if ( (i= LP_nearestvalue(iambob,values,n,targetval)) < 0 )
targetval /= 4;
if ( targetval < txfee*(1+LP_MINSIZE_TXFEEMULT) )
continue;
}
if ( i >= 0 || (i= LP_nearestvalue(iambob,values,n,targetval)) >= 0 )
{
//printf("iambob.%d i.%d %.8f target %.8f\n",iambob,i,dstr(biggerval),dstr(targetval));
item = jitem(array,i);
cmpflag = 0;
if ( coin->electrum == 0 )
{
txid = jbits256(item,"txid");
vout = juint(item,"vout");
if ( jstr(item,"scriptPubKey") != 0 && strcmp(script,jstr(item,"scriptPubKey")) == 0 )
cmpflag = 1;
}
else
{
txid = jbits256(item,"tx_hash");
vout = juint(item,"tx_pos");
cmpflag = 1;
}
if ( cmpflag != 0 )
{
value = values[i];
values[i] = 0, used++;
/*portable_mutex_lock(&LP_UTXOmutex);
if ( iambob != 0 )
{
if ( (utxo= LP_utxoadd(1,coin->symbol,txid,vout,value,deposittxid,depositvout,biggerval,coin->smartaddr,mypub,LP_gui,G.LP_sessionid,value)) != 0 )
{
}
}
else
{
//printf("call utxoadd\n");
if ( (utxo= LP_utxoadd(0,coin->symbol,deposittxid,depositvout,biggerval,txid,vout,value,coin->smartaddr,mypub,LP_gui,G.LP_sessionid,biggerval)) != 0 )
{
}
}
portable_mutex_unlock(&LP_UTXOmutex);*/
total += value;
} // else printf("scriptmismatch.(%s) vs %s\n",script,jprint(item,0));
} //else printf("nothing near i.%d\n",i);
} else break;
}
if ( enable_utxos == 0 )
break;
}
}
free_json(array);
if ( 0 && flag != 0 )
LP_postutxos(coin->symbol,coin->smartaddr);
}
if ( values != 0 )
free(values);
if ( coin->privkeydepth > 0 )
coin->privkeydepth--;
//printf("privkey.%s %.8f\n",symbol,dstr(total));
return(flag);
}
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 )
n = 16;
else if ( n > 777 )
n = 777;
conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase));
bitcoin_priv2pub(ctx,pubkey33,coinaddr,privkey,taddr,pubtype);
printf("generator (%s) secrets.[%d] <%s> t.%u p.%u\n",coinaddr,n,passphrase,taddr,pubtype);
sprintf(output,"\"addresses\":[");
for (i=0; i<n; 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);
bitcoin_wif2priv(0,&tmptype,&checkprivkey,wifstr);
bitcoin_addr2rmd160(taddr,&tmptype,rmd160,coinaddr);
if ( bits256_cmp(checkprivkey,privkey) != 0 )
{
printf("WIF.(%s) error -> %s vs %s?\n",wifstr,bits256_str(str,privkey),bits256_str(str2,checkprivkey));
free_json(retjson);
return(clonestr("{\"error\":\"couldnt validate wifstr\"}"));
}
else if ( tmptype != pubtype )
{
printf("checktype.%d != pubtype.%d\n",tmptype,pubtype);
free_json(retjson);
return(clonestr("{\"error\":\"couldnt validate pubtype\"}"));
}
jaddstr(retjson,coinaddr,wifstr);
sprintf(output+strlen(output),"\\\"%s\\\"%c ",coinaddr,i<n-1?',':' ');
printf("./komodo-cli jumblr_secret %s\n",coinaddr);
}
printf("%s]\n",output);
return(jprint(retjson,1));
}
bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguana_info *coin,char *passphrase,char *wifstr)
{
//static uint32_t counter;
bits256 privkey,userpub,zero,userpass,checkkey; char tmpstr[128]; cJSON *retjson; uint8_t tmptype; int32_t notarized;
if ( passphrase != 0 && passphrase[0] != 0 )
{
calc_NXTaddr(G.LP_NXTaddr,userpub.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase));
conv_NXTpassword(privkey.bytes,pubkeyp->bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase));
//vcalc_sha256(0,checkkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase));
//printf("SHA256.(%s) ",bits256_str(pstr,checkkey));
//printf("privkey.(%s)\n",bits256_str(pstr,privkey));
}
else
{
bitcoin_wif2priv(coin->wiftaddr,&tmptype,&privkey,wifstr);
if ( 0 )
{
char str[65],str2[65];
checkkey = iguana_wif2privkey(wifstr);
if ( bits256_cmp(checkkey,privkey) != 0 )
printf("WIF.(%s) -> %s or %s?\n",wifstr,bits256_str(str,privkey),bits256_str(str2,checkkey));
}
}
privkey.bytes[0] &= 248, privkey.bytes[31] &= 127, privkey.bytes[31] |= 64;
bitcoin_priv2pub(ctx,coin->pubkey33,coin->smartaddr,privkey,coin->taddr,coin->pubtype);
if ( coin->counter == 0 )
{
coin->counter++;
memcpy(G.LP_pubsecp,coin->pubkey33,33);
bitcoin_priv2wif(coin->wiftaddr,tmpstr,privkey,coin->wiftype);
bitcoin_addr2rmd160(coin->taddr,&tmptype,G.LP_myrmd160,coin->smartaddr);
LP_privkeyadd(privkey,G.LP_myrmd160);
G.LP_privkey = privkey;
if ( 0 && (coin->pubtype != 60 || strcmp(coin->symbol,"KMD") == 0) )
printf("%s (%s) %d wif.(%s) (%s)\n",coin->symbol,coin->smartaddr,coin->pubtype,tmpstr,passphrase);
if ( G.counter++ == 0 )
{
bitcoin_priv2wif(coin->wiftaddr,G.USERPASS_WIFSTR,privkey,188);
bitcoin_wif2priv(coin->wiftaddr,&tmptype,&checkkey,G.USERPASS_WIFSTR);
if ( bits256_cmp(checkkey,privkey) != 0 )
{
char str[65],str2[65];
printf("FATAL ERROR converting USERPASS_WIFSTR %s -> %s != %s\n",G.USERPASS_WIFSTR,bits256_str(str,checkkey),bits256_str(str2,privkey));
exit(-1);
}
conv_NXTpassword(userpass.bytes,pubkeyp->bytes,(uint8_t *)G.USERPASS_WIFSTR,(int32_t)strlen(G.USERPASS_WIFSTR));
userpub = curve25519(userpass,curve25519_basepoint9());
printf("userpass.(%s)\n",bits256_str(G.USERPASS,userpub));
}
}
if ( coin->importedprivkey == 0 && coin->electrum == 0 && coin->userpass[0] != 0 && LP_getheight(&notarized,coin) > 0 )
{
memset(zero.bytes,0,sizeof(zero));
LP_listunspent_issue(coin->symbol,coin->smartaddr,0,zero,zero);
if ( (retjson= LP_importprivkey(coin->symbol,tmpstr,coin->smartaddr,-1)) != 0 )
{
if ( jobj(retjson,"error") != 0 )
{
printf("cant importprivkey.%s -> (%s), abort session\n",coin->symbol,jprint(retjson,1));
exit(-1);
}
free_json(retjson);
}
coin->importedprivkey = (uint32_t)time(NULL);
}
vcalc_sha256(0,checkkey.bytes,privkey.bytes,sizeof(privkey));
checkkey.bytes[0] &= 248, checkkey.bytes[31] &= 127, checkkey.bytes[31] |= 64;
G.LP_mypub25519 = *pubkeyp = curve25519(checkkey,curve25519_basepoint9());
G.LP_mypriv25519 = checkkey;
LP_pubkeyadd(G.LP_mypub25519);
return(privkey);
}
void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase)
{
struct iguana_info *coin,*tmp; bits256 pubkey,privkey; uint8_t pubkey33[33]; int32_t initonly;
initonly = (passphrase != 0);
memset(privkey.bytes,0,sizeof(privkey));
memset(pubkey.bytes,0,sizeof(pubkey));
//printf("Total coins: %d\n", HASH_COUNT(LP_coins));
//int num_iter = 0;
HASH_ITER(hh,LP_coins,coin,tmp)
{
//printf("LP_privkey_updates [%02d / %02d]\n", num_iter++, HASH_COUNT(LP_coins));
if ( initonly != 0 )
{
coin->counter = 0;
memset(coin->smartaddr,0,sizeof(coin->smartaddr));
if ( bits256_nonz(privkey) == 0 || coin->smartaddr[0] == 0 )
privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,coin,passphrase,"");
}
//printf("i.%d of %d\n",i,LP_numcoins);
else if ( IAMLP == 0 || coin->inactive == 0 )
{
//printf("from updates %s\n",coin->symbol);
if ( 0 && LP_privkey_init(pubsock,coin,G.LP_privkey,G.LP_mypub25519) == 0 && (LP_rand() % 10) == 0 )
{
//LP_postutxos(coin->symbol,coin->smartaddr);
}
}
}
}
int32_t LP_passphrase_init(char *passphrase,char *gui)
{
static void *ctx; int32_t counter; //iambob,; struct LP_utxoinfo *utxo,*tmp;
if ( ctx == 0 )
ctx = bitcoin_ctx();
if ( G.LP_pendingswaps != 0 )
return(-1);
G.initializing = 1;
if ( gui == 0 )
gui = "cli";
counter = G.USERPASS_COUNTER;
while ( G.waiting == 0 )
{
printf("waiting for G.waiting\n");
sleep(5);
}
memset(&G,0,sizeof(G));
LP_privkey_updates(ctx,LP_mypubsock,passphrase);
init_hexbytes_noT(G.LP_myrmd160str,G.LP_myrmd160,20);
G.LP_sessionid = (uint32_t)time(NULL);
safecopy(G.gui,gui,sizeof(G.gui));
LP_tradebot_pauseall();
LP_portfolio_reset();
LP_priceinfos_clear();
G.USERPASS_COUNTER = counter;
G.initializing = 0;
return(0);
}

375
iguana/exchanges/LP_remember.c

@ -32,13 +32,15 @@ void basilisk_dontforget_userdata(char *userdataname,FILE *fp,uint8_t *script,in
void basilisk_dontforget(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx,int32_t locktime,bits256 triggertxid)
{
char zeroes[32],fname[512],str[65],coinaddr[64],secretAmstr[41],secretAm256str[65],secretBnstr[41],secretBn256str[65]; FILE *fp; int32_t i,len; uint8_t redeemscript[256],script[256];
char zeroes[32],fname[512],str[65],coinaddr[64],secretAmstr[41],secretAm256str[65],secretBnstr[41],secretBn256str[65]; FILE *fp; int32_t i,len; uint8_t redeemscript[256],script[256]; struct iguana_info *bobcoin,*alicecoin;
sprintf(fname,"%s/SWAPS/%u-%u.%s",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid,rawtx->name), OS_compatible_path(fname);
bobcoin = LP_coinfind(swap->I.bobstr);
alicecoin = LP_coinfind(swap->I.alicestr);
coinaddr[0] = secretAmstr[0] = secretAm256str[0] = secretBnstr[0] = secretBn256str[0] = 0;
memset(zeroes,0,sizeof(zeroes));
if ( rawtx != 0 && (fp= fopen(fname,"wb")) != 0 )
if ( alicecoin != 0 && bobcoin != 0 && rawtx != 0 && (fp= fopen(fname,"wb")) != 0 )
{
fprintf(fp,"{\"name\":\"%s\",\"coin\":\"%s\"",rawtx->name,rawtx->coin->symbol);
fprintf(fp,"{\"name\":\"%s\",\"coin\":\"%s\"",rawtx->name,rawtx->symbol);
if ( rawtx->I.datalen > 0 )
{
fprintf(fp,",\"tx\":\"");
@ -47,10 +49,10 @@ void basilisk_dontforget(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx
fprintf(fp,"\",\"txid\":\"%s\"",bits256_str(str,bits256_doublesha256(0,rawtx->txbytes,rawtx->I.datalen)));
if ( rawtx == &swap->bobdeposit || rawtx == &swap->bobpayment )
{
LP_swap_coinaddr(&swap->bobcoin,coinaddr,0,rawtx->txbytes,rawtx->I.datalen,0);
LP_swap_coinaddr(bobcoin,coinaddr,0,rawtx->txbytes,rawtx->I.datalen,0);
if ( coinaddr[0] != 0 )
{
LP_importaddress(swap->bobcoin.symbol,coinaddr);
LP_importaddress(swap->I.bobstr,coinaddr);
if ( rawtx == &swap->bobdeposit )
safecopy(swap->Bdeposit,coinaddr,sizeof(swap->Bdeposit));
else safecopy(swap->Bpayment,coinaddr,sizeof(swap->Bpayment));
@ -63,16 +65,16 @@ void basilisk_dontforget(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx
fprintf(fp,",\"%s\":\"%s\"","Bpayment",swap->Bpayment);
fprintf(fp,",\"expiration\":%u",swap->I.expiration);
fprintf(fp,",\"iambob\":%d",swap->I.iambob);
fprintf(fp,",\"bobcoin\":\"%s\"",swap->bobcoin.symbol);
fprintf(fp,",\"alicecoin\":\"%s\"",swap->alicecoin.symbol);
fprintf(fp,",\"bobcoin\":\"%s\"",swap->I.bobstr);
fprintf(fp,",\"alicecoin\":\"%s\"",swap->I.alicestr);
fprintf(fp,",\"lock\":%u",locktime);
fprintf(fp,",\"amount\":%.8f",dstr(rawtx->I.amount));
if ( bits256_nonz(triggertxid) != 0 )
fprintf(fp,",\"trigger\":\"%s\"",bits256_str(str,triggertxid));
if ( bits256_nonz(swap->I.pubAm) != 0 && bits256_nonz(swap->I.pubBn) != 0 )
{
basilisk_alicescript(redeemscript,&len,script,0,coinaddr,swap->alicecoin.taddr,swap->alicecoin.p2shtype,swap->I.pubAm,swap->I.pubBn);
LP_importaddress(swap->alicecoin.symbol,coinaddr);
basilisk_alicescript(redeemscript,&len,script,0,coinaddr,alicecoin->taddr,alicecoin->p2shtype,swap->I.pubAm,swap->I.pubBn);
LP_importaddress(swap->I.alicestr,coinaddr);
fprintf(fp,",\"Apayment\":\"%s\"",coinaddr);
}
if ( rawtx->I.redeemlen > 0 )
@ -93,7 +95,11 @@ void basilisk_dontforget(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx
sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid), OS_compatible_path(fname);
if ( (fp= fopen(fname,"wb")) != 0 )
{
fprintf(fp,"{\"aliceid\":\"%llu\",\"src\":\"%s\",\"srcamount\":%.8f,\"dest\":\"%s\",\"destamount\":%.8f,\"requestid\":%u,\"quoteid\":%u,\"iambob\":%d,\"state\":%u,\"otherstate\":%u,\"expiration\":%u,\"dlocktime\":%u,\"plocktime\":%u,\"Atxfee\":%llu,\"Btxfee\":%llu",(long long)swap->aliceid,swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount),swap->I.req.requestid,swap->I.req.quoteid,swap->I.iambob,swap->I.statebits,swap->I.otherstatebits,swap->I.expiration,swap->bobdeposit.I.locktime,swap->bobpayment.I.locktime,(long long)swap->I.Atxfee,(long long)swap->I.Btxfee);
fprintf(fp,"{\"tradeid\":%u,\"aliceid\":\"%llu\",\"src\":\"%s\",\"srcamount\":%.8f,\"dest\":\"%s\",\"destamount\":%.8f,\"requestid\":%u,\"quoteid\":%u,\"iambob\":%d,\"state\":%u,\"otherstate\":%u,\"expiration\":%u,\"dlocktime\":%u,\"plocktime\":%u,\"Atxfee\":%llu,\"Btxfee\":%llu",swap->tradeid,(long long)swap->aliceid,swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount),swap->I.req.requestid,swap->I.req.quoteid,swap->I.iambob,swap->I.statebits,swap->I.otherstatebits,swap->I.expiration,swap->bobdeposit.I.locktime,swap->bobpayment.I.locktime,(long long)swap->I.Atxfee,(long long)swap->I.Btxfee);
if ( swap->I.iambob == 0 )
fprintf(fp,",\"Agui\":\"%s\"",G.gui);
else fprintf(fp,",\"Bgui\":\"%s\"",G.gui);
fprintf(fp,",\"gui\":\"%s\"",G.gui);
if ( memcmp(zeroes,swap->I.secretAm,20) != 0 )
{
init_hexbytes_noT(secretAmstr,swap->I.secretAm,20);
@ -237,6 +243,7 @@ bits256 basilisk_swap_privbob_extract(char *symbol,bits256 spendtxid,int32_t vin
bits256 basilisk_swap_privBn_extract(bits256 *bobrefundp,char *bobcoin,bits256 bobdeposit,bits256 privBn)
{
char destaddr[64];
destaddr[0] = 0;
if ( bits256_nonz(privBn) == 0 )
{
if ( bits256_nonz(bobdeposit) != 0 )
@ -247,23 +254,45 @@ bits256 basilisk_swap_privBn_extract(bits256 *bobrefundp,char *bobcoin,bits256 b
return(privBn);
}
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 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 utxovout,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 )
bits256 spendtxid,txid; char destaddr[64],str[65]; int32_t i,n; struct iguana_info *coin; cJSON *array,*txobj;
memset(&spendtxid,0,sizeof(spendtxid));
destaddr[0] = 0;
if ( (coin= LP_coinfind(symbol)) == 0 )
return(spendtxid);
//printf("spentaddr.%s aliceaddr.%s bobaddr.%s Adest.%s Bdest.%s\n",spentaddr,aliceaddr,bobaddr,Adest,dest);
if ( coin->electrum != 0 )
{
if ( (histobj= electrum_address_gethistory(symbol,coin->electrum,&histobj,spentaddr)) != 0 )
if ( (array= electrum_address_gethistory(symbol,coin->electrum,&array,spentaddr,txids[utxoind])) != 0 )
{
//printf("processed history.(%s)\n",jprint(histobj,0));
free_json(histobj);
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
txid = jbits256(jitem(array,i),"tx_hash");
//printf("i.%d of %d: %s\n",i,n,bits256_str(str,txid));
if ( bits256_cmp(txid,txids[utxoind]) != 0 )
{
if ( (txobj= LP_gettx(symbol,txid,1)) != 0 ) // good side effects
free_json(txobj);
}
}
}
//printf("processed history.(%s) %s\n",jprint(array,0),bits256_str(str,txids[utxoind]));
free_json(array);
}
}
else
{
if ( iambob != 0 )
strcpy(destaddr,aliceaddr);
else strcpy(destaddr,bobaddr);
}
txid = txids[utxoind];
memset(&spendtxid,0,sizeof(spendtxid));
if ( bits256_nonz(txid) != 0 )//&& sentflags[utxoind] != 0 )
{
destaddr[0] = 0;
spendtxid = LP_swap_spendtxid(symbol,destaddr,txid,vout);
spendtxid = LP_swap_spendtxid(symbol,destaddr,txid,utxovout);
if ( bits256_nonz(spendtxid) != 0 )
{
sentflags[utxoind] = 1;
@ -299,24 +328,10 @@ bits256 basilisk_swap_spendupdate(int32_t iambob,char *symbol,char *spentaddr,in
}
}
} //else printf("no spend of %s/v%d detected\n",bits256_str(str,txid),vout);
} else printf("utxoind.%d null txid\n",utxoind);
} //else printf("utxoind.%d null txid\n",utxoind);
return(spendtxid);
}
#define BASILISK_ALICESPEND 0
#define BASILISK_BOBSPEND 1
#define BASILISK_BOBPAYMENT 2
#define BASILISK_ALICEPAYMENT 3
#define BASILISK_BOBDEPOSIT 4
#define BASILISK_OTHERFEE 5
#define BASILISK_MYFEE 6
#define BASILISK_BOBREFUND 7
#define BASILISK_BOBRECLAIM 8
#define BASILISK_ALICERECLAIM 9
#define BASILISK_ALICECLAIM 10
//0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0
char *txnames[] = { "alicespend", "bobspend", "bobpayment", "alicepayment", "bobdeposit", "otherfee", "myfee", "bobrefund", "bobreclaim", "alicereclaim", "aliceclaim" };
int32_t basilisk_isbobcoin(int32_t iambob,int32_t ind)
{
switch ( ind )
@ -360,11 +375,18 @@ int32_t basilisk_swap_isfinished(int32_t iambob,bits256 *txids,int32_t *sentflag
}
else if ( bits256_nonz(Apaymentspent) != 0 )
return(1);
else if ( bits256_nonz(paymentspent) != 0 && bits256_nonz(depositspent) != 0 )
return(1);
}
else
{
if ( bits256_nonz(txids[BASILISK_ALICEPAYMENT]) == 0 && sentflags[BASILISK_ALICEPAYMENT] == 0 )
return(1);
if ( sentflags[BASILISK_ALICEPAYMENT] == 0 )
{
if ( bits256_nonz(txids[BASILISK_ALICEPAYMENT]) == 0 )
return(1);
else if ( sentflags[BASILISK_BOBPAYMENT] != 0 && sentflags[BASILISK_BOBREFUND] != 0 )
return(1);
}
else
{
if ( sentflags[BASILISK_ALICERECLAIM] != 0 || sentflags[BASILISK_ALICESPEND] != 0 )
@ -397,6 +419,7 @@ uint32_t LP_extract(uint32_t requestid,uint32_t quoteid,char *rootfname,char *fi
t = (t << 8) | redeem[2];
//printf("extracted timestamp.%u\n",t);
}
free_json(json);
}
free(filestr);
}
@ -460,24 +483,24 @@ void LP_totals_update(int32_t iambob,char *alicecoin,char *bobcoin,int64_t *KMDt
}
}
struct LP_swap_remember
{
bits256 pubA0,pubB0,pubB1,privAm,privBn,paymentspent,Apaymentspent,depositspent,myprivs[2],txids[sizeof(txnames)/sizeof(*txnames)];
uint64_t Atxfee,Btxfee,srcamount,destamount,aliceid;
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],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)
{
cJSON *item,*array; int32_t i;
item = cJSON_CreateObject();
if ( LP_swap_endcritical < LP_swap_critical )
{
jaddstr(item,"warning","swaps in critical section");
jaddnum(item,"critical",LP_swap_critical);
jaddnum(item,"endcritical",LP_swap_endcritical);
}
jaddnum(item,"expiration",rswap->expiration);// - INSTANTDEX_LOCKTIME*2);
jaddnum(item,"tradeid",rswap->tradeid);
jaddnum(item,"requestid",rswap->requestid);
jaddnum(item,"quoteid",rswap->quoteid);
jaddnum(item,"iambob",rswap->iambob);
jaddstr(item,"Bgui",rswap->Bgui);
jaddstr(item,"Agui",rswap->Agui);
jaddstr(item,"gui",rswap->gui);
jaddstr(item,"bob",rswap->src);
jaddnum(item,"srcamount",dstr(rswap->srcamount));
jaddnum(item,"bobtxfee",dstr(rswap->Btxfee));
@ -491,7 +514,7 @@ cJSON *LP_swap_json(struct LP_swap_remember *rswap)
if ( rswap->sentflags[i] != 0 )
jaddistr(array,txnames[i]);
if ( rswap->txbytes[i] != 0 )
free(rswap->txbytes[i]);
free(rswap->txbytes[i]), rswap->txbytes[i] = 0;
}
jadd(item,"sentflags",array);
array = cJSON_CreateArray();
@ -500,7 +523,10 @@ cJSON *LP_swap_json(struct LP_swap_remember *rswap)
jadd(item,"values",array);
jaddstr(item,"result","success");
if ( rswap->finishedflag != 0 )
{
jaddstr(item,"status","finished");
jaddnum(item,"finishtime",rswap->finishtime);
}
else jaddstr(item,"status","pending");
jaddbits256(item,"bobdeposit",rswap->txids[BASILISK_BOBDEPOSIT]);
jaddbits256(item,"alicepayment",rswap->txids[BASILISK_ALICEPAYMENT]);
@ -511,7 +537,7 @@ cJSON *LP_swap_json(struct LP_swap_remember *rswap)
return(item);
}
int32_t LP_rswap_init(struct LP_swap_remember *rswap,uint32_t requestid,uint32_t quoteid)
int32_t LP_rswap_init(struct LP_swap_remember *rswap,uint32_t requestid,uint32_t quoteid,int32_t forceflag)
{
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));
@ -523,6 +549,10 @@ int32_t LP_rswap_init(struct LP_swap_remember *rswap,uint32_t requestid,uint32_t
if ( (item= cJSON_Parse(fstr)) != 0 )
{
rswap->iambob = jint(item,"iambob");
safecopy(rswap->Bgui,jstr(item,"Bgui"),sizeof(rswap->Bgui));
safecopy(rswap->Agui,jstr(item,"Agui"),sizeof(rswap->Agui));
safecopy(rswap->gui,jstr(item,"gui"),sizeof(rswap->gui));
rswap->tradeid = juint(item,"tradeid");
rswap->aliceid = j64bits(item,"aliceid");
if ( (secretstr= jstr(item,"secretAm")) != 0 && strlen(secretstr) == 40 )
decode_hex(rswap->secretAm,20,secretstr);
@ -638,9 +668,12 @@ int32_t LP_rswap_init(struct LP_swap_remember *rswap,uint32_t requestid,uint32_t
}
}
}
free_json(txobj);
}
rswap->origfinishedflag = basilisk_swap_isfinished(rswap->iambob,rswap->txids,rswap->sentflags,rswap->paymentspent,rswap->Apaymentspent,rswap->depositspent);
rswap->finishedflag = rswap->origfinishedflag;
if ( forceflag != 0 )
rswap->finishedflag = rswap->origfinishedflag = 0;
free(fstr);
}
return(rswap->iambob);
@ -671,7 +704,7 @@ int32_t LP_refht_update(char *symbol,bits256 txid)
return(0);
}
int32_t LP_swap_load(struct LP_swap_remember *rswap)
int32_t LP_swap_load(struct LP_swap_remember *rswap,int32_t forceflag)
{
int32_t i,needflag,addflag; long fsize; char fname[1024],*fstr,*symbol,*rstr; cJSON *txobj,*sentobj,*fileobj; bits256 txid,checktxid; uint64_t value;
rswap->iambob = -1;
@ -680,7 +713,9 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap)
{
if ( (fileobj= cJSON_Parse(fstr)) != 0 )
{
rswap->origfinishedflag = rswap->finishedflag = 1;
rswap->finishtime = juint(fileobj,"finishtime");
if ( forceflag == 0 )
rswap->origfinishedflag = rswap->finishedflag = 1;
free_json(fileobj);
}
free(fstr);
@ -701,7 +736,11 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap)
rswap->iambob = jint(txobj,"iambob");
txid = jbits256(txobj,"txid");
if ( bits256_nonz(txid) == 0 )
{
free(fstr);
free_json(txobj);
continue;
}
rswap->txids[i] = txid;
if ( jstr(txobj,"Apayment") != 0 )
safecopy(rswap->alicepaymentaddr,jstr(txobj,"Apayment"),sizeof(rswap->alicepaymentaddr));
@ -753,7 +792,7 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap)
safecopy(rswap->alicecoin,symbol,sizeof(rswap->alicecoin));
if ( rswap->finishedflag == 0 )
{
if ( (sentobj= LP_gettx(symbol,txid)) == 0 )
if ( (sentobj= LP_gettx(symbol,txid,1)) == 0 )
{
char str2[65]; printf("%s %s ready to broadcast\n",symbol,bits256_str(str2,txid));
}
@ -773,6 +812,7 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap)
//printf("%s %s %.8f\n",txnames[i],bits256_str(str,txid),dstr(value));
}
}
free_json(txobj);
} //else printf("no symbol\n");
free(fstr);
} else if ( 0 && rswap->finishedflag == 0 )
@ -847,23 +887,30 @@ int32_t LP_spends_set(struct LP_swap_remember *rswap)
return(numspent);
}
cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requestid,uint32_t quoteid)
cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requestid,uint32_t quoteid,int32_t forceflag,int32_t pendingonly)
{
static void *ctx;
struct LP_swap_remember rswap; int32_t i,j,flag,numspent,len,secretstart,redeemlen; char str[65],*srcAdest,*srcBdest,*destAdest,*destBdest,otheraddr[64]; cJSON *item,*txoutobj; bits256 rev,signedtxid,zero,deadtxid; 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 )
if ( requestid == 0 || quoteid == 0 )
return(cJSON_Parse("{\"error\":\"null requestid or quoteid\"}"));
if ( (rswap.iambob= LP_rswap_init(&rswap,requestid,quoteid,forceflag)) < 0 )
return(cJSON_Parse("{\"error\":\"couldnt initialize rswap, are all coins active?\"}"));
decode_hex(deadtxid.bytes,32,"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
LP_swap_load(&rswap);
LP_swap_load(&rswap,forceflag);
memset(zero.bytes,0,sizeof(zero));
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 )
{
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??\"}"));
//printf("legacy r%u-q%u DB SWAPS.(%u %u) %llu files BOB.(%s) Alice.(%s) src.(%s) dest.(%s)\n",requestid,quoteid,rswap.requestid,rswap.quoteid,(long long)rswap.aliceid,rswap.bobcoin,rswap.alicecoin,rswap.src,rswap.dest);
cJSON *retjson = cJSON_CreateObject();
jaddstr(retjson,"error","swap never started");
jaddnum(retjson,"requestid",requestid);
jaddnum(retjson,"quoteid",quoteid);
return(retjson);
//return(cJSON_Parse("{\"error\":\"mismatched bob/alice vs src/dest coins??\"}"));
}
alice = LP_coinfind(rswap.alicecoin);
bob = LP_coinfind(rswap.bobcoin);
@ -876,6 +923,15 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
bitcoin_address(otheraddr,alice->taddr,alice->pubtype,rswap.other33,33);
destBdest = otheraddr;
destAdest = rswap.Adestaddr;
if ( strcmp(alice->smartaddr,rswap.Adestaddr) != 0 )
{
printf("this isnt my swap! alice.(%s vs %s)\n",alice->smartaddr,rswap.Adestaddr);
cJSON *retjson = cJSON_CreateObject();
jaddstr(retjson,"error","swap for different account");
jaddnum(retjson,"requestid",requestid);
jaddnum(retjson,"quoteid",quoteid);
return(retjson);
}
}
if ( (bob= LP_coinfind(rswap.bobcoin)) != 0 )
{
@ -891,6 +947,15 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
bitcoin_address(otheraddr,bob->taddr,bob->pubtype,rswap.other33,33);
srcAdest = otheraddr;
srcBdest = rswap.destaddr;
if ( strcmp(bob->smartaddr,rswap.destaddr) != 0 )
{
printf("this isnt my swap! bob.(%s vs %s)\n",bob->smartaddr,rswap.destaddr);
cJSON *retjson = cJSON_CreateObject();
jaddstr(retjson,"error","swap for different account");
jaddnum(retjson,"requestid",requestid);
jaddnum(retjson,"quoteid",quoteid);
return(retjson);
}
}
if ( (alice= LP_coinfind(rswap.alicecoin)) != 0 )
{
@ -969,7 +1034,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
}
if ( rswap.sentflags[BASILISK_ALICECLAIM] == 0 && rswap.sentflags[BASILISK_BOBDEPOSIT] != 0 && bits256_nonz(rswap.txids[BASILISK_BOBDEPOSIT]) != 0 && bits256_nonz(rswap.depositspent) == 0 )
{
if ( time(NULL) > rswap.expiration )
if ( time(NULL) > rswap.expiration+777 )
{
flag = 0;
if ( bob->electrum == 0 )
@ -1058,7 +1123,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
free_json(txoutobj), flag = 0;
else flag = -1, rswap.paymentspent = deadtxid;
}
if ( flag == 0 && time(NULL) > rswap.expiration )
if ( flag == 0 && time(NULL) > rswap.expiration+777 )
{
// bobreclaim
redeemlen = basilisk_swap_bobredeemscript(0,&secretstart,redeemscript,rswap.plocktime,rswap.pubA0,rswap.pubB0,rswap.pubB1,zero,rswap.privBn,rswap.secretAm,rswap.secretAm256,rswap.secretBn,rswap.secretBn256);
@ -1087,7 +1152,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
free_json(txoutobj), flag = 0;
else flag = -1, rswap.depositspent = deadtxid;
}
if ( flag == 0 && (bits256_nonz(rswap.Apaymentspent) != 0 || time(NULL) > rswap.expiration) )
if ( flag == 0 && (bits256_nonz(rswap.Apaymentspent) != 0 || time(NULL) > rswap.expiration+777) )
{
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 )
@ -1101,7 +1166,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
}
LP_txbytes_update("bobrefund",rswap.bobcoin,rswap.txbytes[BASILISK_BOBREFUND],&rswap.txids[BASILISK_BOBREFUND],&rswap.depositspent,&rswap.sentflags[BASILISK_BOBREFUND]);
}
else if ( flag == 0 )
else if ( 0 && flag == 0 )
printf("bobrefund's time %u vs expiration %u\n",(uint32_t)time(NULL),rswap.expiration);
}
}
@ -1126,29 +1191,48 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
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);
LP_numfinished++;
printf("SWAP %u-%u finished LP_numfinished.%d !\n",requestid,quoteid,LP_numfinished);
if ( rswap.finishtime == 0 )
rswap.finishtime = (uint32_t)time(NULL);
if ( rswap.tradeid != 0 )
LP_tradebot_finished(rswap.tradeid,rswap.requestid,rswap.quoteid);
sprintf(fname,"%s/SWAPS/%u-%u.finished",GLOBAL_DBDIR,rswap.requestid,rswap.quoteid), OS_compatible_path(fname);
item = LP_swap_json(&rswap);
if ( (fp= fopen(fname,"wb")) != 0 )
{
jaddstr(item,"method","tradestatus");
jaddnum(item,"finishtime",rswap.finishtime);
jaddstr(item,"gui",G.gui);
//jaddbits256(item,"srchash",rswap.Q.srchash);
//jaddbits256(item,"desthash",rswap.desthash);
itemstr = jprint(item,0);
fprintf(fp,"%s\n",itemstr);
LP_tradecommand_log(item);
LP_reserved_msg(rswap.src,rswap.dest,zero,clonestr(itemstr));
LP_broadcast_message(LP_mypubsock,rswap.src,rswap.dest,zero,itemstr);
LP_reserved_msg(1,rswap.src,rswap.dest,zero,clonestr(itemstr));
sleep(1);
LP_reserved_msg(0,rswap.src,rswap.dest,zero,itemstr);
//LP_broadcast_message(LP_mypubsock,rswap.src,rswap.dest,zero,itemstr);
fclose(fp);
}
} else item = LP_swap_json(&rswap);
for (i=0; i<sizeof(txnames)/sizeof(*txnames); i++)
if ( rswap.txbytes[i] != 0 )
free(rswap.txbytes[i]), rswap.txbytes[i] = 0;
if ( pendingonly != 0 && rswap.origfinishedflag != 0 )
{
free_json(item);
item = 0;
}
return(item);
}
char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid)
char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid,int32_t forceflag,int32_t pendingonly)
{
uint64_t ridqids[4096],ridqid; char fname[512]; FILE *fp; cJSON *item,*retjson,*array,*totalsobj; uint32_t r,q,quoteid,requestid; int64_t KMDtotals[16],BTCtotals[16],Btotal,Ktotal; int32_t i,j,count=0;
uint64_t ridqids[4096],ridqid; char fname[512]; FILE *fp; cJSON *item,*retjson,*array,*totalsobj; uint32_t r,q,quoteid,requestid; int64_t KMDtotals[LP_MAXPRICEINFOS],BTCtotals[LP_MAXPRICEINFOS],Btotal,Ktotal; int32_t i,j,count=0;
portable_mutex_lock(&LP_swaplistmutex);
memset(ridqids,0,sizeof(ridqids));
memset(KMDtotals,0,sizeof(KMDtotals));
@ -1159,7 +1243,7 @@ char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid)
if ( origrequestid != 0 && origquoteid != 0 )
{
//printf("orig req.%u q.%u\n",origrequestid,origquoteid);
if ( (item= basilisk_remember(KMDtotals,BTCtotals,origrequestid,origquoteid)) != 0 )
if ( (item= basilisk_remember(KMDtotals,BTCtotals,origrequestid,origquoteid,forceflag,0)) != 0 )
jaddi(array,item);
//printf("got.(%s)\n",jprint(item,0));
}
@ -1173,19 +1257,22 @@ char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid)
while ( fread(&requestid,1,sizeof(requestid),fp) == sizeof(requestid) && fread(&quoteid,1,sizeof(quoteid),fp) == sizeof(quoteid) )
{
flag = 0;
for (i=0; i<G.LP_numskips; i++)
if ( pendingonly == 0 )
{
r = (uint32_t)(G.LP_skipstatus[i] >> 32);
q = (uint32_t)G.LP_skipstatus[i];
if ( r == requestid && q == quoteid )
for (i=0; i<G.LP_numskips; i++)
{
item = cJSON_CreateObject();
jaddstr(item,"status","realtime");
jaddnum(item,"requestid",r);
jaddnum(item,"quoteid",q);
jaddi(array,item);
flag = 1;
break;
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");
jaddnum(item,"requestid",r);
jaddnum(item,"quoteid",q);
jaddi(array,item);
flag = 1;
break;
}
}
}
if ( flag == 0 )
@ -1198,7 +1285,7 @@ char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid)
{
if ( count < sizeof(ridqids)/sizeof(*ridqids) )
ridqids[count++] = ridqid;
if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid)) != 0 )
if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid,0,pendingonly)) != 0 )
jaddi(array,item);
}
}
@ -1227,43 +1314,18 @@ char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid)
else if ( Ktotal < 0 && Btotal > 0 )
jaddnum(retjson,"avesell",(double)-Btotal/Ktotal);
}
/*array = cJSON_CreateArray();
for (i=0; i<sizeof(myinfo->linfos)/sizeof(*myinfo->linfos); i++)
{
if ( myinfo->linfos[i].base[0] != 0 && myinfo->linfos[i].rel[0] != 0 )
jaddi(array,linfo_json(&myinfo->linfos[i]));
}
jadd(retjson,"quotes",array);*/
portable_mutex_unlock(&LP_swaplistmutex);
return(jprint(retjson,1));
}
char *basilisk_swapentry(uint32_t requestid,uint32_t quoteid)
char *basilisk_swapentry(uint32_t requestid,uint32_t quoteid,int32_t forceflag)
{
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 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
//printf("(%s) check r%u/q%u\n",jprint(item,0),juint(item,"requestid"),juint(item,"quoteid"));
if ( juint(item,"requestid") == requestid && juint(item,"quoteid") == quoteid )
{
retstr = jprint(item,0);
break;
}
}
}
free_json(retjson);
}
free(liststr);
}
return(retstr);
cJSON *item; int64_t KMDtotals[LP_MAXPRICEINFOS],BTCtotals[LP_MAXPRICEINFOS];
memset(KMDtotals,0,sizeof(KMDtotals));
memset(BTCtotals,0,sizeof(BTCtotals));
if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid,forceflag,0)) != 0 )
return(jprint(item,1));
else return(clonestr("{\"error\":\"cant find requestid-quoteid\"}"));
}
extern struct LP_quoteinfo LP_Alicequery;
@ -1271,7 +1333,10 @@ 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;
char fname[512],*retstr,*base,*rel,*statusstr; long fsize,offset; FILE *fp; int32_t baseind,relind,i=0; uint32_t requestid,quoteid; cJSON *array,*item,*retjson,*subitem,*swapjson; int64_t KMDtotals[LP_MAXPRICEINFOS],BTCtotals[LP_MAXPRICEINFOS]; double srcamount,destamount,netamounts[LP_MAXPRICEINFOS];
memset(KMDtotals,0,sizeof(KMDtotals));
memset(BTCtotals,0,sizeof(BTCtotals));
memset(netamounts,0,sizeof(netamounts));
if ( limit <= 0 )
limit = 3;
sprintf(fname,"%s/SWAPS/list",GLOBAL_DBDIR), OS_compatible_path(fname);
@ -1293,6 +1358,36 @@ char *LP_recent_swaps(int32_t limit)
item = cJSON_CreateArray();
jaddinum(item,requestid);
jaddinum(item,quoteid);
if ( (retstr= basilisk_swapentry(requestid,quoteid,0)) != 0 )
{
if ( (swapjson= cJSON_Parse(retstr)) != 0 )
{
base = jstr(swapjson,"bob");
rel = jstr(swapjson,"alice");
statusstr = jstr(swapjson,"status");
baseind = relind = -1;
if ( base != 0 && rel != 0 && statusstr != 0 && strcmp(statusstr,"finished") == 0 && (baseind= LP_priceinfoind(base)) >= 0 && (relind= LP_priceinfoind(rel)) >= 0 )
{
srcamount = jdouble(swapjson,"srcamount");
destamount = jdouble(swapjson,"destamount");
if ( jint(swapjson,"iambob") != 0 )
srcamount = -srcamount;
else destamount = -destamount;
if ( srcamount != 0. && destamount != 0. )
{
netamounts[baseind] += srcamount;
netamounts[relind] += destamount;
subitem = cJSON_CreateObject();
jaddnum(subitem,base,srcamount);
jaddnum(subitem,rel,destamount);
jaddnum(subitem,"price",-destamount/srcamount);
jaddi(item,subitem);
}
} else printf("base.%p rel.%p statusstr.%p baseind.%d relind.%d\n",base,rel,statusstr,baseind,relind);
free_json(swapjson);
} else printf("error parsing.(%s)\n",retstr);
free(retstr);
}
jaddi(array,item);
} else break;
} else break;
@ -1302,11 +1397,23 @@ char *LP_recent_swaps(int32_t limit)
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jadd(retjson,"swaps",array);
array = cJSON_CreateArray();
for (i=0; i<LP_MAXPRICEINFOS; i++)
{
if ( netamounts[i] != 0. )
{
item = cJSON_CreateObject();
jaddnum(item,LP_priceinfostr(i),netamounts[i]);
jaddi(array,item);
}
}
jadd(retjson,"netamounts",array);
if ( time(NULL) < Alice_expiration )
{
item = cJSON_CreateObject();
jaddnum(item,"expiration",Alice_expiration);
jaddnum(item,"timeleft",Alice_expiration-time(NULL));
jaddnum(item,"tradeid",LP_Alicequery.tradeid);
jaddnum(item,"requestid",LP_Alicequery.R.requestid);
jaddnum(item,"quoteid",LP_Alicequery.R.quoteid);
jaddstr(item,"bob",LP_Alicequery.srccoin);
@ -1315,6 +1422,7 @@ char *LP_recent_swaps(int32_t limit)
jaddstr(item,"alice",LP_Alicequery.destcoin);
jaddstr(item,"rel",LP_Alicequery.destcoin);
jaddnum(item,"relvalue",dstr(LP_Alicequery.destsatoshis));
jaddnum(item,"aliceid",LP_aliceid_calc(LP_Alicequery.desttxid,LP_Alicequery.destvout,LP_Alicequery.feetxid,LP_Alicequery.feevout));
jadd(retjson,"pending",item);
} else Alice_expiration = 0;
return(jprint(retjson,1));
@ -1349,7 +1457,7 @@ char *basilisk_swapentries(char *refbase,char *refrel,int32_t limit)
limit = 10;
memset(ridqids,0,sizeof(ridqids));
retarray = cJSON_CreateArray();
if ( (liststr= basilisk_swaplist(0,0)) != 0 )
if ( (liststr= basilisk_swaplist(0,0,0,0)) != 0 )
{
//printf("swapentry.(%s)\n",liststr);
if ( (retjson= cJSON_Parse(liststr)) != 0 )
@ -1392,7 +1500,7 @@ char *basilisk_swapentries(char *refbase,char *refrel,int32_t limit)
//printf("j.%d count.%d %u %u ridqid.%16llx\n",j,count,requestid,quoteid,(long long)ridqid);
if ( j == count )
{
if ( (retstr2= basilisk_swapentry(requestid,quoteid)) != 0 )
if ( (retstr2= basilisk_swapentry(requestid,quoteid,0)) != 0 )
{
if ( (swapjson= cJSON_Parse(retstr2)) != 0 )
{
@ -1433,3 +1541,40 @@ char *basilisk_swapentries(char *refbase,char *refrel,int32_t limit)
return(jprint(retarray,1));
}
int32_t LP_pendingswap(uint32_t requestid,uint32_t quoteid)
{
cJSON *retjson,*array,*pending,*item; uint32_t r,q; char *retstr; int32_t i,n,retval = 0;
if ( (retstr= LP_recent_swaps(1000)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (array= jarray(&n,retjson,"swaps")) != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
r = juint(jitem(item,0),0);
q = juint(jitem(item,1),0);
if ( r == requestid && q == quoteid )
{
retval = 1;
break;
}
}
}
if ( retval == 0 )
{
if ( (pending= jobj(retjson,"pending")) != 0 )
{
r = juint(pending,"requestid");
q = juint(pending,"quoteid");
if ( r == requestid && q == quoteid )
retval = 1;
}
}
free_json(retjson);
}
free(retstr);
}
return(retval);
}

632
iguana/exchanges/LP_rpc.c

@ -1,4 +1,3 @@
/******************************************************************************
* Copyright © 2014-2017 The SuperNET Developers. *
* *
@ -18,27 +17,6 @@
// marketmaker
//
char *LP_issue_curl(char *debugstr,char *destip,uint16_t port,char *url)
{
char *retstr = 0; int32_t maxerrs; struct LP_peerinfo *peer = 0;
peer = LP_peerfind((uint32_t)calc_ipbits(destip),port);
maxerrs = LP_MAXPEER_ERRORS;
if ( peer == 0 || (peer->errors < maxerrs || peer->good >= LP_MINPEER_GOOD) )
{
if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) == 0 )
{
if ( peer != 0 )
{
peer->errors++;
peer->good *= LP_PEERGOOD_ERRORDECAY;
} else printf("%s error on (%s:%u) without peer\n",debugstr,destip,port);
}
else if ( peer != 0 )
peer->good++;
}
return(retstr);
}
char *LP_isitme(char *destip,uint16_t destport)
{
if ( LP_mypeer != 0 && strcmp(destip,LP_mypeer->ipaddr) == 0 && LP_mypeer->port == destport )
@ -48,59 +26,6 @@ char *LP_isitme(char *destip,uint16_t destport)
} else return(0);
}
char *issue_LP_getpeers(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers)
{
char url[512],*retstr;
sprintf(url,"http://%s:%u/api/stats/getpeers?ipaddr=%s&port=%u&numpeers=%d",destip,destport,ipaddr,port,numpeers);
retstr = LP_issue_curl("getpeers",destip,port,url);
//printf("%s -> getpeers.(%s)\n",destip,retstr);
return(retstr);
}
char *issue_LP_uitem(char *destip,uint16_t destport,char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t height,uint64_t value)
{
char url[512],*retstr,str[65];
if ( (retstr= LP_isitme(destip,destport)) != 0 )
return(retstr);
sprintf(url,"http://%s:%u/api/stats/uitem?coin=%s&coinaddr=%s&txid=%s&vout=%d&ht=%d&value=%llu",destip,destport,symbol,coinaddr,bits256_str(str,txid),vout,height,(long long)value);
retstr = LP_issue_curl("uitem",destip,destport,url);
//printf("uitem.(%s)\n",retstr);
return(retstr);
}
char *issue_LP_notify(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers,uint32_t sessionid,char *rmd160str,bits256 pub)
{
char url[512],*retstr,str[65];
if ( (retstr= LP_isitme(destip,destport)) != 0 )
return(retstr);
sprintf(url,"http://%s:%u/api/stats/notify?ipaddr=%s&port=%u&numpeers=%d&session=%u",destip,destport,ipaddr,port,numpeers,sessionid);
if ( rmd160str != 0 && bits256_nonz(pub) != 0 )
{
sprintf(url+strlen(url),"&rmd160=%s&pub=%s",rmd160str,bits256_str(str,pub));
//printf("SEND (%s)\n",url);
}
return(LP_issue_curl("notify",destip,destport,url));
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
}
char *issue_LP_getprices(char *destip,uint16_t destport)
{
char url[512];
sprintf(url,"http://%s:%u/api/stats/getprices",destip,destport);
//printf("getutxo.(%s)\n",url);
return(LP_issue_curl("getprices",destip,destport,url));
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
}
char *issue_LP_listunspent(char *destip,uint16_t destport,char *symbol,char *coinaddr)
{
char url[512],*retstr;
sprintf(url,"http://%s:%u/api/stats/listunspent?coin=%s&address=%s",destip,destport,symbol,coinaddr);
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)
{
cJSON *retjson; char *retstr;
@ -110,7 +35,7 @@ char *LP_apicall(struct iguana_info *coin,char *method,char *params)
{
if ( (retjson= electrum_submit(coin->symbol,coin->electrum,&retjson,method,params,ELECTRUM_TIMEOUT)) != 0 )
{
retstr = jprint(retjson,0);
retstr = jprint(retjson,1);
//printf("got.%p (%s)\n",retjson,retstr);
return(retstr);
} return(clonestr("{\"error\":\"electrum no response\"}"));
@ -127,7 +52,7 @@ cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params)
//printf("issue.(%s, %s, %s, %s, %s)\n",coin->symbol,coin->serverport,coin->userpass,method,params);
if ( coin->electrum != 0 && (strcmp(method,"getblock") == 0 || strcmp(method,"paxprice") == 0 || strcmp(method,"getrawmempool") == 0) )
return(cJSON_Parse("{\"error\":\"illegal electrum call\"}"));
if ( coin->inactive == 0 || strcmp(method,"importprivkey") == 0 || strcmp(method,"validateaddress") == 0 )
if ( coin->inactive == 0 || strcmp(method,"importprivkey") == 0 || strcmp(method,"validateaddress") == 0 || strcmp(method,"getrawtransaction") == 0 || strcmp(method,"getblock") == 0 || strcmp(method,"getinfo") == 0 )
{
if ( coin->electrum == 0 )
{
@ -149,13 +74,6 @@ cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params)
free_json(retjson);
retjson = 0;
}
//printf("electrum %s.%s -> (%s)\n",method,params,jprint(retjson,0));
/*if ( (resultjson= jobj(retjson,"result")) != 0 )
{
resultjson = jduplicate(resultjson);
free_json(retjson);
retjson = resultjson;
}*/
}
}
} else retjson = cJSON_Parse("{\"result\":\"disabled\"}");
@ -165,167 +83,17 @@ cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params)
void LP_unspents_mark(char *symbol,cJSON *vins)
{
printf("LOCK (%s)\n",jprint(vins,0));
}
char *NXTnodes[] = { "62.75.159.113", "91.44.203.238", "82.114.88.225", "78.63.207.76", "188.174.110.224", "91.235.72.49", "213.144.130.91", "209.222.98.250", "216.155.128.10", "178.33.203.157", "162.243.122.251", "69.163.47.173", "193.151.106.129", "78.94.2.74", "192.3.196.10", "173.33.112.87", "104.198.173.28", "35.184.154.126", "174.140.167.239", "23.88.113.131", "198.71.84.173", "178.150.207.53", "23.88.61.53", "192.157.233.106", "192.157.241.212", "23.89.192.88", "23.89.200.27", "192.157.241.139", "23.89.200.63", "23.89.192.98", "163.172.214.102", "176.9.85.5", "80.150.243.88", "80.150.243.92", "80.150.243.98", "109.70.186.198", "146.148.84.237", "104.155.56.82", "104.197.157.140", "37.48.73.249", "146.148.77.226", "84.57.170.200", "107.161.145.131", "80.150.243.97", "80.150.243.93", "80.150.243.100", "80.150.243.95", "80.150.243.91", "80.150.243.99", "80.150.243.96", "93.231.187.177", "212.237.23.85", "35.158.179.254", "46.36.66.41", "185.170.113.79", "163.172.68.112", "78.47.35.210", "77.90.90.75", "94.177.196.134", "212.237.22.215", "94.177.234.11", "167.160.180.199", "54.68.189.9", "94.159.62.14", "195.181.221.89", "185.33.145.94", "195.181.209.245", "195.181.221.38", "195.181.221.162", "185.33.145.12", "185.33.145.176", "178.79.128.235", "94.177.214.120", "94.177.199.41", "94.177.214.200", "94.177.213.201", "212.237.13.162", "195.181.221.236", "195.181.221.185", "185.28.103.187", "185.33.146.244", "217.61.123.71", "195.181.214.45", "195.181.212.99", "195.181.214.46", "195.181.214.215", "195.181.214.68", "217.61.123.118", "195.181.214.79", "217.61.123.14", "217.61.124.100", "195.181.214.111", "85.255.0.176", "81.2.254.116", "217.61.123.184", "195.181.212.231", "94.177.214.110", "195.181.209.164", "104.129.56.238", "85.255.13.64", "167.160.180.206", "217.61.123.226", "167.160.180.208", "93.186.253.127", "212.237.6.208", "94.177.207.190", "217.61.123.119", "85.255.1.245", "217.61.124.157", "37.59.57.141", "167.160.180.58", "104.223.53.14", "217.61.124.69", "195.181.212.103", "85.255.13.141", "104.207.133.204", "71.90.7.107", "107.150.18.108", "23.94.134.161", "80.150.243.13", "80.150.243.11", "185.81.165.52", "80.150.243.8" };
static char *assetids[][4] =
{
{ "13502152099823770958", "SUPERNETx2", "10000", "10000" },
{ "12071612744977229797", "SUPERNET", "10000", "10000" },
{ "12071612744977229797", "UNITY", "10000", "10000" },
{ "15344649963748848799", "DEX", "1", "100000000" },
{ "6883271355794806507", "PANGEA", "10000", "10000" },
{ "17911762572811467637", "JUMBLR", "10000", "10000" },
{ "17083334802666450484", "BET", "10000", "10000" },
{ "13476425053110940554", "CRYPTO", "1000", "100000" },
{ "6932037131189568014", "HODL", "1", "100000000" },
{ "3006420581923704757", "SHARK", "10000", "10000" },
{ "17571711292785902558", "BOTS", "1", "100000000" },
{ "10524562908394749924", "MGW", "1", "100000000" },
};
uint64_t LP_assetid_mult(int32_t *assetindp,char *name,uint64_t assetid)
{
int32_t i; uint64_t mult = 0;
name[0] = 0;
*assetindp = -1;
for (i=0; i<sizeof(assetids)/sizeof(*assetids); i++)
{
if ( assetid == calc_nxt64bits(assetids[i][0]) )
{
*assetindp = i;
mult = atoi(assetids[i][3]);
strcpy(name,assetids[i][1]);
break;
}
}
return(mult);
}
cJSON *LP_NXT_message(char *method,uint64_t txnum,char *passphrase)
{
char url[1024],*retstr; cJSON *retjson = 0;
sprintf(url,"http://127.0.0.1:7876/nxt?requestType=%s&transaction=%llu&secretPhrase=%s",method,(long long)txnum,passphrase);
//printf("issue.(%s)\n",url);
if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
}
free(retstr);
}
return(retjson);
//printf("LOCK (%s)\n",jprint(vins,0));
}
cJSON *LP_NXT_redeems()
{
char url[1024],*retstr,*recv,*method,*msgstr,assetname[16]; uint64_t totals[20],mult,txnum,assetid,qty; int32_t i,ind,numtx; cJSON *item,*attach,*array,*msgjson,*encjson,*retjson=0;
memset(totals,0,sizeof(totals));
sprintf(url,"http://127.0.0.1:7876/nxt?requestType=getBlockchainTransactions&account=NXT-MRBN-8DFH-PFMK-A4DBM");//,NXTnodes[rand() % (sizeof(NXTnodes)/sizeof(*NXTnodes))]);
//printf("calling (%s)\n",url);
if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (array= jarray(&numtx,retjson,"transactions")) != 0 )
{
for (i=0; i<numtx; i++)
{
msgjson = 0;
txnum = assetid = qty = 0;
item = jitem(array,i);
msgstr = jstr(item,"message");
txnum = j64bits(item,"transaction");
//printf("%d: %s\n",i,jprint(item,0));
if ( (recv= jstr(item,"recipientRS")) != 0 && strcmp(recv,"NXT-MRBN-8DFH-PFMK-A4DBM") == 0 )
{
if ( (attach= jobj(item,"attachment")) != 0 && jint(attach,"version.AssetTransfer") == 1 )
{
assetid = j64bits(attach,"asset");
qty = j64bits(attach,"quantityQNT");
//printf("txnum.%llu (%s)\n",(long long)txnum,jprint(attach,0));
if ( (msgstr == 0 || msgstr[0] == 0) && jint(attach,"version.PrunablePlainMessage") == 1 )
{
method = "getPrunableMessage";
if ( (msgjson= LP_NXT_message(method,txnum,"test")) != 0 )
{
msgstr = jstr(msgjson,"message");
//printf("%d method.(%s) (%s)\n",i,method,msgstr);
}
}
if ( msgstr == 0 || msgstr[0] == 0 )
msgstr = jstr(attach,"message");
if ( msgstr == 0 || msgstr[0] == 0 )
{
if ( (encjson= jobj(attach,"encryptedMessage")) != 0 )
msgstr = "encryptedMessage";//jstr(encjson,"data");
}
}
mult = LP_assetid_mult(&ind,assetname,assetid);
if ( ind >= 0 )
totals[ind] += qty * mult;
if ( msgstr != 0 && assetname[0] != 0 && qty != 0 )
printf("%-4d: (%35s) <- %13.5f %10s tx.%llu\n",i,msgstr!=0?msgstr:jprint(item,0),dstr(qty * mult),assetname,(long long)txnum);
if ( msgjson != 0 )
free_json(msgjson);
}
if ( txnum == calc_nxt64bits("7256847492742571143") )
break;
}
}
free_json(retjson);
}
free(retstr);
}
printf("\nTotal redeemed\n");
for (i=0; i<sizeof(totals)/sizeof(*totals); i++)
{
if ( totals[i] != 0 )
printf("%-10s %13.5f\n",assetids[i][1],dstr(totals[i]));
}
return(retjson);
}
cJSON *LP_assethbla(char *assetid)
{
char url[1024],*retstr; int32_t n; cJSON *array,*bid=0,*ask=0,*retjson;
sprintf(url,"http://%s:7876/nxt?requestType=getBidOrders&asset=%s&firstIndex=0&lastIndex=0",NXTnodes[rand() % (sizeof(NXTnodes)/sizeof(*NXTnodes))],assetid);
if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 )
{
bid = cJSON_Parse(retstr);
free(retstr);
}
sprintf(url,"http://%s:7876/nxt?requestType=getAskOrders&asset=%s&firstIndex=0&lastIndex=0",NXTnodes[rand() % (sizeof(NXTnodes)/sizeof(*NXTnodes))],assetid);
if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 )
{
ask = cJSON_Parse(retstr);
free(retstr);
}
retjson = cJSON_CreateObject();
if ( bid != 0 && ask != 0 )
{
if ( (array= jarray(&n,bid,"bidOrders")) != 0 )
jadd(retjson,"bid",jduplicate(jitem(array,0)));
if ( (array= jarray(&n,ask,"askOrders")) != 0 )
jadd(retjson,"ask",jduplicate(jitem(array,0)));
}
if ( bid != 0 )
free_json(bid);
if ( ask != 0 )
free_json(ask);
return(retjson);
}
int32_t LP_getheight(struct iguana_info *coin)
int32_t LP_getheight(int32_t *notarizedp,struct iguana_info *coin)
{
cJSON *retjson; char *retstr,*method = "getinfo"; int32_t height;
*notarizedp = 0;
if ( coin == 0 )
return(-1);
height = coin->height;
if ( coin->electrum == 0 && time(NULL) > coin->heighttime+60 )
if ( coin->electrum == 0 && time(NULL) > coin->heighttime+60 && coin->userpass[0] != 0 )
{
if ( strcmp(coin->symbol,"BTC") == 0 )
method = "getblockchaininfo";
@ -334,6 +102,13 @@ int32_t LP_getheight(struct iguana_info *coin)
{
retjson = cJSON_Parse(retstr);
coin->height = height = jint(retjson,"blocks");
if ( (*notarizedp= jint(retjson,"notarized")) != 0 && *notarizedp != coin->notarized )
{
printf("new notarized %s %d -> %d\n",coin->symbol,coin->notarized,*notarizedp);
coin->notarized = *notarizedp;
coin->notarizationtxid = jbits256(retjson,"notarizedtxid");
coin->notarizedhash = jbits256(retjson,"notarizedhash");
}
free_json(retjson);
if ( coin->height > 0 )
coin->heighttime = (uint32_t)time(NULL);
@ -343,7 +118,7 @@ int32_t LP_getheight(struct iguana_info *coin)
return(height);
}
uint64_t LP_smartbalance(struct iguana_info *coin)
uint64_t LP_RTsmartbalance(struct iguana_info *coin)
{
cJSON *array,*item; char buf[512],*retstr; int32_t i,n; uint64_t valuesum,value;
valuesum = 0;
@ -366,7 +141,7 @@ uint64_t LP_smartbalance(struct iguana_info *coin)
return(valuesum);
}
cJSON *LP_getmempool(char *symbol,char *coinaddr)
cJSON *LP_getmempool(char *symbol,char *coinaddr,bits256 txid,bits256 txid2)
{
cJSON *array; struct iguana_info *coin;
if ( symbol == 0 || symbol[0] == 0 )
@ -376,7 +151,7 @@ cJSON *LP_getmempool(char *symbol,char *coinaddr)
return(cJSON_Parse("{\"error\":\"no native coin\"}"));
if ( coin->electrum == 0 )
return(bitcoin_json(coin,"getrawmempool","[]"));
else return(electrum_address_getmempool(symbol,coin->electrum,&array,coinaddr));
else return(electrum_address_getmempool(symbol,coin->electrum,&array,coinaddr,txid,txid2));
}
cJSON *LP_paxprice(char *fiat)
@ -388,9 +163,9 @@ cJSON *LP_paxprice(char *fiat)
return(bitcoin_json(coin,"paxprice",buf));
}
cJSON *LP_gettx(char *symbol,bits256 txid)
cJSON *LP_gettx(char *symbol,bits256 txid,int32_t suppress_errors)
{
struct iguana_info *coin; char buf[512],str[65]; cJSON *retjson;
struct iguana_info *coin; char buf[512],str[65]; int32_t height; cJSON *retjson;
//printf("LP_gettx %s %s\n",symbol,bits256_str(str,txid));
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
@ -407,9 +182,10 @@ cJSON *LP_gettx(char *symbol,bits256 txid)
}
else
{
if ( (retjson= electrum_transaction(symbol,coin->electrum,&retjson,txid)) != 0 )
if ( (retjson= electrum_transaction(&height,symbol,coin->electrum,&retjson,txid,0)) != 0 )
return(retjson);
else printf("failed blockchain.transaction.get %s %s\n",coin->symbol,bits256_str(str,txid));
else if ( suppress_errors == 0 )
printf("failed blockchain.transaction.get %s %s\n",coin->symbol,bits256_str(str,txid));
return(cJSON_Parse("{\"error\":\"no transaction bytes\"}"));
}
}
@ -417,7 +193,7 @@ 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 )
if ( (txobj= LP_gettx(symbol,txid,0)) != 0 )
{
locktime = juint(txobj,"locktime");
free_json(txobj);
@ -446,7 +222,7 @@ cJSON *LP_gettxout_json(bits256 txid,int32_t vout,int32_t height,char *coinaddr,
cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout)
{
char buf[128],str[65]; cJSON *item,*array,*vouts,*txobj,*retjson=0; int32_t i,v,n; bits256 t; struct iguana_info *coin; struct LP_transaction *tx; struct LP_address_utxo *up;
char buf[128],str[65]; cJSON *item,*array,*vouts,*txobj,*retjson=0; int32_t i,v,height,n; bits256 t,zero; struct iguana_info *coin; struct LP_transaction *tx; struct LP_address_utxo *up;
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
if ( (coin= LP_coinfind(symbol)) == 0 )
@ -468,7 +244,7 @@ cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout)
}
if ( coinaddr[0] == 0 )
{
if ( (txobj= electrum_transaction(symbol,coin->electrum,&txobj,txid)) != 0 )
if ( (txobj= electrum_transaction(&height,symbol,coin->electrum,&txobj,txid,0)) != 0 )
{
if ( (vouts= jarray(&n,txobj,"vout")) != 0 && n > 0 )
LP_destaddr(coinaddr,jitem(vouts,vout));
@ -483,7 +259,8 @@ 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,1)) != 0 )
memset(zero.bytes,0,sizeof(zero));
if ( (array= electrum_address_listunspent(coin->symbol,0,&array,coinaddr,1,txid,zero)) != 0 )
{
//printf("array.(%s)\n",jprint(array,0));
if ( array != 0 && (n= cJSON_GetArraySize(array)) > 0 )
@ -505,22 +282,11 @@ cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout)
return(retjson);
}
}
printf("couldnt find %s/v%d\n",bits256_str(str,txid),vout);
//printf("couldnt find %s (%s) %s/v%d\n",symbol,coinaddr,bits256_str(str,txid),vout);
return(cJSON_Parse("{\"error\":\"couldnt get tx\"}"));
}
}
/*cJSON *LP_listtransactions(char *symbol,char *coinaddr,int32_t count,int32_t skip)
{
char buf[128]; struct iguana_info *coin = LP_coinfind(symbol);
if ( coin == 0 )
return(cJSON_Parse("{\"error\":\"no coin\"}"));
if ( count == 0 )
count = 100;
sprintf(buf,"[\"%s\", %d, %d, true]",coinaddr,count,skip);
return(bitcoin_json(coin,"listtransactions",buf));
}*/
cJSON *LP_validateaddress(char *symbol,char *address)
{
char buf[512],coinaddr[64],checkaddr[64],script[128]; int32_t i; uint8_t rmd160[20],addrtype; cJSON *retjson; struct iguana_info *coin;
@ -547,7 +313,7 @@ cJSON *LP_validateaddress(char *symbol,char *address)
}
bitcoin_address(coinaddr,coin->taddr,coin->pubtype,G.LP_myrmd160,20);
jadd(retjson,"ismine",strcmp(address,coin->smartaddr) == 0 ? cJSON_CreateTrue() : cJSON_CreateFalse());
jadd(retjson,"iswatchonly",cJSON_CreateFalse());
jadd(retjson,"iswatchonly",cJSON_CreateTrue());
jadd(retjson,"isscript",addrtype == coin->p2shtype ? cJSON_CreateTrue() : cJSON_CreateFalse());
return(retjson);
}
@ -560,12 +326,12 @@ cJSON *LP_validateaddress(char *symbol,char *address)
int32_t LP_address_ismine(char *symbol,char *address)
{
int32_t doneflag = 0; cJSON *retjson;
int32_t doneflag = 0; cJSON *retjson,*obj;
if ( symbol == 0 || symbol[0] == 0 )
return(0);
if ( (retjson= LP_validateaddress(symbol,address)) != 0 )
{
if ( jobj(retjson,"ismine") != 0 && is_cJSON_True(jobj(retjson,"ismine")) != 0 )
if ( (obj= jobj(retjson,"ismine")) != 0 && is_cJSON_True(obj) != 0 )
{
doneflag = 1;
//printf("%s ismine (%s)\n",address,jprint(retjson,0));
@ -576,6 +342,24 @@ int32_t LP_address_ismine(char *symbol,char *address)
return(doneflag);
}
int32_t LP_address_iswatchonly(char *symbol,char *address)
{
int32_t doneflag = 0; cJSON *retjson,*obj;
if ( symbol == 0 || symbol[0] == 0 )
return(0);
if ( (retjson= LP_validateaddress(symbol,address)) != 0 )
{
if ( (obj= jobj(retjson,"iswatchonly")) != 0 && is_cJSON_True(obj) != 0 )
{
doneflag = 1;
//printf("%s iswatchonly (%s)\n",address,jprint(retjson,0));
}
//printf("%s\n",jprint(retjson,0));
free_json(retjson);
}
return(doneflag);
}
int32_t LP_address_isvalid(char *symbol,char *address)
{
int32_t isvalid = 0; cJSON *retjson;
@ -594,38 +378,110 @@ int32_t LP_address_isvalid(char *symbol,char *address)
return(isvalid);
}
cJSON *LP_listunspent(char *symbol,char *coinaddr)
cJSON *LP_listunspent(char *symbol,char *coinaddr,bits256 reftxid,bits256 reftxid2)
{
char buf[128]; cJSON *retjson; int32_t numconfs; struct iguana_info *coin;
char buf[128],*retstr; struct LP_address *ap; cJSON *retjson; int32_t numconfs,usecache=1; struct iguana_info *coin;
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
coin = LP_coinfind(symbol);
//printf("LP_listunspent.(%s %s)\n",symbol,coinaddr);
if ( coin == 0 || (IAMLP == 0 && coin->inactive != 0) )
return(cJSON_Parse("{\"error\":\"no coin\"}"));
if ( coin->electrum == 0 )
{
if ( LP_address_ismine(symbol,coinaddr) > 0 )
if ( (ap= LP_addressfind(coin,coinaddr)) != 0 )
{
if ( ap->unspenttime == 0 )
usecache = 0;
else if ( G.LP_pendingswaps != 0 && time(NULL) > ap->unspenttime+1 )
usecache = 0;
if ( usecache != 0 && (retstr= LP_unspents_filestr(symbol,coinaddr)) != 0 )
{
retjson = cJSON_Parse(retstr);
free(retstr);
return(retjson);
}
}
//printf("%s %s usecache.%d iswatched.%d\n",coin->symbol,coinaddr,usecache,LP_address_iswatchonly(symbol,coinaddr));
if ( LP_address_ismine(symbol,coinaddr) > 0 || LP_address_iswatchonly(symbol,coinaddr) > 0 )
{
if ( strcmp(symbol,"BTC") == 0 )
numconfs = 0;
else numconfs = 1;
sprintf(buf,"[%d, 99999999, [\"%s\"]]",numconfs,coinaddr);
return(bitcoin_json(coin,"listunspent",buf));
//printf("LP_listunspent.(%s %s)\n",symbol,coinaddr);
retjson = bitcoin_json(coin,"listunspent",buf);
retstr = jprint(retjson,0);
LP_unspents_cache(coin->symbol,coinaddr,retstr,1);
free(retstr);
if ( ap != 0 )
ap->unspenttime = (uint32_t)time(NULL);
return(retjson);
} else return(LP_address_utxos(coin,coinaddr,0));
} else return(electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,1));
} else return(electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,1,reftxid,reftxid2));
}
int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag)
cJSON *LP_listreceivedbyaddress(char *symbol,char *coinaddr)
{
struct iguana_info *coin; int32_t n = 0; cJSON *retjson=0; char *retstr=0,destip[64]; uint16_t destport;
char buf[128],*addr; bits256 zero; cJSON *retjson,*array,*item; int32_t i,n; struct iguana_info *coin;
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
coin = LP_coinfind(symbol);
if ( coin == 0 || (IAMLP == 0 && coin->inactive != 0) )
return(cJSON_Parse("{\"error\":\"no coin\"}"));
memset(zero.bytes,0,sizeof(zero));
if ( coin->electrum == 0 )
{
sprintf(buf,"[1, false, true]");
if ( (array= bitcoin_json(coin,"listreceivedbyaddress",buf)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( (addr= jstr(item,"address")) != 0 && strcmp(addr,coinaddr) == 0 )
{
retjson = jduplicate(jobj(item,"txids"));
free_json(array);
return(retjson);
}
}
}
}
return(cJSON_Parse("[]"));
} else return(electrum_address_gethistory(symbol,coin->electrum,&retjson,coinaddr,zero));
}
int64_t LP_listunspent_parseitem(struct iguana_info *coin,bits256 *txidp,int32_t *voutp,int32_t *heightp,cJSON *item)
{
int64_t satoshis = 0;
if ( coin->electrum == 0 )
{
*txidp = jbits256(item,"txid");
*voutp = juint(item,"vout");
satoshis = LP_value_extract(item,0);
*heightp = LP_txheight(coin,*txidp);
}
else
{
*txidp = jbits256(item,"tx_hash");
*voutp = juint(item,"tx_pos");
satoshis = j64bits(item,"value");
*heightp = jint(item,"height");
}
return(satoshis);
}
int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag,bits256 reftxid,bits256 reftxid2)
{
struct iguana_info *coin; struct LP_address *ap; int32_t n = 0; cJSON *retjson=0; char *retstr=0;
if ( symbol == 0 || symbol[0] == 0 )
return(0);
if ( (coin= LP_coinfind(symbol)) != 0 )
{
if ( coin->electrum != 0 )
{
if ( (retjson= electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,1)) != 0 )
if ( (retjson= electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,fullflag,reftxid,reftxid2)) != 0 )
{
n = cJSON_GetArraySize(retjson);
//printf("LP_listunspent_issue.%s %s.%d %s\n",symbol,coinaddr,n,jprint(retjson,0));
@ -633,29 +489,14 @@ int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag)
}
else
{
if ( strcmp(coin->smartaddr,coinaddr) == 0 )
{
retjson = LP_listunspent(symbol,coinaddr);
//printf("SELF_LISTUNSPENT.(%s %s)\n",symbol,coinaddr);
}
else if ( IAMLP == 0 )
{
printf("LP_listunspent_query.(%s %s)\n",symbol,coinaddr);
LP_listunspent_query(coin->symbol,coin->smartaddr);
if ( 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 ( fullflag == 2 && (ap= LP_addressfind(coin,coinaddr)) != 0 )
ap->unspenttime = 0;
retjson = LP_listunspent(symbol,coinaddr,reftxid,reftxid2);
coin->numutxos = cJSON_GetArraySize(retjson);
if ( retjson != 0 )
{
n = cJSON_GetArraySize(retjson);
if ( electrum_process_array(coin,0,coinaddr,retjson,1) != 0 )
if ( electrum_process_array(coin,0,coinaddr,retjson,1,reftxid,reftxid2) != 0 )
{
//LP_postutxos(symbol,coinaddr); // might be good to not saturate
}
@ -714,10 +555,10 @@ int32_t LP_importaddress(char *symbol,char *address)
if ( coin->electrum != 0 )
{
/*if ( (retjson= electrum_address_subscribe(symbol,coin->electrum,&retjson,address)) != 0 )
{
printf("importaddress.(%s) -> %s\n",address,jprint(retjson,0));
free_json(retjson);
}*/
{
printf("importaddress.(%s) -> %s\n",address,jprint(retjson,0));
free_json(retjson);
}*/
return(0);
}
else
@ -747,11 +588,21 @@ int32_t LP_importaddress(char *symbol,char *address)
double _LP_getestimatedrate(struct iguana_info *coin)
{
char buf[512],*retstr; cJSON *errjson; double rate = 0.00000020;
char buf[512],*retstr=0; int32_t numblocks; cJSON *errjson,*retjson; double rate = 0.00000020;
if ( coin->rate < 0. || time(NULL) > coin->ratetime+30 )
{
sprintf(buf,"[%d]",strcmp(coin->symbol,"BTC") == 0 ? 6 : 2);
if ( (retstr= LP_apicall(coin,coin->electrum==0?"estimatefee" : "blockchain.estimatefee",buf)) != 0 )
numblocks = strcmp(coin->symbol,"BTC") == 0 ? 6 : 2;
if ( coin->electrum == 0 )
{
sprintf(buf,"[%d]",numblocks);
retstr = LP_apicall(coin,"estimatefee",buf);
}
else
{
if ( (retjson= electrum_estimatefee(coin->symbol,coin->electrum,&retjson,numblocks)) != 0 )
retstr = jprint(retjson,1);
}
if ( retstr != 0 )
{
if ( retstr[0] == '{' && (errjson= cJSON_Parse(retstr)) != 0 )
{
@ -764,16 +615,16 @@ double _LP_getestimatedrate(struct iguana_info *coin)
rate = atof(retstr) / 1024.;
if ( rate < 0.00000020 )
rate = 0.00000020;
rate *= 1.1;
rate *= 1.5;
if ( coin->electrum != 0 )
rate *= 1.667;
rate *= 1.5;
if ( fabs(rate - coin->rate) > SMALLVAL )
printf("t%u estimated rate.(%s) (%s) -> %.8f %.8f\n",coin->ratetime,coin->symbol,retstr,rate,coin->rate);
coin->rate = rate;
coin->ratetime = (uint32_t)time(NULL);
}
free(retstr);
}
} else rate = coin->rate;
} else rate = coin->rate;
return(rate);
}
@ -808,7 +659,7 @@ char *LP_sendrawtransaction(char *symbol,char *signedtx)
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
@ -825,6 +676,7 @@ char *LP_sendrawtransaction(char *symbol,char *signedtx)
errobj = cJSON_CreateObject();
jaddstr(errobj,"error","rejected");
jaddnum(errobj,"code",-27);
free(retstr);
retstr = jprint(errobj,1);
}
else
@ -881,36 +733,38 @@ char *LP_signrawtx(char *symbol,bits256 *signedtxidp,int32_t *completedp,cJSON *
return(jprint(retjson,1));
}
return(signedtx);
array = cJSON_CreateArray();
jaddistr(array,rawtx);
jaddi(array,jduplicate(vins));
jaddi(array,jduplicate(privkeys));
paramstr = jprint(array,1);
//printf("signrawtransaction\n");
if ( (retstr= bitcoind_passthru(symbol,coin->serverport,coin->userpass,"signrawtransaction",paramstr)) != 0 )
if ( (0) )
{
if ( (json= cJSON_Parse(retstr)) != 0 )
array = cJSON_CreateArray();
jaddistr(array,rawtx);
jaddi(array,jduplicate(vins));
jaddi(array,jduplicate(privkeys));
paramstr = jprint(array,1);
//printf("signrawtransaction\n");
if ( (retstr= bitcoind_passthru(symbol,coin->serverport,coin->userpass,"signrawtransaction",paramstr)) != 0 )
{
if ( (hexstr= jstr(json,"hex")) != 0 )
if ( (json= cJSON_Parse(retstr)) != 0 )
{
len = (int32_t)strlen(hexstr);
signedtx = calloc(1,len+1);
strcpy(signedtx,hexstr);
*completedp = is_cJSON_True(jobj(json,"complete"));
len >>= 1;
data = malloc(len);
decode_hex(data,len,hexstr);
*signedtxidp = bits256_doublesha256(0,data,len);
if ( (hexstr= jstr(json,"hex")) != 0 )
{
len = (int32_t)strlen(hexstr);
signedtx = calloc(1,len+1);
strcpy(signedtx,hexstr);
*completedp = is_cJSON_True(jobj(json,"complete"));
len >>= 1;
data = malloc(len);
decode_hex(data,len,hexstr);
*signedtxidp = bits256_doublesha256(0,data,len);
}
//else
printf("%s signrawtransaction.(%s) params.(%s)\n",coin->symbol,retstr,paramstr);
free_json(json);
}
//else
printf("%s signrawtransaction.(%s) params.(%s)\n",coin->symbol,retstr,paramstr);
free_json(json);
free(retstr);
}
free(retstr);
free(paramstr);
return(signedtx);
}
free(paramstr);
return(signedtx);
}
cJSON *LP_getblock(char *symbol,bits256 txid)
@ -948,23 +802,25 @@ bits256 LP_getbestblockhash(struct iguana_info *coin)
decode_hex(blockhash.bytes,sizeof(blockhash),retstr);
free(retstr);
}
}
} else printf("electrum mode doesnt support block level scanning\n");
return(blockhash);
}
char *LP_blockhashstr(char *symbol,int32_t height)
{
cJSON *array; char *paramstr,*retstr; struct iguana_info *coin;
char params[64],*retstr; struct iguana_info *coin; //cJSON *array;
if ( symbol == 0 || symbol[0] == 0 )
return(0);
coin = LP_coinfind(symbol);
if ( coin == 0 || coin->electrum != 0 )
return(0);
array = cJSON_CreateArray();
jaddinum(array,height);
paramstr = jprint(array,1);
retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"getblockhash",paramstr);
free(paramstr);
//array = cJSON_CreateArray();
//jaddinum(array,height);
//paramstr = jprint(array,1);
sprintf(params,"[%d]",height);
retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"getblockhash",params);
//free(paramstr);
//printf("blockhashstr.(%s)\n",retstr);
return(retstr);
}
@ -980,6 +836,37 @@ cJSON *LP_getblockhashstr(char *symbol,char *blockhashstr)
return(bitcoin_json(coin,"getblock",buf));
}
uint32_t LP_heighttime(char *symbol,int32_t height)
{
struct electrum_info *ep; uint32_t timestamp = 0; cJSON *retjson; char *blockhashstr; struct iguana_info *coin = LP_coinfind(symbol);
if ( coin != 0 )
{
if ( (ep= coin->electrum) == 0 )
{
if ( (blockhashstr= LP_blockhashstr(symbol,height)) != 0 )
{
if ( (retjson= cJSON_Parse(blockhashstr)) != 0 )
{
//printf("height.(%s)\n",jprint(retjson,0));
timestamp = juint(retjson,"time");
free_json(retjson);
}
free(blockhashstr);
}
}
else
{
if ( (retjson= electrum_getheader(coin->symbol,ep,&retjson,height)) != 0 )
{
//printf("%s\n",jprint(retjson,0));
timestamp = juint(retjson,"timestamp");
free_json(retjson);
}
}
}
return(timestamp);
}
cJSON *LP_blockjson(int32_t *heightp,char *symbol,char *blockhashstr,int32_t height)
{
cJSON *json = 0; int32_t flag = 0; struct iguana_info *coin;
@ -1002,7 +889,7 @@ cJSON *LP_blockjson(int32_t *heightp,char *symbol,char *blockhashstr,int32_t hei
*heightp = juint(json,"height");
if ( height >= 0 && *heightp != height )
{
printf("unexpected height %d vs %d for %s (%s)\n",*heightp,height,blockhashstr,jprint(json,0));
//printf("unexpected height %d vs %d for %s (%s)\n",*heightp,height,blockhashstr,jprint(json,0));
*heightp = -1;
free_json(json);
json = 0;
@ -1083,10 +970,11 @@ const char *Notaries_elected[][2] =
{ "xxspot2_XX", "03d85b221ea72ebcd25373e7961f4983d12add66a92f899deaf07bab1d8b6f5573" }
};
int32_t LP_txhasnotarization(struct iguana_info *coin,bits256 txid)
int32_t LP_txhasnotarization(bits256 *notarizedhashp,struct iguana_info *coin,bits256 txid)
{
cJSON *txobj,*vins,*vin,*vouts,*vout,*spentobj,*sobj; char *hexstr; uint8_t script[35]; bits256 spenttxid; uint64_t notarymask; int32_t i,j,numnotaries,len,spentvout,numvins,numvouts,hasnotarization = 0;
if ( (txobj= LP_gettx(coin->symbol,txid)) != 0 )
cJSON *txobj,*vins,*vin,*vouts,*vout,*spentobj,*sobj; char *hexstr; uint8_t script[1024]; bits256 spenttxid; uint64_t notarymask; int32_t i,j,numnotaries,len,spentvout,numvins,numvouts,hasnotarization = 0;
memset(notarizedhashp,0,sizeof(*notarizedhashp));
if ( (txobj= LP_gettx(coin->symbol,txid,0)) != 0 )
{
if ( (vins= jarray(&numvins,txobj,"vin")) != 0 )
{
@ -1098,14 +986,14 @@ int32_t LP_txhasnotarization(struct iguana_info *coin,bits256 txid)
vin = jitem(vins,i);
spenttxid = jbits256(vin,"txid");
spentvout = jint(vin,"vout");
if ( (spentobj= LP_gettx(coin->symbol,spenttxid)) != 0 )
if ( (spentobj= LP_gettx(coin->symbol,spenttxid,0)) != 0 )
{
if ( (vouts= jarray(&numvouts,spentobj,"vout")) != 0 )
{
if ( spentvout < numvouts )
{
vout = jitem(vouts,spentvout);
if ( (sobj= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(sobj,"hex")) != 0 && (len= is_hexstr(hexstr,0)) == sizeof(script)*2 )
if ( (sobj= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(sobj,"hex")) != 0 && (len= is_hexstr(hexstr,0)) == 35*2 )
{
len >>= 1;
decode_hex(script,len,hexstr);
@ -1139,20 +1027,76 @@ int32_t LP_txhasnotarization(struct iguana_info *coin,bits256 txid)
}
}
}
if ( (vouts= jarray(&numvouts,txobj,"vout")) != 0 )
{
vout = jitem(vouts,1);
if ( (sobj= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(sobj,"hex")) != 0 && (len= is_hexstr(hexstr,0)) >= 35 )
{
len >>= 1;
decode_hex(script,len,hexstr);
iguana_rwbignum(0,&script[2],32,(uint8_t *)notarizedhashp);
}
}
free_json(txobj);
}
return(hasnotarization);
}
int32_t LP_notarization_validate(char *symbol,int32_t notarized,bits256 notarizedhash,bits256 notarizationtxid)
{
struct iguana_info *coin; int32_t valid = 0; cJSON *blockjson; bits256 notarizedhash2; char str[65],str2[65];
if ( strcmp(symbol,"KMD") == 0 )
coin = LP_coinfind("BTC");
else coin = LP_coinfind("KMD");
if ( coin != 0 )
{
if (LP_txhasnotarization(&notarizedhash2,coin,notarizationtxid) == 0 )
{
printf("missing %s notarization txid %s\n",symbol,bits256_str(str,notarizationtxid));
return(-1);
}
else if ( bits256_cmp(notarizedhash,notarizedhash2) != 0 )
{
printf("mismatched %s notarizedhash %s vs %s\n",symbol,bits256_str(str,notarizedhash),bits256_str(str2,notarizedhash2));
return(-1);
}
}
if ( (coin= LP_coinfind(symbol)) != 0 )
{
if ( coin->electrum == 0 )
{
if ( (blockjson= LP_getblock(coin->symbol,notarizedhash)) != 0 )
{
if ( jint(blockjson,"height") != notarized )
valid = 1;
free_json(blockjson);
}
}
else
{
if ( (blockjson= electrum_getheader(symbol,coin->electrum,&blockjson,notarized+1)) != 0 )
{
notarizedhash2 = jbits256(blockjson,"prev_block_hash");
if ( bits256_cmp(notarizedhash,notarizedhash2) == 0 )
valid = 1;
free_json(blockjson);
}
}
}
if ( valid == 1 )
return(0);
else return(-1);
}
int32_t LP_hasnotarization(struct iguana_info *coin,cJSON *blockjson)
{
int32_t i,n,hasnotarization = 0; bits256 txid; cJSON *txarray;
int32_t i,n,hasnotarization = 0; bits256 txid,notarizedhash; cJSON *txarray;
if ( (txarray= jarray(&n,blockjson,"tx")) != 0 )
{
for (i=0; i<n; i++)
{
txid = jbits256i(txarray,i);
hasnotarization += LP_txhasnotarization(coin,txid);
hasnotarization += LP_txhasnotarization(&notarizedhash,coin,txid);
}
}
return(hasnotarization);
@ -1183,7 +1127,7 @@ int32_t LP_notarization_latest(int32_t *bestheightp,struct iguana_info *coin)
blockhash = jbits256(blockjson,"previousblockhash");
if ( bits256_nonz(blockhash) == 0 )
{
printf("null prev.(%s)\n",jprint(blockjson,0));
//printf("null prev.(%s)\n",jprint(blockjson,0));
free_json(blockjson);
break;
}

21
iguana/exchanges/LP_scan.c

@ -26,6 +26,7 @@ int32_t LP_blockinit(struct iguana_info *coin,int32_t height)
{
if ( (txs= jarray(&numtx,blockobj,"tx")) != 0 )
{
//printf("LP_blockinit %s ht.%d numtx.%d\n",coin->symbol,height,numtx);
for (iter=0; iter<2; iter++)
{
txobj = 0;
@ -127,7 +128,7 @@ int sort_balance(void *a,void *b)
cJSON *LP_snapshot(struct iguana_info *coin,int32_t height)
{
static bits256 bannedarray[64]; static int32_t numbanned,indallvouts,maxsnapht; static char lastcoin[16];
static bits256 bannedarray[64]; static int32_t numbanned,indallvouts,maxsnapht; static char lastcoin[65];
struct LP_transaction *tx,*tmp; struct LP_address *ap,*atmp; int32_t isKMD,i,j,n,skipflag=0,startht,endht,ht; uint64_t banned_balance=0,balance=0,noaddr_balance=0; cJSON *retjson,*array,*item;
if ( bannedarray[0].txid == 0 )
numbanned = komodo_bannedset(&indallvouts,bannedarray,(int32_t)(sizeof(bannedarray)/sizeof(*bannedarray)));
@ -413,10 +414,11 @@ int32_t LP_spendsearch(char *coinaddr,bits256 *spendtxidp,int32_t *indp,char *sy
int32_t LP_mempoolscan(char *symbol,bits256 searchtxid)
{
int32_t i,n; cJSON *array,*txobj; bits256 txid; struct iguana_info *coin; struct LP_transaction *tx;
int32_t i,n; cJSON *array,*txobj; bits256 txid,zero; struct iguana_info *coin; struct LP_transaction *tx;
if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 || coin->electrum != 0 )
return(-1);
if ( (array= LP_getmempool(symbol,0)) != 0 )
memset(zero.bytes,0,sizeof(zero));
if ( (array= LP_getmempool(symbol,0,searchtxid,zero)) != 0 )
{
if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{
@ -444,7 +446,7 @@ int32_t LP_mempoolscan(char *symbol,bits256 searchtxid)
int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t duration)
{
struct iguana_info *coin; cJSON *array,*item; uint32_t expiration,i,n; int32_t numconfirms = -1;
struct iguana_info *coin; bits256 zero; cJSON *array,*item; uint32_t expiration,i,n; int32_t numconfirms = -1;
if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 )
{
printf("LP_waitmempool missing coin.%p or inactive\n",coin);
@ -464,9 +466,10 @@ int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int
}
else
{
if ( (array= electrum_address_getmempool(symbol,coin->electrum,&array,coinaddr)) != 0 )
memset(zero.bytes,0,sizeof(zero));
if ( (array= electrum_address_getmempool(symbol,coin->electrum,&array,coinaddr,txid,zero)) != 0 )
{
char str[65]; printf("check %s mempool.(%s)\n",bits256_str(str,txid),jprint(array,0));
//char str[65]; printf("check %s mempool.(%s)\n",bits256_str(str,txid),jprint(array,0));
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
@ -482,12 +485,12 @@ int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int
}
free(array);
}
LP_listunspent_issue(coin->symbol,coinaddr,1);
LP_listunspent_issue(coin->symbol,coinaddr,1,txid,zero);
struct LP_address_utxo *up;
if ( (up= LP_address_utxofind(coin,coinaddr,txid,vout)) != 0 )
{
char str[65]; printf("address_utxofind found confirmed %s %s %s ht.%d vs %d\n",symbol,coinaddr,bits256_str(str,txid),up->U.height,coin->height);
if ( coin->electrum != 0 && (array= electrum_address_gethistory(symbol,coin->electrum,&array,coinaddr)) != 0 )
if ( coin->electrum != 0 && (array= electrum_address_gethistory(symbol,coin->electrum,&array,coinaddr,txid)) != 0 )
free_json(array);
if ( coin->height >= up->U.height )
numconfirms = (coin->height - up->U.height + 1);
@ -512,7 +515,7 @@ int32_t LP_mempool_vinscan(bits256 *spendtxidp,int32_t *spendvinp,char *symbol,c
return(-1);
if ( time(NULL) > coin->lastmempool+LP_MEMPOOL_TIMEINCR )
{
if ( (array= LP_getmempool(symbol,coinaddr)) != 0 )
if ( (array= LP_getmempool(symbol,coinaddr,searchtxid,searchtxid2)) != 0 )
{
free_json(array);
coin->lastmempool = (uint32_t)time(NULL);

235
iguana/exchanges/LP_signatures.c

@ -35,7 +35,7 @@ struct basilisk_request *LP_requestinit(struct basilisk_request *rp,bits256 srch
rp->desthash = desthash;
rp->destamount = destsatoshis;
rp->quoteid = basilisk_quoteid(rp);
printf("r.%u %u, q.%u %u: %s %.8f -> %s %.8f\n",rp->timestamp,rp->requestid,rp->quotetime,rp->quoteid,rp->src,dstr(rp->srcamount),rp->dest,dstr(rp->destamount));
//printf("r.%u %u, q.%u %u: %s %.8f -> %s %.8f\n",rp->timestamp,rp->requestid,rp->quotetime,rp->quoteid,rp->src,dstr(rp->srcamount),rp->dest,dstr(rp->destamount));
return(rp);
}
@ -44,6 +44,7 @@ cJSON *LP_quotejson(struct LP_quoteinfo *qp)
double price; cJSON *retjson = cJSON_CreateObject();
jaddstr(retjson,"gui",qp->gui[0] != 0 ? qp->gui : LP_gui);
jadd64bits(retjson,"aliceid",qp->aliceid);
jaddnum(retjson,"tradeid",qp->tradeid);
jaddstr(retjson,"base",qp->srccoin);
jaddstr(retjson,"rel",qp->destcoin);
if ( qp->coinaddr[0] != 0 )
@ -103,12 +104,14 @@ cJSON *LP_quotejson(struct LP_quoteinfo *qp)
int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson)
{
uint32_t rid,qid;
memset(qp,0,sizeof(*qp));
safecopy(qp->gui,LP_gui,sizeof(qp->gui));
safecopy(qp->srccoin,jstr(argjson,"base"),sizeof(qp->srccoin));
safecopy(qp->coinaddr,jstr(argjson,"address"),sizeof(qp->coinaddr));
safecopy(qp->destcoin,jstr(argjson,"rel"),sizeof(qp->destcoin));
safecopy(qp->destaddr,jstr(argjson,"destaddr"),sizeof(qp->destaddr));
qp->aliceid = j64bits(argjson,"aliceid");
qp->tradeid = juint(argjson,"tradeid");
qp->timestamp = juint(argjson,"timestamp");
qp->quotetime = juint(argjson,"quotetime");
qp->txid = jbits256(argjson,"txid");
@ -129,14 +132,16 @@ int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson)
qp->R.quoteid = juint(argjson,"quoteid");
if ( qp->R.requestid == 0 )
{
rid= basilisk_requestid(&qp->R);
//printf("requestid.%u -> %u\n",qp->R.requestid,rid);
rid = basilisk_requestid(&qp->R);
if ( qp->R.requestid != 0 && qp->R.requestid != rid )
printf("requestid.%u -> %u\n",qp->R.requestid,rid);
qp->R.requestid = rid;
}
if ( qp->R.quoteid == 0 )
{
qid= basilisk_quoteid(&qp->R);
//printf("quoteid.%u -> %u\n",qp->R.quoteid,qid);
qid = basilisk_quoteid(&qp->R);
if ( qp->R.quoteid != 0 && qp->R.quoteid != qid )
printf("quoteid.%u -> %u\n",qp->R.quoteid,qid);
qp->R.quoteid = qid;
}
return(0);
@ -146,7 +151,7 @@ void LP_txfees(uint64_t *txfeep,uint64_t *desttxfeep,char *base,char *rel)
{
*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));
//printf("LP_txfees(%.8f %.8f)\n",dstr(*txfeep),dstr(*desttxfeep));
}
int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char *destcoin,double price,uint64_t satoshis,uint64_t destsatoshis)
@ -189,15 +194,15 @@ int32_t LP_quotedestinfo(struct LP_quoteinfo *qp,bits256 desttxid,int32_t destvo
return(0);
}
char *LP_quotereceived(cJSON *argjson)
char *LP_quotereceived(struct LP_quoteinfo *qp)
{
struct LP_cacheinfo *ptr; double price; struct LP_quoteinfo Q;
LP_quoteparse(&Q,argjson);
price = (double)Q.destsatoshis / (Q.satoshis - Q.txfee);
if ( (ptr= LP_cacheadd(Q.srccoin,Q.destcoin,Q.txid,Q.vout,price,&Q)) != 0 )
struct LP_cacheinfo *ptr; double price;
//LP_quoteparse(&Q,argjson);
price = (double)qp->destsatoshis / (qp->satoshis - qp->txfee);
if ( (ptr= LP_cacheadd(qp->srccoin,qp->destcoin,qp->txid,qp->vout,price,qp)) != 0 )
{
ptr->Q = Q;
printf(">>>>>>>>>> received quote %s/%s %.8f\n",Q.srccoin,Q.destcoin,price);
ptr->Q = *qp;
printf(">>>>>>>>>> received quote %s/%s %.8f\n",qp->srccoin,qp->destcoin,price);
return(clonestr("{\"result\":\"updated\"}"));
} else return(clonestr("{\"error\":\"nullptr\"}"));
}
@ -271,7 +276,7 @@ bits256 LP_utxos_sighash(uint32_t timestamp,uint8_t *pubsecp,bits256 pubkey,bits
int32_t LP_utxos_sigcheck(uint32_t timestamp,char *sigstr,char *pubsecpstr,bits256 pubkey,bits256 utxoshash)
{
static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash; char str[65]; struct LP_pubkeyinfo *pubp;
static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash; char str[65]; struct LP_pubkey_info *pubp;
if ( ctx == 0 )
ctx = bitcoin_ctx();
pubp = LP_pubkeyfind(pubkey);
@ -284,11 +289,12 @@ int32_t LP_utxos_sigcheck(uint32_t timestamp,char *sigstr,char *pubsecpstr,bits2
if ( memcmp(pub33,pubsecp,33) != 0 || retval != 0 )
{
static uint32_t counter;
if ( counter++ < 10 )
if ( counter++ <= LP_MAXPUBKEY_ERRORS )
{
if ( pubp != 0 )
pubp->numerrors++;
printf("LP_utxos_sigcheck failure.%d, probably from %s with older version\n",pubp!=0?pubp->numerrors:-1,bits256_str(str,pubkey));
if ( pubp != 0 && pubp->numerrors > LP_MAXPUBKEY_ERRORS/2 )
printf("LP_utxos_sigcheck failure.%d, probably from %s with older version\n",pubp!=0?pubp->numerrors:-1,bits256_str(str,pubkey));
}
retval = -1;
} else retval = 0;
@ -324,6 +330,7 @@ int32_t LP_utxos_sigadd(cJSON *item,uint32_t timestamp,bits256 priv,uint8_t *pub
void LP_postutxos(char *symbol,char *coinaddr)
{
bits256 zero; uint32_t timestamp; bits256 utxoshash; char pubsecpstr[67]; struct iguana_info *coin; cJSON *array,*reqjson = cJSON_CreateObject();
return;
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);
@ -345,70 +352,14 @@ void LP_postutxos(char *symbol,char *coinaddr)
//char str[65]; printf("utxoshash add %s\n",bits256_str(str,utxoshash));
LP_utxos_sigadd(reqjson,timestamp,G.LP_privkey,G.LP_pubsecp,G.LP_mypub25519,utxoshash);
//printf("post (%s) -> %d\n",msg,LP_mypubsock);
LP_reserved_msg(symbol,symbol,zero,jprint(reqjson,1));
}
}
}
queue_t utxosQ;
struct LP_utxos_qitem { struct queueitem DL; cJSON *argjson; };
char *LP_postutxos_recv(cJSON *argjson)
{
struct LP_utxos_qitem *uitem; struct iguana_info *coin; char *coinaddr,*symbol; bits256 utxoshash,pubkey; cJSON *obj; struct LP_pubkeyinfo *pubp;
pubkey = jbits256(argjson,"pubkey");
pubp = LP_pubkeyfind(pubkey);
if ( pubp != 0 && pubp->numerrors > LP_MAXPUBKEY_ERRORS )
return(clonestr("{\"error\":\"blacklisted\"}"));
if ( (coinaddr= jstr(argjson,"coinaddr")) != 0 && (symbol= jstr(argjson,"coin")) != 0 && (coin= LP_coinfind(symbol)) != 0 )
{
if ( strcmp(coinaddr,coin->smartaddr) == 0 )
{
//printf("ignore my utxo from external source %s %s\n",symbol,coinaddr);
return(clonestr("{\"result\":\"success\"}"));
}
}
if ( (obj= jobj(argjson,"utxos")) != 0 )
{
utxoshash = LP_utxoshash_calc(obj);
//char str[65]; printf("got utxoshash %s\n",bits256_str(str,utxoshash));
if ( LP_utxos_sigcheck(juint(argjson,"timestamp"),jstr(argjson,"sig"),jstr(argjson,"pubsecp"),pubkey,utxoshash) == 0 )
{
uitem = calloc(1,sizeof(*uitem));
uitem->argjson = jduplicate(argjson);
queue_enqueue("utxosQ",&utxosQ,&uitem->DL);
return(clonestr("{\"result\":\"success\"}"));
LP_reserved_msg(0,symbol,symbol,zero,jprint(reqjson,1));
}
}
return(clonestr("{\"error\":\"sig failure\"}"));
}
int32_t LP_utxosQ_process()
{
struct LP_utxos_qitem *uitem; int32_t n; char *symbol,*coinaddr; struct LP_address *ap; struct iguana_info *coin; cJSON *array;
if ( (uitem= queue_dequeue(&utxosQ)) != 0 )
{
//printf("LP_utxosQ_process.(%s)\n",jprint(uitem->argjson,0));
if ( (coinaddr= jstr(uitem->argjson,"coinaddr")) != 0 && (symbol= jstr(uitem->argjson,"coin")) != 0 && (coin= LP_coinfind(symbol)) != 0 ) // addsig
{
if ( coin->electrum == 0 || (ap= LP_addressfind(coin,coinaddr)) != 0 )
{
if ( (array= jarray(&n,uitem->argjson,"utxos")) != 0 )
LP_unspents_array(coin,coinaddr,array);
}
else if ( (array= electrum_address_listunspent(symbol,coin->electrum,&array,coinaddr,1)) != 0 )
free_json(array);
}
free_json(uitem->argjson);
free(uitem);
return(1);
}
return(0);
}
int32_t LP_price_sigcheck(uint32_t timestamp,char *sigstr,char *pubsecpstr,bits256 pubkey,char *base,char *rel,uint64_t price64)
{
static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash; struct LP_pubkeyinfo *pubp;
static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash; struct LP_pubkey_info *pubp;
if ( ctx == 0 )
ctx = bitcoin_ctx();
pubp = LP_pubkeyfind(pubkey);
@ -443,9 +394,10 @@ int32_t LP_price_sigadd(cJSON *item,uint32_t timestamp,bits256 priv,uint8_t *pub
char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *rel,double price)
{
struct iguana_info *basecoin,*relcoin; char pubsecpstr[67]; uint32_t timestamp; uint64_t price64; bits256 zero; cJSON *reqjson = cJSON_CreateObject();
struct iguana_info *basecoin,*relcoin,*kmd; struct LP_address *ap; char pubsecpstr[67]; uint32_t numutxos,timestamp; uint64_t price64,balance,minsize,maxsize; bits256 zero; cJSON *reqjson;
reqjson = cJSON_CreateObject();
// LP_addsig
if ( (basecoin= LP_coinfind(base)) != 0 && (relcoin= LP_coinfind(rel)) != 0 && basecoin->electrum == 0 && relcoin->electrum == 0 )
if ( (basecoin= LP_coinfind(base)) != 0 && (relcoin= LP_coinfind(rel)) != 0 )//&& basecoin->electrum == 0 )//&& relcoin->electrum == 0 )
{
memset(zero.bytes,0,sizeof(zero));
jaddbits256(reqjson,"pubkey",G.LP_mypub25519);
@ -459,8 +411,19 @@ char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *re
jaddnum(reqjson,"timestamp",timestamp);
init_hexbytes_noT(pubsecpstr,G.LP_pubsecp,33);
jaddstr(reqjson,"pubsecp",pubsecpstr);
if ( (kmd= LP_coinfind("KMD")) != 0 && (ap= LP_address(kmd,kmd->smartaddr)) != 0 && ap->instantdex_credits != 0 )
jaddnum(reqjson,"credits",dstr(ap->instantdex_credits));
if ( (numutxos= LP_address_minmax(&balance,&minsize,&maxsize,basecoin,basecoin->smartaddr)) != 0 )
{
//printf("send %s numutxos.%d balance %.8f min %.8f max %.8f\n",base,numutxos,dstr(balance),dstr(minsize),dstr(maxsize));
jaddstr(reqjson,"utxocoin",base);
jaddnum(reqjson,"n",numutxos);
jaddnum(reqjson,"bal",dstr(balance));
jaddnum(reqjson,"min",dstr(minsize));
jaddnum(reqjson,"max",dstr(maxsize));
}
LP_price_sigadd(reqjson,timestamp,G.LP_privkey,G.LP_pubsecp,G.LP_mypub25519,base,rel,price64);
LP_reserved_msg(base,rel,zero,jprint(reqjson,1));
LP_reserved_msg(0,base,rel,zero,jprint(reqjson,1));
return(clonestr("{\"result\":\"success\"}"));
} else return(clonestr("{\"error\":\"electrum node cant post bob asks\"}"));
}
@ -476,9 +439,15 @@ char *LP_postprice_recv(cJSON *argjson)
{
if ( LP_price_sigcheck(juint(argjson,"timestamp"),jstr(argjson,"sig"),jstr(argjson,"pubsecp"),pubkey,base,rel,j64bits(argjson,"price64")) == 0 )
{
LP_pricefeedupdate(pubkey,base,rel,price);
//printf("call pricefeed update\n");
LP_pricefeedupdate(pubkey,base,rel,price,jstr(argjson,"utxocoin"),jint(argjson,"n"),jdouble(argjson,"bal")*SATOSHIDEN,jdouble(argjson,"min")*SATOSHIDEN,jdouble(argjson,"max")*SATOSHIDEN,jdouble(argjson,"credits")*SATOSHIDEN);
return(clonestr("{\"result\":\"success\"}"));
} else return(clonestr("{\"error\":\"sig failure\"}"));
}
else
{
printf("sig failure\n");
return(clonestr("{\"error\":\"sig failure\"}"));
}
}
}
return(clonestr("{\"error\":\"missing fields in posted price\"}"));
@ -500,7 +469,7 @@ int32_t LP_pubkey_sigadd(cJSON *item,uint32_t timestamp,bits256 priv,bits256 pub
return(LP_bitcoinsig_add(item,priv,pubsecp,sighash));
}
int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *pubp,cJSON *item)
int32_t LP_pubkey_sigcheck(struct LP_pubkey_info *pubp,cJSON *item)
{
int32_t i,len,siglen,retval=-1; uint8_t rmd160[20],checkrmd160[20],pubsecp[33],sig[65],zeroes[20]; char *sigstr,*hexstr,*pubsecpstr;
if ( (hexstr= jstr(item,"rmd160")) != 0 && strlen(hexstr) == 2*sizeof(rmd160) )
@ -525,20 +494,20 @@ int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *pubp,cJSON *item)
{
if ( memcmp(rmd160,pubp->rmd160,20) != 0 )
{
for (i=0; i<20; i++)
printf("%02x",pubp->rmd160[i]);
//for (i=0; i<20; i++)
// printf("%02x",pubp->rmd160[i]);
memcpy(pubp->rmd160,rmd160,sizeof(pubp->rmd160));
memcpy(pubp->pubsecp,pubsecp,sizeof(pubp->pubsecp));
memcpy(pubp->sig,sig,sizeof(pubp->sig));
pubp->siglen = siglen;
char str[65]; printf(" -> rmd160.(%s) for %s (%s) sig.%s\n",hexstr,bits256_str(str,pubp->pubkey),pubsecpstr,sigstr);
pubp->timestamp = (uint32_t)time(NULL);
//char str[65]; printf(" -> rmd160.(%s) for %s (%s) sig.%s\n",hexstr,bits256_str(str,pubp->pubkey),pubsecpstr,sigstr);
}
pubp->timestamp = juint(item,"timestamp");
retval = 0;
} else pubp->numerrors++;
}
}
else
else if ( 0 )
{
for (i=0; i<20; i++)
printf("%02x",rmd160[i]);
@ -548,7 +517,7 @@ int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *pubp,cJSON *item)
printf(" for %s\n",pubsecpstr);
}
}
}// else pubp->timestamp = (uint32_t)time(NULL);
}
}
}
return(retval);
@ -556,7 +525,7 @@ int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *pubp,cJSON *item)
void LP_notify_pubkeys(void *ctx,int32_t pubsock)
{
bits256 zero; uint32_t timestamp; char secpstr[67]; cJSON *reqjson = cJSON_CreateObject();
bits256 zero; uint32_t timestamp; char LPipaddr[64],secpstr[67]; cJSON *reqjson = cJSON_CreateObject();
memset(zero.bytes,0,sizeof(zero));
jaddstr(reqjson,"method","notify");
jaddstr(reqjson,"rmd160",G.LP_myrmd160str);
@ -566,17 +535,42 @@ void LP_notify_pubkeys(void *ctx,int32_t pubsock)
timestamp = (uint32_t)time(NULL);
jaddnum(reqjson,"timestamp",timestamp);
LP_pubkey_sigadd(reqjson,timestamp,G.LP_privkey,G.LP_mypub25519,G.LP_myrmd160,G.LP_pubsecp);
LP_reserved_msg("","",zero,jprint(reqjson,1));
if ( IAMLP != 0 )
{
if ( LP_rarestpeer(LPipaddr) != 0 )
{
jaddstr(reqjson,"isLP",LPipaddr);
if ( strcmp(LPipaddr,LP_myipaddr) == 0 )
jaddnum(reqjson,"ismine",1);
}
else printf("no LPipaddr\n");
}
jaddnum(reqjson,"session",G.LP_sessionid);
LP_reserved_msg(0,"","",zero,jprint(reqjson,1));
}
char *LP_notify_recv(cJSON *argjson)
{
bits256 pub; struct LP_pubkeyinfo *pubp;
bits256 pub; struct LP_pubkey_info *pubp; char *ipaddr;
pub = jbits256(argjson,"pub");
if ( bits256_nonz(pub) != 0 )
{
if ( (pubp= LP_pubkeyadd(pub)) != 0 )
LP_pubkey_sigcheck(pubp,argjson);
if ( (ipaddr= jstr(argjson,"isLP")) != 0 )
{
//printf("notify got isLP %s %d\n",ipaddr,jint(argjson,"ismine"));
LP_peer_recv(ipaddr,jint(argjson,"ismine"));
if ( IAMLP != 0 && G.LP_IAMLP == 0 && strcmp(ipaddr,LP_myipaddr) == 0 )
{
if ( bits256_cmp(pub,G.LP_mypub25519) != 0 )
{
char str[65]; printf("that's me! and it is from %s which isnt me\n",bits256_str(str,pub));
G.LP_IAMLP = 1;
}
}
LP_addpeer(LP_mypeer,LP_mypubsock,ipaddr,RPC_port,RPC_port+10,RPC_port+20,1,juint(argjson,"session"));
}
//char str[65]; printf("%.3f NOTIFIED pub %s rmd160 %s\n",OS_milliseconds()-millis,bits256_str(str,pub),rmd160str);
}
return(clonestr("{\"result\":\"success\",\"notify\":\"received\"}"));
@ -584,7 +578,8 @@ char *LP_notify_recv(cJSON *argjson)
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;
uint64_t value; bits256 zero,txid; int32_t i,vout,height,n; cJSON *array,*item,*req;
return;
if ( coin->smartaddr[0] == 0 )
return;
//LP_notify_pubkeys(coin->ctx,LP_mypubsock);
@ -601,14 +596,6 @@ void LP_smartutxos_push(struct iguana_info *coin)
vout = jint(item,"tx_pos");
value = j64bits(item,"value");
height = jint(item,"height");
if ( 0 && (rand() % 100) == 0 && IAMLP == 0 )
{
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);
@ -618,7 +605,7 @@ void LP_smartutxos_push(struct iguana_info *coin)
jaddnum(req,"ht",height);
jadd64bits(req,"value",value);
//printf("ADDR_UNSPENTS[] <- %s\n",jprint(req,0));
LP_reserved_msg("","",zero,jprint(req,1));
LP_reserved_msg(0,"","",zero,jprint(req,1));
}
}
free_json(array);
@ -628,6 +615,7 @@ void LP_smartutxos_push(struct iguana_info *coin)
char *LP_uitem_recv(cJSON *argjson)
{
bits256 txid; int32_t vout,height; uint64_t value; struct iguana_info *coin; char *coinaddr,*symbol;
printf("LP_uitem_recv deprecated\n");
txid = jbits256(argjson,"txid");
vout = jint(argjson,"vout");
height = jint(argjson,"ht");
@ -637,7 +625,7 @@ char *LP_uitem_recv(cJSON *argjson)
{
//char str[65]; printf("uitem %s %s %s/v%d %.8f ht.%d\n",symbol,coinaddr,bits256_str(str,txid),vout,dstr(value),height);
if ( strcmp(coin->smartaddr,coinaddr) != 0 )
LP_address_utxoadd("LP_uitem_recv",coin,coinaddr,txid,vout,value,height,-1);
LP_address_utxoadd((uint32_t)time(NULL),"LP_uitem_recv",coin,coinaddr,txid,vout,value,height,-1);
//else printf("ignore external uitem %s %s\n",symbol,coin->smartaddr);
}
return(clonestr("{\"result\":\"success\"}"));
@ -650,16 +638,19 @@ void LP_listunspent_query(char *symbol,char *coinaddr)
jaddstr(reqjson,"method","addr_unspents");
jaddstr(reqjson,"coin",symbol);
jaddstr(reqjson,"address",coinaddr);
LP_reserved_msg("","",zero,jprint(reqjson,1));
LP_reserved_msg(0,"","",zero,jprint(reqjson,1));
}
void LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct LP_quoteinfo *qp)
{
cJSON *reqjson; bits256 zero; char *msg,*msg2; int32_t flag = 0; struct LP_utxoinfo *utxo;
cJSON *reqjson; bits256 zero; char *msg; struct iguana_info *coin; int32_t flag = 0;
if ( strcmp(method,"request") == 0 )
{
if ( (utxo= LP_utxofind(0,qp->desttxid,qp->destvout)) != 0 && LP_ismine(utxo) > 0 && LP_isavailable(utxo) > 0 )
LP_unavailableset(utxo,qp->srchash);
if ( LP_allocated(qp->desttxid,qp->destvout) == 0 && LP_allocated(qp->feetxid,qp->feevout) == 0 )
{
LP_unavailableset(qp->desttxid,qp->destvout,qp->timestamp+LP_AUTOTRADE_TIMEOUT*4,qp->srchash);
LP_unavailableset(qp->feetxid,qp->feevout,qp->timestamp+LP_AUTOTRADE_TIMEOUT*4,qp->srchash);
}
else
{
printf("couldnt find my txid to make request\n");
@ -671,19 +662,33 @@ void LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct LP_
flag = 1;
jaddbits256(reqjson,"pubkey",qp->srchash);
jaddstr(reqjson,"method",method);
jaddnum(reqjson,"timestamp",time(NULL));
if ( jobj(reqjson,"timestamp") == 0 )
jaddnum(reqjson,"timestamp",time(NULL));
if ( strcmp(method,"connect") == 0 )
{
if ( (coin= LP_coinfind("KMD")) != 0 )
jadd(reqjson,"proof",LP_instantdex_txids(0,coin->smartaddr));
}
msg = jprint(reqjson,1);
msg2 = clonestr(msg);
// LP_addsig
printf("QUERY.(%s)\n",msg);
memset(&zero,0,sizeof(zero));
portable_mutex_lock(&LP_reservedmutex);
if ( num_Reserved_msgs < sizeof(Reserved_msgs)/sizeof(*Reserved_msgs)-2 )
//if ( bits256_nonz(qp->srchash) == 0 || strcmp(method,"request") != 0 )
{
Reserved_msgs[num_Reserved_msgs++] = msg;
//Reserved_msgs[num_Reserved_msgs++] = msg2;
}
LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,zero,msg2);
portable_mutex_unlock(&LP_reservedmutex);
memset(&zero,0,sizeof(zero));
LP_reserved_msg(1,qp->srccoin,qp->destcoin,zero,clonestr(msg));
if ( strcmp(method,"request") == 0 )
{
sleep(1);
LP_reserved_msg(1,qp->srccoin,qp->destcoin,zero,clonestr(msg));
sleep(1);
LP_reserved_msg(1,qp->srccoin,qp->destcoin,zero,clonestr(msg));
}
free(msg);
/*portable_mutex_lock(&LP_reservedmutex);
if ( num_Reserved_msgs[1] < sizeof(Reserved_msgs[1])/sizeof(*Reserved_msgs[1])-2 )
Reserved_msgs[1][num_Reserved_msgs[1]++] = msg;
if ( num_Reserved_msgs[0] < sizeof(Reserved_msgs[0])/sizeof(*Reserved_msgs[0])-2 )
Reserved_msgs[0][num_Reserved_msgs[0]++] = msg2;
portable_mutex_unlock(&LP_reservedmutex);*/
} //else LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,qp->srchash,msg);
}

400
iguana/exchanges/LP_socket.c

@ -98,7 +98,7 @@ int32_t LP_socket(int32_t bindflag,char *hostname,uint16_t port)
#endif
expand_ipbits(checkipaddr,saddr.sin_addr.s_addr);
if ( strcmp(ipaddr,checkipaddr) != 0 )
printf("bindflag.%d iguana_socket mismatch (%s) -> (%s)?\n",bindflag,checkipaddr,ipaddr);
printf("bindflag.%d iguana_socket mismatch (%s) -> (%s)\n",bindflag,checkipaddr,ipaddr);
//#endif
if ( (sock= socket(AF_INET,SOCK_STREAM,0)) < 0 )
{
@ -124,9 +124,9 @@ int32_t LP_socket(int32_t bindflag,char *hostname,uint16_t port)
#endif
if ( bindflag == 0 )
{
printf("call connect sock.%d\n",sock);
//printf("call connect sock.%d\n",sock);
result = connect(sock,(struct sockaddr *)&saddr,addrlen);
printf("called connect result.%d\n",result);
//printf("called connect result.%d\n",result);
timeout.tv_sec = 2;
timeout.tv_usec = 0;
setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(void *)&timeout,sizeof(timeout));
@ -238,18 +238,7 @@ int32_t LP_socketrecv(int32_t sock,uint8_t *recvbuf,int32_t maxlen)
return(recvlen);
}
struct electrum_info
{
queue_t sendQ,pendingQ;
portable_mutex_t mutex,txmutex;
struct electrum_info *prev;
int32_t bufsize,sock,*heightp,numerrors;
struct iguana_info *coin;
uint32_t stratumid,lasttime,pending,*heighttimep;
char ipaddr[64],symbol[16];
uint16_t port;
uint8_t buf[];
} *Electrums[8192];
struct electrum_info *Electrums[8192];
int32_t Num_electrums;
struct electrum_info *electrum_server(char *symbol,struct electrum_info *ep)
@ -283,7 +272,7 @@ struct electrum_info *electrum_server(char *symbol,struct electrum_info *ep)
ep = recent_ep;
if ( n > 0 )
{
i = (rand() % n);
i = (LP_rand() % n);
ep = rbuf[i];
}
}
@ -294,7 +283,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 electrumflag)
int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep,char *coinaddr,cJSON *array,int32_t electrumflag,bits256 reftxid,bits256 reftxid2)
{
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 )
@ -314,7 +303,7 @@ int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep
else
{
//printf("external unspent has no gettxout\n");
flag += LP_address_utxoadd("electrum process",coin,coinaddr,txid,v,value,0,1);
flag += LP_address_utxoadd((uint32_t)time(NULL),"electrum process",coin,coinaddr,txid,v,value,0,1);
}
}
else
@ -328,17 +317,25 @@ int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep
continue;
if ( (tx= LP_transactionfind(coin,txid)) == 0 )
{
txobj = LP_transactioninit(coin,txid,0,0);
LP_transactioninit(coin,txid,1,txobj);
free_json(txobj);
tx = LP_transactionfind(coin,txid);
if ( (bits256_nonz(reftxid) == 0 || bits256_cmp(reftxid,txid) == 0) && (bits256_nonz(reftxid2) == 0 || bits256_cmp(reftxid2,txid) == 0) )
{
txobj = LP_transactioninit(coin,txid,0,0);
LP_transactioninit(coin,txid,1,txobj);
free_json(txobj);
tx = LP_transactionfind(coin,txid);
}
}
if ( tx != 0 )
{
if (tx->height <= 0 )
{
tx->height = ht;
//printf("%s %s >>>>>>>>>> set %s <- height %d\n",coin->symbol,coinaddr,bits256_str(str,txid),tx->height);
if ( ep != 0 && coin != 0 && tx->SPV == 0 )
{
if ( 0 && strcmp(coinaddr,coin->smartaddr) == 0 )
tx->SPV = LP_merkleproof(coin,coin->smartaddr,ep,txid,tx->height);
//printf("%s %s >>>>>>>>>> set %s <- height %d\n",coin->symbol,coinaddr,bits256_str(str,txid),tx->height);
}
}
if ( v >= 0 && v < tx->numvouts )
{
@ -351,7 +348,7 @@ int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep
if ( tx->height > 0 )
{
//printf("from electrum_process_array\n");
flag += LP_address_utxoadd("electrum process2",coin,coinaddr,txid,v,value,tx->height,-1);
flag += LP_address_utxoadd((uint32_t)time(NULL),"electrum process2",coin,coinaddr,txid,v,value,tx->height,-1);
}
//printf("v.%d numvouts.%d %.8f (%s)\n",v,tx->numvouts,dstr(tx->outpoints[jint(item,"tx_pos")].value),jprint(item,0));
} //else printf("cant find tx\n");
@ -360,6 +357,55 @@ int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep
return(flag);
}
cJSON *electrum_version(char *symbol,struct electrum_info *ep,cJSON **retjsonp);
cJSON *electrum_headers_subscribe(char *symbol,struct electrum_info *ep,cJSON **retjsonp);
struct stritem *electrum_sitem(struct electrum_info *ep,char *stratumreq,int32_t timeout,cJSON **retjsonp)
{
struct stritem *sitem = (struct stritem *)queueitem(stratumreq);
sitem->expiration = timeout;
sitem->DL.type = ep->stratumid++;
sitem->retptrp = (void **)retjsonp;
queue_enqueue("sendQ",&ep->sendQ,&sitem->DL);
return(sitem);
}
void electrum_initial_requests(struct electrum_info *ep)
{
cJSON *retjson; char stratumreq[1024];
retjson = 0;
sprintf(stratumreq,"{ \"jsonrpc\":\"2.0\", \"id\": %u, \"method\":\"%s\", \"params\": %s }\n",ep->stratumid,"blockchain.headers.subscribe","[]");
electrum_sitem(ep,stratumreq,3,&retjson);
retjson = 0;
sprintf(stratumreq,"{ \"jsonrpc\":\"2.0\", \"id\": %u, \"method\":\"%s\", \"params\": %s }\n",ep->stratumid,"server.version","[\"barterDEX\", [\"1.1\", \"1.1\"]]");
electrum_sitem(ep,stratumreq,3,&retjson);
retjson = 0;
sprintf(stratumreq,"{ \"jsonrpc\":\"2.0\", \"id\": %u, \"method\":\"%s\", \"params\": %s }\n",ep->stratumid,"blockchain.estimatefee","[2]");
electrum_sitem(ep,stratumreq,3,&retjson);
}
int32_t electrum_kickstart(struct electrum_info *ep)
{
closesocket(ep->sock);//, ep->sock = -1;
if ( (ep->sock= LP_socket(0,ep->ipaddr,ep->port)) < 0 )
{
printf("error RE-connecting to %s:%u\n",ep->ipaddr,ep->port);
return(-1);
}
else
{
ep->stratumid = 0;
electrum_initial_requests(ep);
printf("RECONNECT ep.%p %s numerrors.%d too big -> new %s:%u sock.%d\n",ep,ep->symbol,ep->numerrors,ep->ipaddr,ep->port,ep->sock);
ep->numerrors = 0;
}
return(0);
}
int32_t zeroval();
cJSON *electrum_submit(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *method,char *params,int32_t timeout)
{
// queue id and string and callback
@ -368,37 +414,28 @@ cJSON *electrum_submit(char *symbol,struct electrum_info *ep,cJSON **retjsonp,ch
ep = electrum_server(symbol,0);
while ( ep != 0 )
{
if ( strcmp(ep->symbol,symbol) != 0 )
{
printf("electrum_submit ep.%p %s %s:%u called for [%s]???\n",ep,ep->symbol,ep->ipaddr,ep->port,symbol);
}
if ( ep != 0 && ep->sock >= 0 && retjsonp != 0 )
{
*retjsonp = 0;
sprintf(stratumreq,"{ \"jsonrpc\":\"2.0\", \"id\": %u, \"method\":\"%s\", \"params\": %s }\n",ep->stratumid,method,params);
//printf("%s %s",symbol,stratumreq);
memset(ep->buf,0,ep->bufsize);
sitem = (struct stritem *)queueitem(stratumreq);
sitem->expiration = timeout;
sitem->DL.type = ep->stratumid++;
sitem->retptrp = (void **)retjsonp;
portable_mutex_lock(&ep->mutex);
queue_enqueue("sendQ",&ep->sendQ,&sitem->DL);
sitem = electrum_sitem(ep,stratumreq,timeout,retjsonp);
portable_mutex_lock(&ep->mutex); // this helps performance!
expiration = (uint32_t)time(NULL) + timeout + 1;
while ( *retjsonp == 0 && time(NULL) <= expiration )
usleep(5000);
usleep(15000);
portable_mutex_unlock(&ep->mutex);
if ( *retjsonp == 0 || jobj(*retjsonp,"error") != 0 )
{
if ( ++ep->numerrors >= LP_ELECTRUM_MAXERRORS )
{
closesocket(ep->sock), ep->sock = -1;
if ( (ep->sock= LP_socket(0,ep->ipaddr,ep->port)) < 0 )
printf("error RE-connecting to %s:%u\n",ep->ipaddr,ep->port);
else
{
printf("ep.%p %s numerrors.%d too big -> new %s:%u sock.%d\n",ep,ep->symbol,ep->numerrors,ep->ipaddr,ep->port,ep->sock);
ep->numerrors = 0;
}
}
electrum_kickstart(ep);
} else if ( ep->numerrors > 0 )
ep->numerrors++;
ep->numerrors--;
if ( ep->prev == 0 )
{
if ( *retjsonp == 0 )
@ -408,10 +445,10 @@ cJSON *electrum_submit(char *symbol,struct electrum_info *ep,cJSON **retjsonp,ch
}
return(*retjsonp);
}
} else printf("couldnt find electrum server for (%s %s) or no retjsonp.%p\n",method,params,retjsonp);
} //else printf("couldnt find electrum server for (%s %s) or no retjsonp.%p\n",method,params,retjsonp);
ep = ep->prev;
if ( ep != 0 )
printf("using prev ep.%s\n",ep->symbol);
//if ( ep != 0 )
// printf("using prev ep.%s\n",ep->symbol);
}
return(0);
}
@ -454,7 +491,16 @@ cJSON *electrum_hasharg(char *symbol,struct electrum_info *ep,cJSON **retjsonp,c
return(electrum_submit(symbol,ep,retjsonp,method,params,timeout));
}
cJSON *electrum_version(char *symbol,struct electrum_info *ep,cJSON **retjsonp) { return(electrum_noargs(symbol,ep,retjsonp,"server.version",ELECTRUM_TIMEOUT)); }
cJSON *electrum_version(char *symbol,struct electrum_info *ep,cJSON **retjsonp)
{
char params[128]; cJSON *retjson;
if ( retjsonp == 0 )
retjsonp = &retjson;
sprintf(params,"[\"barterDEX\", [\"1.1\", \"1.1\"]]");
return(electrum_submit(symbol,ep,retjsonp,"server.version",params,ELECTRUM_TIMEOUT));
}
cJSON *electrum_banner(char *symbol,struct electrum_info *ep,cJSON **retjsonp) { return(electrum_noargs(symbol,ep,retjsonp,"server.banner",ELECTRUM_TIMEOUT)); }
cJSON *electrum_donation(char *symbol,struct electrum_info *ep,cJSON **retjsonp) { return(electrum_noargs(symbol,ep,retjsonp,"server.donation_address",ELECTRUM_TIMEOUT)); }
cJSON *electrum_peers(char *symbol,struct electrum_info *ep,cJSON **retjsonp) { return(electrum_noargs(symbol,ep,retjsonp,"server.peers.subscribe",ELECTRUM_TIMEOUT)); }
@ -472,12 +518,12 @@ cJSON *electrum_address_subscribe(char *symbol,struct electrum_info *ep,cJSON **
cJSON *retjson;
if ( (retjson= electrum_strarg(symbol,ep,retjsonp,"blockchain.address.subscribe",addr,ELECTRUM_TIMEOUT)) != 0 )
{
printf("subscribe.(%s)\n",jprint(retjson,0));
//printf("subscribe.(%s)\n",jprint(retjson,0));
}
return(retjson);
}
cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr)
cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr,bits256 reftxid)
{
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);
@ -489,7 +535,7 @@ cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON *
item = jitem(retjson,i);
txid = jbits256(item,"tx_hash");
height = jint(item,"height");
if ( (tx= LP_transactionfind(coin,txid)) == 0 )
if ( (tx= LP_transactionfind(coin,txid)) == 0 && (bits256_nonz(reftxid) == 0 || bits256_cmp(txid,reftxid) == 0) )
{
//char str[65]; printf("history txinit %s ht.%d\n",bits256_str(str,txid),height);
txobj = LP_transactioninit(coin,txid,0,0);
@ -503,7 +549,7 @@ cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON *
if ( tx->height > 0 && tx->height != height )
printf("update %s height.%d <- %d\n",bits256_str(str,txid),tx->height,height);
tx->height = height;
LP_address_utxoadd("electrum history",coin,addr,txid,0,0,height,-1);
LP_address_utxoadd((uint32_t)time(NULL),"electrum history",coin,addr,txid,0,0,height,-1);
}
}
}
@ -512,31 +558,33 @@ 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)
int32_t LP_txheight_check(struct iguana_info *coin,char *coinaddr,bits256 txid)
{
cJSON *retjson;
if ( coin->electrum != 0 )
{
if ( (retjson= electrum_address_gethistory(coin->symbol,coin->electrum,&retjson,coinaddr)) != 0 )
if ( (retjson= electrum_address_gethistory(coin->symbol,coin->electrum,&retjson,coinaddr,txid)) != 0 )
free_json(retjson);
}
return(0);
}
cJSON *electrum_address_getmempool(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr)
cJSON *electrum_address_getmempool(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr,bits256 reftxid,bits256 reftxid2)
{
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,1);
electrum_process_array(coin,ep,addr,retjson,1,reftxid,reftxid2);
return(retjson);
}
cJSON *electrum_address_listunspent(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr,int32_t electrumflag)
cJSON *electrum_address_listunspent(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr,int32_t electrumflag,bits256 txid,bits256 txid2)
{
cJSON *retjson=0; struct LP_address *ap; struct iguana_info *coin; int32_t height,usecache=1;
cJSON *retjson=0; char *retstr; struct LP_address *ap; struct iguana_info *coin; int32_t updatedflag,height,usecache=1;
if ( (coin= LP_coinfind(symbol)) == 0 )
return(0);
if ( strcmp(addr,INSTANTDEX_KMD) == 0 )
return(cJSON_Parse("[]"));
if ( ep == 0 || ep->heightp == 0 )
height = coin->longestchain;
else height = *(ep->heightp);
@ -546,24 +594,47 @@ cJSON *electrum_address_listunspent(char *symbol,struct electrum_info *ep,cJSON
usecache = 0;
else if ( ap->unspentheight < height )
usecache = 0;
else if ( G.LP_pendingswaps != 0 && time(NULL) > ap->unspenttime+20 )
else if ( G.LP_pendingswaps != 0 && time(NULL) > ap->unspenttime+13 )
usecache = 0;
}
//printf("electrum.%s/%s listunspent last.(%s lag %d)\n",ep->symbol,coin->symbol,coin->lastunspent,(int32_t)(time(NULL) - coin->unspenttime));
if ( usecache == 0 )
if ( usecache == 0 || electrumflag > 1 )
{
if ( (retjson= electrum_strarg(symbol,ep,retjsonp,"blockchain.address.listunspent",addr,ELECTRUM_TIMEOUT)) != 0 )
{
printf("%s.%d u.%u/%d t.%ld %s LISTUNSPENT.(%d)\n",coin->symbol,height,ap->unspenttime,ap->unspentheight,time(NULL),addr,(int32_t)strlen(jprint(retjson,0)));
if ( electrum_process_array(coin,ep,addr,retjson,electrumflag) != 0 )
LP_postutxos(coin->symbol,addr);
if ( ap != 0 )
if ( jobj(retjson,"error") == 0 && is_cJSON_Array(retjson) != 0 )
{
if ( 0 && electrumflag > 1 )
printf("%s.%d u.%u/%d t.%ld %s LISTUNSPENT.(%d)\n",coin->symbol,height,ap->unspenttime,ap->unspentheight,time(NULL),addr,(int32_t)strlen(jprint(retjson,0)));
updatedflag = 0;
if ( electrum_process_array(coin,ep,addr,retjson,electrumflag,txid,txid2) != 0 )
{
//LP_postutxos(coin->symbol,addr);
updatedflag = 1;
}
retstr = jprint(retjson,0);
LP_unspents_cache(coin->symbol,addr,retstr,1);
free(retstr);
if ( ap != 0 )
{
ap->unspenttime = (uint32_t)time(NULL);
ap->unspentheight = height;
}
}
else
{
ap->unspenttime = (uint32_t)time(NULL);
ap->unspentheight = height;
free_json(retjson);
retjson = 0;
}
}
} else retjson = LP_address_utxos(coin,addr,1);
}
if ( retjson == 0 )
{
if ( (retstr= LP_unspents_filestr(symbol,addr)) != 0 )
{
retjson = cJSON_Parse(retstr);
free(retstr);
} else retjson = LP_address_utxos(coin,addr,1);
}
return(retjson);
}
@ -575,7 +646,11 @@ cJSON *electrum_address_getbalance(char *symbol,struct electrum_info *ep,cJSON *
cJSON *electrum_addpeer(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *endpoint) { return(electrum_strarg(symbol,ep,retjsonp,"server.add_peer",endpoint,ELECTRUM_TIMEOUT)); }
cJSON *electrum_sendrawtransaction(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *rawtx) { return(electrum_strarg(symbol,ep,retjsonp,"blockchain.transaction.broadcast",rawtx,ELECTRUM_TIMEOUT)); }
cJSON *electrum_estimatefee(char *symbol,struct electrum_info *ep,cJSON **retjsonp,int32_t numblocks) { return(electrum_intarg(symbol,ep,retjsonp,"blockchain.estimatefee",numblocks,ELECTRUM_TIMEOUT)); }
cJSON *electrum_estimatefee(char *symbol,struct electrum_info *ep,cJSON **retjsonp,int32_t numblocks)
{
return(electrum_intarg(symbol,ep,retjsonp,"blockchain.estimatefee",numblocks,ELECTRUM_TIMEOUT));
}
cJSON *electrum_getchunk(char *symbol,struct electrum_info *ep,cJSON **retjsonp,int32_t n) { return(electrum_intarg(symbol,ep,retjsonp,"blockchain.block.get_chunk",n,ELECTRUM_TIMEOUT)); }
cJSON *electrum_getheader(char *symbol,struct electrum_info *ep,cJSON **retjsonp,int32_t n)
@ -583,19 +658,27 @@ cJSON *electrum_getheader(char *symbol,struct electrum_info *ep,cJSON **retjsonp
return(electrum_intarg(symbol,ep,retjsonp,"blockchain.block.get_header",n,ELECTRUM_TIMEOUT));
}
cJSON *LP_transaction_fromdata(struct iguana_info *coin,bits256 txid,uint8_t *serialized,int32_t len)
cJSON *LP_cache_transaction(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,4000000);
memset(&msgtx,0,sizeof(msgtx));
txobj = bitcoin_data2json(coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->height,&checktxid,&msgtx,extraspace,4000000,serialized,len,0,0,coin->zcash);
//printf("TX.(%s) match.%d\n",jprint(txobj,0),bits256_cmp(txid,checktxid));
free(extraspace);
if ( bits256_cmp(txid,checktxid) != 0 )
{
printf("%s LP_transaction_fromdata mismatched txid %s vs %s\n",coin->symbol,bits256_str(str,txid),bits256_str(str2,checktxid));
free_json(txobj);
txobj = 0;
cJSON *txobj; struct LP_transaction *tx;
if ( (txobj= LP_transaction_fromdata(coin,txid,serialized,len)) != 0 )
{
if ( (tx= LP_transactionfind(coin,txid)) == 0 || tx->serialized == 0 )
{
txobj = LP_transactioninit(coin,txid,0,txobj);
LP_transactioninit(coin,txid,1,txobj);
tx = LP_transactionfind(coin,txid);
}
if ( tx != 0 )
{
tx->serialized = serialized;
tx->len = len;
}
else
{
char str[65]; printf("unexpected couldnt find tx %s %s\n",coin->symbol,bits256_str(str,txid));
free(serialized);
}
}
return(txobj);
}
@ -625,11 +708,11 @@ cJSON *_electrum_transaction(char *symbol,struct electrum_info *ep,cJSON **retjs
}
hexjson = electrum_hasharg(symbol,ep,&hexjson,"blockchain.transaction.get",txid,ELECTRUM_TIMEOUT);
hexstr = jprint(hexjson,0);
if ( strlen(hexstr) > 60000 )
if ( strlen(hexstr) > 100000 )
{
static uint32_t counter;
if ( counter++ < 3 )
printf("rawtransaction too big %d\n",(int32_t)strlen(hexstr));
printf("rawtransaction %s %s too big %d\n",coin->symbol,bits256_str(str,txid),(int32_t)strlen(hexstr));
free(hexstr);
free_json(hexjson);
*retjsonp = cJSON_Parse("{\"error\":\"transaction too big\"}");
@ -649,30 +732,11 @@ cJSON *_electrum_transaction(char *symbol,struct electrum_info *ep,cJSON **retjs
memcpy(coin->cachedtxiddata,serialized,len);
free(hexstr);
//printf("DATA.(%s) from (%s)\n",hexstr+1,jprint(hexjson,0));
if ( (txobj= LP_transaction_fromdata(coin,txid,serialized,len)) != 0 )
{
if ( (tx= LP_transactionfind(coin,txid)) == 0 || tx->serialized == 0 )
{
txobj = LP_transactioninit(coin,txid,0,txobj);
LP_transactioninit(coin,txid,1,txobj);
tx = LP_transactionfind(coin,txid);
}
if ( tx != 0 )
{
tx->serialized = serialized;
tx->len = len;
}
else
{
printf("unexpected couldnt find tx %s %s\n",coin->symbol,bits256_str(str,txid));
free(serialized);
}
}
*retjsonp = txobj;
*retjsonp = LP_cache_transaction(coin,txid,serialized,len); // eats serialized
free_json(hexjson);
//printf("return from electrum_transaction\n");
return(*retjsonp);
} else printf("%s %s non-hex tx.(%s)\n",coin->symbol,bits256_str(str,txid),jprint(hexjson,0));
} //else printf("%s %s non-hex tx.(%s)\n",coin->symbol,bits256_str(str,txid),jprint(hexjson,0));
free(hexstr);
free_json(hexjson);
}
@ -680,12 +744,34 @@ cJSON *_electrum_transaction(char *symbol,struct electrum_info *ep,cJSON **retjs
return(*retjsonp);
}
cJSON *electrum_transaction(char *symbol,struct electrum_info *ep,cJSON **retjsonp,bits256 txid)
cJSON *electrum_transaction(int32_t *heightp,char *symbol,struct electrum_info *ep,cJSON **retjsonp,bits256 txid,char *SPVcheck)
{
cJSON *retjson;
cJSON *retjson,*array; bits256 zero; struct LP_transaction *tx=0; struct iguana_info *coin;
coin = LP_coinfind(symbol);
*heightp = 0;
if ( ep != 0 )
portable_mutex_lock(&ep->txmutex);
retjson = _electrum_transaction(symbol,ep,retjsonp,txid);
if ( (tx= LP_transactionfind(coin,txid)) != 0 && ep != 0 && coin != 0 && SPVcheck != 0 && SPVcheck[0] != 0 )
{
if ( tx->height <= 0 )
{
memset(zero.bytes,0,sizeof(zero));
if ( (array= electrum_address_listunspent(symbol,ep,&array,SPVcheck,2,txid,zero)) != 0 )
{
printf("SPVcheck.%s got %d unspents\n",SPVcheck,cJSON_GetArraySize(array));
free_json(array);
}
}
if ( tx->height > 0 )
{
if ( tx->SPV == 0 )
tx->SPV = LP_merkleproof(coin,SPVcheck,ep,txid,tx->height);
*heightp = tx->height;
}
char str[65]; printf("%s %s %s SPV height %d SPV %d\n",coin->symbol,SPVcheck,bits256_str(str,txid),tx->height,tx->SPV);
} else if ( tx != 0 )
*heightp = tx->height;
if ( ep != 0 )
portable_mutex_unlock(&ep->txmutex);
return(retjson);
@ -702,12 +788,13 @@ cJSON *electrum_getmerkle(char *symbol,struct electrum_info *ep,cJSON **retjsonp
void electrum_test()
{
cJSON *retjson; bits256 hash; struct electrum_info *ep = 0; char *addr,*script,*symbol = "BTC";
cJSON *retjson; int32_t height; bits256 hash,zero; struct electrum_info *ep = 0; char *addr,*script,*symbol = "BTC";
while ( Num_electrums == 0 )
{
sleep(1);
printf("Num_electrums %p -> %d\n",&Num_electrums,Num_electrums);
}
memset(zero.bytes,0,sizeof(zero));
printf("found electrum server\n");
if ( (retjson= electrum_version(symbol,ep,0)) != 0 )
printf("electrum_version %s\n",jprint(retjson,1));
@ -727,16 +814,16 @@ void electrum_test()
decode_hex(hash.bytes,sizeof(hash),"b967a7d55889fe11e993430921574ec6379bc8ce712a652c3fcb66c6be6e925c");
if ( (retjson= electrum_getmerkle(symbol,ep,0,hash,403000)) != 0 )
printf("electrum_getmerkle %s\n",jprint(retjson,1));
if ( (retjson= electrum_transaction(symbol,ep,0,hash)) != 0 )
if ( (retjson= electrum_transaction(&height,symbol,ep,0,hash,0)) != 0 )
printf("electrum_transaction %s\n",jprint(retjson,1));
addr = "14NeevLME8UAANiTCVNgvDrynUPk1VcQKb";
if ( (retjson= electrum_address_gethistory(symbol,ep,0,addr)) != 0 )
if ( (retjson= electrum_address_gethistory(symbol,ep,0,addr,zero)) != 0 )
printf("electrum_address_gethistory %s\n",jprint(retjson,1));
if ( (retjson= electrum_address_getmempool(symbol,ep,0,addr)) != 0 )
if ( (retjson= electrum_address_getmempool(symbol,ep,0,addr,zero,zero)) != 0 )
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,1)) != 0 )
if ( (retjson= electrum_address_listunspent(symbol,ep,0,addr,1,zero,zero)) != 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));
@ -816,9 +903,12 @@ struct electrum_info *LP_electrum_info(int32_t *alreadyp,char *symbol,char *ipad
int32_t LP_recvfunc(struct electrum_info *ep,char *str,int32_t len)
{
cJSON *strjson,*errjson,*resultjson,*paramsjson; char *method; int32_t i,n,height; uint32_t idnum=0; struct stritem *stritem; struct iguana_info *coin; struct queueitem *tmp,*item = 0;
if ( str == 0 || len == 0 )
return(-1);
ep->lasttime = (uint32_t)time(NULL);
if ( (strjson= cJSON_Parse(str)) != 0 )
{
//printf("%s RECV.(%ld) id.%d (%s)\n",ep->symbol,strlen(str),jint(strjson,"id"),jint(strjson,"id")==0?str:"");
resultjson = jobj(strjson,"result");
//printf("strjson.(%s)\n",jprint(strjson,0));
if ( (method= jstr(strjson,"method")) != 0 )
@ -859,10 +949,12 @@ int32_t LP_recvfunc(struct electrum_info *ep,char *str,int32_t len)
stritem = (struct stritem *)item;
if ( item->type == idnum )
{
//printf("matched idnum.%d result.%p\n",idnum,resultjson);
DL_DELETE(ep->pendingQ.list,item);
*((cJSON **)stritem->retptrp) = (resultjson != 0 ? jduplicate(resultjson) : strjson);
resultjson = strjson = 0;
if ( resultjson != 0 )
*((cJSON **)stritem->retptrp) = jduplicate(resultjson);
else *((cJSON **)stritem->retptrp) = strjson, strjson = 0;
//printf("matched idnum.%d result.(%s)\n",idnum,jprint(*((cJSON **)stritem->retptrp),0));
//resultjson = strjson = 0;
free(item);
break;
}
@ -890,11 +982,10 @@ int32_t LP_recvfunc(struct electrum_info *ep,char *str,int32_t len)
void LP_dedicatedloop(void *arg)
{
struct pollfd fds; int32_t i,len,flag,timeout = 10; struct iguana_info *coin; cJSON *retjson; struct stritem *sitem; struct electrum_info *ep = arg;
struct pollfd fds; int32_t i,len,n,flag,timeout = 10; struct iguana_info *coin; struct stritem *sitem; struct electrum_info *ep = arg;
if ( (coin= LP_coinfind(ep->symbol)) != 0 )
ep->heightp = &coin->height, ep->heighttimep = &coin->heighttime;
if ( (retjson= electrum_headers_subscribe(ep->symbol,ep,0)) != 0 )
free_json(retjson);
electrum_initial_requests(ep);
printf("LP_dedicatedloop ep.%p sock.%d for %s:%u num.%d %p %s ht.%d\n",ep,ep->sock,ep->ipaddr,ep->port,Num_electrums,&Num_electrums,ep->symbol,*ep->heightp);
while ( ep->sock >= 0 )
{
@ -912,6 +1003,7 @@ void LP_dedicatedloop(void *arg)
ep->sock = -1;
break;
}
ep->keepalive = (uint32_t)time(NULL);
if ( sitem->expiration != 0 )
sitem->expiration += (uint32_t)time(NULL);
else sitem->expiration = (uint32_t)time(NULL) + ELECTRUM_TIMEOUT;
@ -922,7 +1014,34 @@ void LP_dedicatedloop(void *arg)
{
if ( (fds.revents & POLLIN) != 0 )
{
if ( (len= LP_socketrecv(ep->sock,ep->buf,ep->bufsize)) > 0 )
len = 0;
while ( len+65536 < ep->bufsize )
{
if ( (n= LP_socketrecv(ep->sock,&ep->buf[len],ep->bufsize-len)) > 0 )
{
len += n;
if ( ep->buf[len - 1] == '\n' )
break;
memset(&fds,0,sizeof(fds));
fds.fd = ep->sock;
fds.events = POLLIN;
if ( poll(&fds,1,1000) <= 0 )
{
printf("no more electrum data after a second\n");
electrum_kickstart(ep);
break;
}
}
else
{
#ifndef _WIN32
printf("no more electrum data when expected2\n");
electrum_kickstart(ep);
#endif
break;
}
}
if ( len > 0 )
{
ep->pending = 0;
LP_recvfunc(ep,(char *)ep->buf,len);
@ -959,10 +1078,38 @@ void LP_dedicatedloop(void *arg)
cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port)
{
struct electrum_info *ep; int32_t already; cJSON *retjson = cJSON_CreateObject();
struct electrum_info *ep,*prev; int32_t kickval,already; cJSON *retjson,*array,*item;
if ( ipaddr == 0 || ipaddr[0] == 0 || port == 0 )
{
ep = coin->electrum;
coin->electrum = 0;
coin->inactive = (uint32_t)time(NULL);
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"status","electrum mode disabled, now in disabled native coin mode");
if ( ep != 0 )
{
array = cJSON_CreateArray();
while ( ep != 0 )
{
item = cJSON_CreateObject();
jaddstr(item,"ipaddr",ep->ipaddr);
jaddnum(item,"port",ep->port);
jaddnum(item,"kickstart",electrum_kickstart(ep));
jaddi(array,item);
prev = ep->prev;
ep->prev = 0;
ep = prev;
}
jadd(retjson,"electrums",array);
}
//printf("would have disabled %s electrum here\n",coin->symbol);
return(retjson);
}
retjson = cJSON_CreateObject();
jaddstr(retjson,"ipaddr",ipaddr);
jaddnum(retjson,"port",port);
if ( (ep= LP_electrum_info(&already,coin->symbol,ipaddr,port,IGUANA_MAXPACKETSIZE * 10)) == 0 )
if ( (ep= LP_electrum_info(&already,coin->symbol,ipaddr,port,IGUANA_MAXPACKETSIZE)) == 0 )
{
jaddstr(retjson,"error","couldnt connect to electrum server");
return(retjson);
@ -976,16 +1123,31 @@ cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port)
}
else
{
printf("launched electrum.(%s:%u)\n",ep->ipaddr,ep->port);
//printf("launched %s electrum.(%s:%u)\n",coin->symbol,ep->ipaddr,ep->port);
jaddstr(retjson,"result","success");
ep->prev = coin->electrum;
coin->electrum = ep;
if ( coin->loadedcache == 0 )
{
LP_cacheptrs_init(coin);
coin->loadedcache = (uint32_t)time(NULL);
}
}
}
else
{
if ( coin->electrum == 0 )
{
coin->electrum = ep;
ep->prev = 0;
}
jaddstr(retjson,"result","success");
jaddstr(retjson,"status","already there");
if ( ep->numerrors > 0 )
{
kickval = electrum_kickstart(ep);
jaddnum(retjson,"restart",kickval);
}
}
//printf("(%s)\n",jprint(retjson,0));
return(retjson);

1978
iguana/exchanges/LP_statemachine.c

File diff suppressed because it is too large

644
iguana/exchanges/LP_stats.c

@ -20,22 +20,82 @@
#define LP_STATSLOG_FNAME "stats.log"
struct LP_swapstats
{
UT_hash_handle hh;
struct LP_quoteinfo Q;
bits256 bobdeposit,alicepayment,bobpayment,paymentspent,Apaymentspent,depositspent;
double qprice;
uint64_t aliceid;
uint32_t ind,methodind,finished,expired;
char alicegui[32],bobgui[32];
} *LP_swapstats;
struct LP_swapstats *LP_swapstats,*LP_RTstats;
int32_t LP_statslog_parsequote(char *method,cJSON *lineobj);
char *LP_stats_methods[] = { "unknown", "request", "reserved", "connect", "connected", "tradestatus" };
#define LP_TRADESTATUS_METHODIND 5
static uint32_t LP_requests,LP_reserveds,LP_connects,LP_connecteds,LP_tradestatuses,LP_parse_errors,LP_unknowns,LP_duplicates,LP_aliceids;
void LP_dPoW_request(struct iguana_info *coin)
{
bits256 zero; cJSON *reqjson;
reqjson = cJSON_CreateObject();
jaddstr(reqjson,"method","getdPoW");
jaddstr(reqjson,"coin",coin->symbol);
memset(zero.bytes,0,sizeof(zero));
//printf("request %s\n",jprint(reqjson,0));
LP_reserved_msg(0,coin->symbol,coin->symbol,zero,jprint(reqjson,1));
}
void LP_dPoW_broadcast(struct iguana_info *coin)
{
bits256 zero; cJSON *reqjson;
if ( time(NULL) > coin->dPoWtime+60 && (coin->isassetchain != 0 || strcmp(coin->symbol,"KMD") == 0) )
{
reqjson = cJSON_CreateObject();
jaddstr(reqjson,"method","dPoW");
jaddstr(reqjson,"coin",coin->symbol);
jaddnum(reqjson,"notarized",coin->notarized);
jaddbits256(reqjson,"notarizedhash",coin->notarizedhash);
jaddbits256(reqjson,"notarizationtxid",coin->notarizationtxid);
memset(zero.bytes,0,sizeof(zero));
//printf("broadcast %s\n",jprint(reqjson,0));
LP_reserved_msg(0,coin->symbol,coin->symbol,zero,jprint(reqjson,1));
coin->dPoWtime = (uint32_t)time(NULL);
}
}
char *LP_dPoW_recv(cJSON *argjson)
{
int32_t notarized; bits256 notarizedhash,notarizationtxid; char *symbol; struct iguana_info *coin;
if ( (symbol= jstr(argjson,"coin")) != 0 && (coin= LP_coinfind(symbol)) != 0 && coin->electrum != 0 )
{
notarized = jint(argjson,"notarized");
notarizedhash = jbits256(argjson,"notarizedhash");
notarizationtxid = jbits256(argjson,"notarizationtxid");
//printf("dPoW %s\n",jprint(argjson,0));
if ( notarized > coin->notarized && LP_notarization_validate(symbol,notarized,notarizedhash,notarizationtxid) == 0 )
{
coin->notarized = notarized;
coin->notarizedhash = notarizedhash;
coin->notarizationtxid = notarizationtxid;
printf("VALIDATED dPoW %s\n",jprint(argjson,0));
}
}
return(clonestr("{\"result\":\"success\"}"));
}
/*int32_t LP_dPoWheight(struct iguana_info *coin) // get dPoW protected height
{
int32_t notarized,oldnotarized;
if ( coin->electrum == 0 )
{
coin->heighttime = (uint32_t)(time(NULL) - 61);
oldnotarized = coin->notarized;
LP_getheight(&notarized,coin);
if ( notarized != 0 && notarized != oldnotarized )
{
printf("dPoWheight.%s %d <- %d\n",coin->symbol,oldnotarized,notarized);
coin->notarized = notarized;
}
}
else if ( coin->notarized == 0 )
LP_dPoW_request(coin);
return(coin->notarized);
}*/
void LP_tradecommand_log(cJSON *argjson)
{
static FILE *logfp; char *jsonstr;
@ -90,13 +150,14 @@ void LP_statslog_parseline(cJSON *lineobj)
int32_t LP_statslog_parse()
{
static long lastpos; FILE *fp; char line[8192]; cJSON *lineobj; int32_t n = 0;
static long lastpos;
FILE *fp; long fpos; char line[8192]; cJSON *lineobj; int32_t c,n = 0;
if ( (fp= fopen(LP_STATSLOG_FNAME,"rb")) != 0 )
{
if ( lastpos > 0 )
{
fseek(fp,0,SEEK_END);
if ( ftell(fp) > lastpos )
if ( ftell(fp) >= lastpos )
fseek(fp,lastpos,SEEK_SET);
else
{
@ -104,6 +165,20 @@ int32_t LP_statslog_parse()
return(0);
}
}
else if ( 1 )
{
if ( IAMLP == 0 )
{
fseek(fp,0,SEEK_END);
if ( (fpos= ftell(fp)) > LP_CLIENT_STATSPARSE )
{
fseek(fp,fpos-LP_CLIENT_STATSPARSE,SEEK_SET);
while ( (c= fgetc(fp)) >= 0 && c != '\n' )
;
printf("start scanning %s from %ld, found boundary %ld\n",LP_STATSLOG_FNAME,fpos-LP_CLIENT_STATSPARSE,ftell(fp));
} else rewind(fp);
}
}
while ( fgets(line,sizeof(line),fp) > 0 )
{
lastpos = ftell(fp);
@ -123,18 +198,22 @@ int32_t LP_statslog_parse()
struct LP_swapstats *LP_swapstats_find(uint64_t aliceid)
{
struct LP_swapstats *sp;
HASH_FIND(hh,LP_swapstats,&aliceid,sizeof(aliceid),sp);
HASH_FIND(hh,LP_RTstats,&aliceid,sizeof(aliceid),sp);
if ( sp == 0 )
HASH_FIND(hh,LP_swapstats,&aliceid,sizeof(aliceid),sp);
return(sp);
}
struct LP_swapstats *LP_swapstats_add(uint64_t aliceid)
struct LP_swapstats *LP_swapstats_add(uint64_t aliceid,int32_t RTflag)
{
struct LP_swapstats *sp;
if ( (sp= LP_swapstats_find(aliceid)) == 0 )
{
sp = calloc(1,sizeof(*sp));
sp->aliceid = aliceid;
HASH_ADD(hh,LP_swapstats,aliceid,sizeof(aliceid),sp);
if ( RTflag != 0 )
HASH_ADD(hh,LP_RTstats,aliceid,sizeof(aliceid),sp);
else HASH_ADD(hh,LP_swapstats,aliceid,sizeof(aliceid),sp);
}
return(LP_swapstats_find(aliceid));
}
@ -173,6 +252,7 @@ bits256 LP_swapstats_txid(cJSON *argjson,char *name,bits256 oldtxid)
int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSON *lineobj)
{
char *statusstr,*base,*rel,gui[64]; uint32_t requestid,quoteid; uint64_t satoshis,destsatoshis;
sp->lasttime = (uint32_t)time(NULL);
safecopy(gui,sp->Q.gui,sizeof(gui));
if ( strcmp(LP_stats_methods[sp->methodind],"tradestatus") == 0 )
{
@ -182,7 +262,7 @@ int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSO
quoteid = juint(lineobj,"quoteid");
satoshis = jdouble(lineobj,"srcamount") * SATOSHIDEN;
destsatoshis = jdouble(lineobj,"destamount") * SATOSHIDEN;
if ( base != 0 && strcmp(base,sp->Q.srccoin) == 0 && rel != 0 && strcmp(rel,sp->Q.destcoin) == 0 && requestid == sp->Q.R.requestid && quoteid == sp->Q.R.quoteid && ((satoshis+2*sp->Q.txfee)|1) == (sp->Q.satoshis|1) && ((destsatoshis+2*sp->Q.desttxfee)|1) == (sp->Q.destsatoshis|1) )
if ( base != 0 && strcmp(base,sp->Q.srccoin) == 0 && rel != 0 && strcmp(rel,sp->Q.destcoin) == 0 && requestid == sp->Q.R.requestid && quoteid == sp->Q.R.quoteid && llabs((int64_t)(satoshis+2*sp->Q.txfee) - (int64_t)sp->Q.satoshis) <= sp->Q.txfee && llabs((int64_t)(destsatoshis+2*sp->Q.desttxfee) - (int64_t)sp->Q.destsatoshis) <= sp->Q.desttxfee )
{
sp->bobdeposit = LP_swapstats_txid(lineobj,"bobdeposit",sp->bobdeposit);
sp->alicepayment = LP_swapstats_txid(lineobj,"alicepayment",sp->alicepayment);
@ -195,14 +275,14 @@ int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSO
if ( (sp->finished= juint(lineobj,"timestamp")) == 0 )
sp->finished = (uint32_t)time(NULL);
}
if ( sp->finished == 0 && time(NULL) > sp->Q.timestamp+INSTANTDEX_LOCKTIME*2 )
if ( sp->finished == 0 && time(NULL) > sp->Q.timestamp+LP_atomic_locktime(base,rel)*2 )
sp->expired = (uint32_t)time(NULL);
return(0);
}
else
{
if ( requestid == sp->Q.R.requestid && quoteid == sp->Q.R.quoteid )
printf("mismatched tradestatus aliceid.%016llx b%s/%s r%s/%s r%u/%u q%u/%u %.8f/%.8f -> %.8f/%.8f\n",(long long)sp->aliceid,base,sp->Q.srccoin,rel,sp->Q.destcoin,requestid,sp->Q.R.requestid,quoteid,sp->Q.R.quoteid,dstr(satoshis+2*sp->Q.txfee),dstr(sp->Q.satoshis),dstr(destsatoshis+2*sp->Q.desttxfee),dstr(sp->Q.destsatoshis));
if ( 0 && requestid == sp->Q.R.requestid && quoteid == sp->Q.R.quoteid )
printf("mismatched tradestatus aliceid.%22llu b%s/%s r%s/%s r%u/%u q%u/%u %.8f/%.8f -> %.8f/%.8f\n",(long long)sp->aliceid,base,sp->Q.srccoin,rel,sp->Q.destcoin,requestid,sp->Q.R.requestid,quoteid,sp->Q.R.quoteid,dstr(satoshis+2*sp->Q.txfee),dstr(sp->Q.satoshis),dstr(destsatoshis+2*sp->Q.desttxfee),dstr(sp->Q.destsatoshis));
return(-1);
}
@ -212,10 +292,140 @@ int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSO
return(0);
}
int32_t LP_finished_lastheight(struct LP_swapstats *sp)
{
int32_t height = 1; struct iguana_info *bob,*alice; //char str[65];
if ( (bob= LP_coinfind(sp->Q.srccoin)) != 0 && (alice= LP_coinfind(sp->Q.destcoin)) != 0 )
{
if ( strcmp(bob->symbol,"BTC") == 0 )
sp->bobneeds_dPoW = 0;
if ( strcmp(alice->symbol,"BTC") == 0 )
sp->aliceneeds_dPoW = 0;
if ( sp->bobneeds_dPoW != 0 )
{
if ( bits256_nonz(sp->bobdeposit) != 0 && sp->bobdeposit_ht == 0 )
{
if ( (sp->bobdeposit_ht= LP_txheight(bob,sp->bobdeposit)) > sp->bobneeds_dPoW )
sp->bobneeds_dPoW = sp->bobdeposit_ht;
//printf("%s bobdeposit.%d height.%d\n",bits256_str(str,sp->bobdeposit),ht,sp->bobneeds_dPoW);
}
if ( bits256_nonz(sp->bobpayment) != 0 && sp->bobpayment_ht == 0 )
{
if ( (sp->bobpayment_ht= LP_txheight(bob,sp->bobpayment)) > sp->bobneeds_dPoW )
sp->bobneeds_dPoW = sp->bobpayment_ht;
//printf("%s bobpayment.%d height.%d\n",bits256_str(str,sp->bobpayment),ht,sp->bobneeds_dPoW);
}
if ( bits256_nonz(sp->paymentspent) != 0 && sp->paymentspent_ht == 0 )
{
if ( (sp->paymentspent_ht= LP_txheight(bob,sp->paymentspent)) > sp->bobneeds_dPoW )
sp->bobneeds_dPoW = sp->paymentspent_ht;
//printf("%s paymentspent.%d height.%d\n",bits256_str(str,sp->paymentspent),ht,sp->bobneeds_dPoW);
}
if ( bits256_nonz(sp->depositspent) != 0 && sp->depositspent_ht == 0 )
{
if ( (sp->depositspent_ht= LP_txheight(bob,sp->depositspent)) > sp->bobneeds_dPoW )
sp->bobneeds_dPoW = sp->depositspent_ht;
//printf("%s depositspent.%d height.%d\n",bits256_str(str,sp->depositspent),ht,sp->bobneeds_dPoW);
}
}
if ( sp->aliceneeds_dPoW != 0 )
{
if ( bits256_nonz(sp->alicepayment) != 0 && sp->alicepayment_ht == 0 )
{
if ( (sp->alicepayment_ht= LP_txheight(alice,sp->alicepayment)) > sp->aliceneeds_dPoW )
sp->aliceneeds_dPoW = sp->alicepayment_ht;
//printf("%s alicepayment.%d height.%d\n",bits256_str(str,sp->alicepayment),ht,sp->aliceneeds_dPoW);
}
if ( bits256_nonz(sp->Apaymentspent) != 0 && sp->Apaymentspent_ht == 0 )
{
if ( (sp->Apaymentspent_ht= LP_txheight(alice,sp->Apaymentspent)) > sp->aliceneeds_dPoW )
sp->aliceneeds_dPoW = sp->Apaymentspent_ht;
//printf("%s Apaymentspent.%d height.%d\n",bits256_str(str,sp->Apaymentspent),ht,sp->aliceneeds_dPoW);
}
}
}
return(height);
}
int32_t LP_swap_finished(struct LP_swapstats *sp,int32_t dPoWflag)
{
struct iguana_info *bob,*alice;
if ( sp->dPoWfinished != 0 || sp->expired != 0 )
return(1);
else if ( dPoWflag == 0 && sp->finished != 0 )
return(1);
if ( (bob= LP_coinfind(sp->Q.srccoin)) == 0 )
{
//printf("no bobcoin.%s\n",sp->Q.srccoin);
return(0);
}
if ( (alice= LP_coinfind(sp->Q.destcoin)) == 0 )
{
//printf("no alicecoin.%s\n",sp->Q.destcoin);
return(0);
}
if ( dPoWflag != 0 )
{
if ( sp->finished != 0 )
{
LP_finished_lastheight(sp);
if ( 0 && IAMLP == 0 )
printf("bob needs %d @ %d, alice needs %d @ %d\n",sp->bobneeds_dPoW,bob->notarized,sp->aliceneeds_dPoW,alice->notarized);
}
if ( (sp->bobneeds_dPoW == 0 || (sp->bobneeds_dPoW > 1 && bob->notarized >= sp->bobneeds_dPoW)) && (sp->aliceneeds_dPoW == 0 || (sp->aliceneeds_dPoW > 1 && alice->notarized >= sp->aliceneeds_dPoW)) )
{
sp->dPoWfinished = (uint32_t)time(NULL);
return(1);
}
}
return(0);
}
struct LP_swapstats *LP_swapstats_create(uint64_t aliceid,int32_t RTflag,struct LP_quoteinfo *qp,double qprice,int32_t methodind)
{
struct LP_pubswap *ptr; struct iguana_info *alice,*bob; struct LP_pubkey_info *pubp; char *base,*rel; struct LP_swapstats *sp = 0;
base = qp->srccoin, rel = qp->destcoin;
if ( (sp= LP_swapstats_add(aliceid,RTflag)) != 0 )
{
sp->Q = *qp;
sp->qprice = qprice;
sp->methodind = methodind;
sp->ind = LP_aliceids++;
sp->lasttime = (uint32_t)time(NULL);
if ( sp->lasttime > sp->Q.timestamp+LP_atomic_locktime(base,rel)*2 )
sp->expired = sp->lasttime;
else
{
if ( (alice= LP_coinfind(rel)) != 0 && (alice->isassetchain != 0 || strcmp("KMD",alice->symbol) == 0) )
sp->aliceneeds_dPoW = 1;
if ( (bob= LP_coinfind(rel)) != 0 && (bob->isassetchain != 0 || strcmp(bob->symbol,"KMD") == 0) )
sp->bobneeds_dPoW = 1;
}
strcpy(sp->bobgui,"nogui");
strcpy(sp->alicegui,"nogui");
if ( LP_swap_finished(sp,1) == 0 ) //sp->finished == 0 && sp->expired == 0 )
{
if ( (pubp= LP_pubkeyadd(qp->srchash)) != 0 )
{
ptr = calloc(1,sizeof(*ptr));
ptr->swap = sp;
DL_APPEND(pubp->bobswaps,ptr);
}
if ( (pubp= LP_pubkeyadd(qp->desthash)) != 0 )
{
ptr = calloc(1,sizeof(*ptr));
ptr->swap = sp;
DL_APPEND(pubp->aliceswaps,ptr);
}
}
} else printf("unexpected LP_swapstats_add failure\n");
return(sp);
}
int32_t LP_statslog_parsequote(char *method,cJSON *lineobj)
{
static uint32_t unexpected;
struct LP_swapstats *sp,*tmp; double qprice; uint32_t requestid,quoteid,timestamp; int32_t i,flag,numtrades[LP_MAXPRICEINFOS],methodind,destvout,feevout,duplicate=0; char *gui,*base,*rel; uint64_t aliceid,txfee,satoshis,destsatoshis; bits256 desttxid,feetxid; struct LP_quoteinfo Q; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS];
struct LP_swapstats *sp,*tmp; double qprice; uint32_t requestid,quoteid,timestamp; int32_t i,RTflag,flag,numtrades[LP_MAXPRICEINFOS],methodind,destvout,feevout,duplicate=0; char *statusstr,*gui,*base,*rel; uint64_t aliceid,txfee,satoshis,destsatoshis; bits256 desttxid,feetxid; struct LP_quoteinfo Q; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS];
memset(numtrades,0,sizeof(numtrades));
memset(basevols,0,sizeof(basevols));
memset(relvols,0,sizeof(relvols));
@ -235,8 +445,11 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj)
if ( (sp= LP_swapstats_find(aliceid)) != 0 )
{
sp->methodind = methodind;
sp->Q.R.requestid = requestid;
sp->Q.R.quoteid = quoteid;
if ( LP_swapstats_update(sp,&Q,lineobj) == 0 )
flag = 1;
//else printf("LP_swapstats_update error\n");
}
if ( flag == 0 )
{
@ -246,14 +459,20 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj)
{
sp->methodind = methodind;
if ( LP_swapstats_update(sp,&Q,lineobj) == 0 )
{
flag = 1;
else printf("error after delayed match\n");
break;
break;
}
printf("error after delayed match\n");
}
}
}
if ( flag == 0 )
printf("unexpected.%d tradestatus.(%s)\n",unexpected++,jprint(lineobj,0));
{
static uint32_t counter;
if ( counter++ < 3 )
printf("unexpected.%d tradestatus aliceid.%llu requestid.%u quoteid.%u\n",unexpected++,(long long)aliceid,requestid,quoteid);//,jprint(lineobj,0));
}
return(0);
}
if ( LP_quoteparse(&Q,lineobj) < 0 )
@ -283,6 +502,9 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj)
destvout = jint(lineobj,"destvout");
feetxid = jbits256(lineobj,"feetxid");
feevout = jint(lineobj,"feevout");
if ( (statusstr= jstr(lineobj,"status")) != 0 && strcmp(statusstr,"finished") == 0 )
RTflag = 0;
else RTflag = 1;
qprice = ((double)destsatoshis / (satoshis - txfee));
//printf("%s/v%d %s/v%d\n",bits256_str(str,desttxid),destvout,bits256_str(str2,feetxid),feevout);
aliceid = LP_aliceid_calc(desttxid,destvout,feetxid,feevout);
@ -298,17 +520,8 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj)
}
else
{
if ( (sp= LP_swapstats_add(aliceid)) != 0 )
{
sp->Q = Q;
sp->qprice = qprice;
sp->methodind = methodind;
sp->ind = LP_aliceids++;
strcpy(sp->bobgui,"nogui");
strcpy(sp->alicegui,"nogui");
//LP_swapstats_line(numtrades,basevols,relvols,line,sp);
//printf("%s\n",line);
} else printf("unexpected LP_swapstats_add failure\n");
sp = LP_swapstats_create(aliceid,RTflag,&Q,qprice,methodind);
//printf("create aliceid.%llu\n",(long long)aliceid);
}
if ( sp != 0 )
{
@ -323,11 +536,194 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj)
return(duplicate == 0);
}
char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey)
cJSON *LP_swapstats_json(struct LP_swapstats *sp)
{
cJSON *item = cJSON_CreateObject();
jaddnum(item,"timestamp",sp->Q.timestamp);
jadd64bits(item,"aliceid",sp->aliceid);
jaddbits256(item,"src",sp->Q.srchash);
jaddstr(item,"base",sp->Q.srccoin);
jaddnum(item,"basevol",dstr(sp->Q.satoshis));
jaddbits256(item,"dest",sp->Q.desthash);
jaddstr(item,"rel",sp->Q.destcoin);
jaddnum(item,"relvol",dstr(sp->Q.destsatoshis));
jaddnum(item,"price",sp->qprice);
jaddnum(item,"requestid",sp->Q.R.requestid);
jaddnum(item,"quoteid",sp->Q.R.quoteid);
jaddnum(item,"finished",sp->finished);
jaddnum(item,"expired",sp->expired);
if ( bits256_nonz(sp->bobdeposit) != 0 )
jaddbits256(item,"bobdeposit",sp->bobdeposit);
if ( bits256_nonz(sp->alicepayment) != 0 )
jaddbits256(item,"alicepayment",sp->alicepayment);
if ( bits256_nonz(sp->bobpayment) != 0 )
jaddbits256(item,"bobpayment",sp->bobpayment);
if ( bits256_nonz(sp->paymentspent) != 0 )
jaddbits256(item,"paymentspent",sp->paymentspent);
if ( bits256_nonz(sp->Apaymentspent) != 0 )
jaddbits256(item,"Apaymentspent",sp->Apaymentspent);
if ( bits256_nonz(sp->depositspent) != 0 )
jaddbits256(item,"depositspent",sp->depositspent);
if ( sp->finished == 0 && sp->expired == 0 )
jaddnum(item,"expires",sp->Q.timestamp + LP_atomic_locktime(sp->Q.srccoin,sp->Q.destcoin)*2 - time(NULL));
jaddnum(item,"ind",sp->methodind);
//jaddstr(item,"line",line);
return(item);
}
char *LP_swapstatus_recv(cJSON *argjson)
{
cJSON *retjson,*array,*item; struct LP_swapstats *sp,*tmp; int32_t i,dispflag,numtrades[LP_MAXPRICEINFOS]; char line[1024]; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS];
struct LP_swapstats *sp; char *statusstr; uint64_t aliceid; double qprice; struct LP_quoteinfo Q; int32_t methodind,RTflag; bits256 txid; //char str[65];
if ( (aliceid= j64bits(argjson,"aliceid")) == 0 )
return(clonestr("{\"error\":\"LP_swapstatus_recv null aliceid\"}"));
if ( (sp= LP_swapstats_find(aliceid)) == 0 )
{
LP_quoteparse(&Q,argjson);
if ( Q.satoshis > Q.txfee )
return(clonestr("{\"error\":\"LP_swapstatus_recv null satoshis\"}"));
qprice = (double)Q.destsatoshis / (Q.satoshis - Q.txfee);
if ( (statusstr= jstr(argjson,"status")) != 0 && strcmp(statusstr,"finished") == 0 )
RTflag = 0;
else RTflag = 1;
sp = LP_swapstats_create(aliceid,RTflag,&Q,qprice,LP_TRADESTATUS_METHODIND);
//printf("create swapstatus from recv\n");
}
if ( sp != 0 )
{
if ( 0 && IAMLP == 0 )
printf("swapstatus.(%s)\n",jprint(argjson,0));
sp->lasttime = (uint32_t)time(NULL);
if ( (methodind= jint(argjson,"ind")) > sp->methodind && methodind < sizeof(LP_stats_methods)/sizeof(*LP_stats_methods) )
{
if ( 0 && sp->finished == 0 && sp->expired == 0 )
printf("SWAPSTATUS updated %llu %s %u %u\n",(long long)sp->aliceid,LP_stats_methods[sp->methodind],juint(argjson,"finished"),juint(argjson,"expired"));
sp->methodind = methodind;
sp->finished = juint(argjson,"finished");
sp->expired = juint(argjson,"expired");
txid = jbits256(argjson,"bobdeposit");
if ( bits256_nonz(txid) != 0 && bits256_nonz(sp->bobdeposit) == 0 )
{
sp->bobdeposit = txid;
//printf("set aliceid.%llu bobdeposit %s\n",(long long)sp->aliceid,bits256_str(str,txid));
}
txid = jbits256(argjson,"alicepayment");
if ( bits256_nonz(txid) != 0 && bits256_nonz(sp->alicepayment) == 0 )
{
sp->alicepayment = txid;
//printf("set aliceid.%llu alicepayment %s\n",(long long)sp->aliceid,bits256_str(str,txid));
}
txid = jbits256(argjson,"bobpayment");
if ( bits256_nonz(txid) != 0 && bits256_nonz(sp->bobpayment) == 0 )
{
sp->bobpayment = txid;
//printf("set aliceid.%llu bobpayment %s\n",(long long)sp->aliceid,bits256_str(str,txid));
}
txid = jbits256(argjson,"paymentspent");
if ( bits256_nonz(txid) != 0 && bits256_nonz(sp->paymentspent) == 0 )
{
sp->paymentspent = txid;
//printf("set aliceid.%llu paymentspent %s\n",(long long)sp->aliceid,bits256_str(str,txid));
}
txid = jbits256(argjson,"Apaymentspent");
if ( bits256_nonz(txid) != 0 && bits256_nonz(sp->Apaymentspent) == 0 )
{
sp->Apaymentspent = txid;
//printf("set aliceid.%llu Apaymentspent %s\n",(long long)sp->aliceid,bits256_str(str,txid));
}
txid = jbits256(argjson,"depositspent");
if ( bits256_nonz(txid) != 0 && bits256_nonz(sp->depositspent) == 0 )
{
sp->depositspent = txid;
//printf("set aliceid.%llu depositspent %s\n",(long long)sp->aliceid,bits256_str(str,txid));
}
}
}
return(clonestr("{\"result\":\"success\"}"));
}
char *LP_gettradestatus(uint64_t aliceid,uint32_t requestid,uint32_t quoteid)
{
struct LP_swapstats *sp; struct iguana_info *bob,*alice; char *swapstr,*statusstr; cJSON *reqjson,*swapjson; bits256 zero;
//printf("gettradestatus.(%llu)\n",(long long)aliceid);
if ( IAMLP != 0 )
{
if ( (sp= LP_swapstats_find(aliceid)) != 0 && sp->Q.satoshis != 0 && sp->Q.destsatoshis != 0 && bits256_nonz(sp->bobdeposit) != 0 )
{
if ( time(NULL) > sp->lasttime+60 )
{
if ( (reqjson= LP_swapstats_json(sp)) != 0 )
{
jaddstr(reqjson,"method","swapstatus");
memset(zero.bytes,0,sizeof(zero));
LP_reserved_msg(0,"","",zero,jprint(reqjson,1));
}
if ( (bob= LP_coinfind(sp->Q.srccoin)) != 0 )
LP_dPoW_broadcast(bob);
if ( (alice= LP_coinfind(sp->Q.destcoin)) != 0 )
LP_dPoW_broadcast(alice);
}
return(clonestr("{\"result\":\"success\"}"));
}
}
if ( (swapstr= basilisk_swapentry(requestid,quoteid,0)) != 0 )
{
if ( (swapjson= cJSON_Parse(swapstr)) != 0 )
{
if ( (statusstr= jstr(swapjson,"status")) != 0 && strcmp(statusstr,"finished") == 0 )
{
jaddstr(swapjson,"method","swapstatus");
memset(zero.bytes,0,sizeof(zero));
printf("send local swapstatus\n");
LP_reserved_msg(0,"","",zero,jprint(swapjson,0));
}
free_json(swapjson);
}
free(swapstr);
}
return(clonestr("{\"result\":\"success\"}"));
}
int32_t LP_stats_dispiter(cJSON *array,struct LP_swapstats *sp,uint32_t starttime,uint32_t endtime,char *refbase,char *refrel,char *refgui,bits256 refpubkey)
{
int32_t dispflag,retval = 0;
if ( sp->finished == 0 && sp->expired == 0 && time(NULL) > sp->Q.timestamp+LP_atomic_locktime(sp->Q.srccoin,sp->Q.destcoin)*2 )
sp->expired = (uint32_t)time(NULL);
if ( LP_swap_finished(sp,1) > 0 )
retval = 1;
dispflag = 0;
if ( starttime == 0 && endtime == 0 )
dispflag = 1;
else if ( starttime > time(NULL) && endtime == starttime && sp->finished == 0 && sp->expired == 0 )
dispflag = 1;
else if ( sp->Q.timestamp >= starttime && sp->Q.timestamp <= endtime )
dispflag = 1;
if ( refbase != 0 && strcmp(refbase,sp->Q.srccoin) != 0 && strcmp(refbase,sp->Q.destcoin) != 0 )
dispflag = 0;
if ( refrel != 0 && strcmp(refrel,sp->Q.srccoin) != 0 && strcmp(refrel,sp->Q.destcoin) != 0 )
dispflag = 0;
if ( dispflag != 0 )
{
dispflag = 0;
if ( refgui == 0 || refgui[0] == 0 || strcmp(refgui,sp->bobgui) == 0 || strcmp(refgui,sp->alicegui) == 0 )
{
if ( bits256_nonz(refpubkey) == 0 || bits256_cmp(refpubkey,sp->Q.srchash) == 0 || bits256_cmp(refpubkey,sp->Q.desthash) == 0 )
dispflag = 1;
}
}
if ( dispflag != 0 )
jaddi(array,LP_swapstats_json(sp));
return(retval);
}
cJSON *LP_statslog_disp(uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey,char *refbase,char *refrel)
{
static int32_t rval;
cJSON *retjson,*array,*item,*reqjson; struct LP_pubkey_info *pubp,*ptmp; bits256 zero; uint32_t now; struct LP_swapstats *sp,*tmp; int32_t i,n,numtrades[LP_MAXPRICEINFOS]; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS];
if ( rval == 0 )
rval = (LP_rand() % 300) + 60;
if ( starttime > endtime )
starttime = endtime;
n = LP_statslog_parse();
memset(basevols,0,sizeof(basevols));
memset(relvols,0,sizeof(relvols));
memset(numtrades,0,sizeof(numtrades));
@ -335,45 +731,41 @@ char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgu
jaddstr(retjson,"result","success");
jaddnum(retjson,"newlines",n);
array = cJSON_CreateArray();
HASH_ITER(hh,LP_swapstats,sp,tmp)
LP_RTcount = LP_swapscount = 0;
now = (uint32_t)time(NULL);
HASH_ITER(hh,LP_RTstats,sp,tmp)
{
if ( sp->finished == 0 && time(NULL) > sp->Q.timestamp+INSTANTDEX_LOCKTIME*2 )
sp->expired = (uint32_t)time(NULL);
dispflag = 0;
if ( starttime == 0 && endtime == 0 )
dispflag = 1;
else if ( starttime > time(NULL) && endtime == starttime && sp->finished == 0 && sp->expired == 0 )
dispflag = 1;
else if ( sp->Q.timestamp >= starttime && sp->Q.timestamp <= endtime )
dispflag = 1;
if ( dispflag != 0 )
{
dispflag = 0;
if ( refgui == 0 || refgui[0] == 0 || strcmp(refgui,sp->bobgui) == 0 || strcmp(refgui,sp->alicegui) == 0 )
{
if ( bits256_nonz(refpubkey) == 0 || bits256_cmp(refpubkey,sp->Q.srchash) == 0 || bits256_cmp(refpubkey,sp->Q.desthash) == 0 )
dispflag = 1;
}
if ( LP_stats_dispiter(array,sp,starttime,endtime,refbase,refrel,refgui,refpubkey) > 0 )
{
HASH_DELETE(hh,LP_RTstats,sp);
HASH_ADD(hh,LP_swapstats,aliceid,sizeof(sp->aliceid),sp);
}
if ( dispflag != 0 )
else
{
LP_swapstats_line(numtrades,basevols,relvols,line,sp);
item = cJSON_CreateObject();
jadd64bits(item,"aliceid",sp->aliceid);
jaddbits256(item,"src",sp->Q.srchash);
jaddstr(item,"base",sp->Q.srccoin);
jaddnum(item,"basevol",dstr(sp->Q.satoshis));
jaddbits256(item,"dest",sp->Q.desthash);
jaddstr(item,"rel",sp->Q.destcoin);
jaddnum(item,"relvol",dstr(sp->Q.destsatoshis));
jaddnum(item,"price",sp->qprice);
jaddnum(item,"requestid",sp->Q.R.requestid);
jaddnum(item,"quoteid",sp->Q.R.quoteid);
jaddstr(item,"line",line);
jaddi(array,item);
LP_RTcount++;
if ( now > sp->lasttime+rval )
{
reqjson = cJSON_CreateObject();
jaddstr(reqjson,"method","gettradestatus");
jadd64bits(reqjson,"aliceid",sp->aliceid);
memset(zero.bytes,0,sizeof(zero));
LP_reserved_msg(0,"","",zero,jprint(reqjson,1));
}
}
}
HASH_ITER(hh,LP_swapstats,sp,tmp)
{
LP_stats_dispiter(array,sp,starttime,endtime,refbase,refrel,refgui,refpubkey);
LP_swapscount++;
}
HASH_ITER(hh,LP_pubkeyinfos,pubp,ptmp)
{
pubp->dynamictrust = LP_dynamictrust(0,pubp->pubkey,0);
}
//printf("RT.%d completed.%d\n",LP_RTcount,LP_swapscount);
jadd(retjson,"swaps",array);
jaddnum(retjson,"RTcount",LP_RTcount);
jaddnum(retjson,"swapscount",LP_swapscount);
array = cJSON_CreateArray();
for (i=0; i<LP_MAXPRICEINFOS; i++)
{
@ -398,7 +790,119 @@ char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgu
jaddnum(retjson,"uniques",LP_aliceids);
jaddnum(retjson,"tradestatus",LP_tradestatuses);
jaddnum(retjson,"unknown",LP_unknowns);
return(jprint(retjson,1));
return(retjson);
}
//tradesarray(base, rel, starttime=<now>-timescale*1024, endtime=<now>, timescale=60) -> [timestamp, high, low, open, close, relvolume, basevolume, aveprice, numtrades]
struct LP_ohlc
{
uint32_t timestamp,firsttime,lasttime,numtrades;
double high,low,open,close,relsum,basesum;
};
cJSON *LP_ohlc_json(struct LP_ohlc *bar,struct LP_ohlc *prevbar)
{
cJSON *item; struct LP_ohlc tmp;
memset(&tmp,0,sizeof(tmp));
if ( bar->numtrades == 0 )
{
memset(&tmp,0,sizeof(tmp));
tmp.timestamp = bar->timestamp;
tmp.open = tmp.high = tmp.low = tmp.close = prevbar->close;
tmp.numtrades = 0;
tmp.relsum = tmp.basesum = 0.;
} else tmp = *bar;
bar = &tmp;
item = cJSON_CreateArray();
jaddinum(item,bar->timestamp);
jaddinum(item,bar->high);
jaddinum(item,bar->low);
jaddinum(item,bar->open);
jaddinum(item,bar->close);
jaddinum(item,bar->relsum);
jaddinum(item,bar->basesum);
if ( bar->basesum != 0 )
jaddinum(item,bar->relsum / bar->basesum);
else jaddinum(item,0);
jaddinum(item,bar->numtrades);
return(item);
}
void LP_ohlc_update(struct LP_ohlc *bar,uint32_t timestamp,double basevol,double relvol)
{
double price;
if ( basevol > SMALLVAL && relvol > SMALLVAL )
{
price = relvol / basevol;
if ( bar->firsttime == 0 || timestamp < bar->firsttime )
{
bar->firsttime = timestamp;
bar->open = price;
}
if ( bar->lasttime == 0 || timestamp > bar->lasttime )
{
bar->lasttime = timestamp;
bar->close = price;
}
if ( bar->low == 0. || price < bar->low )
bar->low = price;
if ( bar->high == 0. || price > bar->high )
bar->high = price;
bar->basesum += basevol;
bar->relsum += relvol;
bar->numtrades++;
//printf("%d %.8f/%.8f -> %.8f\n",bar->numtrades,basevol,relvol,price);
}
}
cJSON *LP_tradesarray(char *refbase,char *refrel,uint32_t starttime,uint32_t endtime,int32_t timescale)
{
struct LP_ohlc *bars,nonz; cJSON *array,*item,*statsjson,*swaps; uint32_t timestamp; bits256 zero; char *base,*rel; int32_t i,n,numbars,bari;
if ( timescale < 60 )
return(cJSON_Parse("{\"error\":\"one minute is shortest timescale\"}"));
memset(zero.bytes,0,sizeof(zero));
if ( endtime == 0 )
endtime = (((uint32_t)time(NULL) / timescale) * timescale);
if ( starttime == 0 || starttime >= endtime )
starttime = (endtime - LP_SCREENWIDTH*timescale);
numbars = ((endtime - starttime) / timescale) + 1;
bars = calloc(numbars,sizeof(*bars));
for (bari=0; bari<numbars; bari++)
bars[bari].timestamp = starttime + bari*timescale;
if ( (statsjson= LP_statslog_disp(starttime,endtime,"",zero,refbase,refrel)) != 0 )
{
if ( (swaps= jarray(&n,statsjson,"swaps")) != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(swaps,i);
if ( (timestamp= juint(item,"timestamp")) != 0 && timestamp >= starttime && timestamp <= endtime )
{
bari = (timestamp - starttime) / timescale;
base = jstr(item,"base");
rel = jstr(item,"rel");
if ( strcmp(base,refbase) == 0 && strcmp(rel,refrel) == 0 )
LP_ohlc_update(&bars[bari],timestamp,jdouble(item,"basevol"),jdouble(item,"relvol"));
else if ( strcmp(rel,refbase) == 0 && strcmp(base,refrel) == 0 )
LP_ohlc_update(&bars[bari],timestamp,jdouble(item,"relvol"),jdouble(item,"basevol"));
} else printf("skip.(%s)\n",jprint(item,0));
}
}
free_json(statsjson);
}
array = cJSON_CreateArray();
memset(&nonz,0,sizeof(nonz));
for (bari=0; bari<numbars; bari++)
{
if ( (item= LP_ohlc_json(&bars[bari],&nonz)) != 0 )
{
jaddi(array,item);
if ( bars[bari].numtrades > 0 )
nonz = bars[bari];
}
}
free(bars);
return(array);
}

342
iguana/exchanges/LP_swap.c

@ -109,24 +109,44 @@
*/
uint32_t LP_atomic_locktime(char *base,char *rel)
{
if ( strcmp(base,"BTC") != 0 && strcmp(rel,"BTC") != 0 )
return(INSTANTDEX_LOCKTIME);
else return(INSTANTDEX_LOCKTIME * 10);
}
void basilisk_rawtx_purge(struct basilisk_rawtx *rawtx)
{
if ( rawtx->vins != 0 )
free_json(rawtx->vins);
free_json(rawtx->vins), rawtx->vins = 0;
//if ( rawtx->txbytes != 0 )
// free(rawtx->txbytes), rawtx->txbytes = 0;
}
void basilisk_swap_finished(struct basilisk_swap *swap)
{
int32_t i;
/*int32_t i;
if ( swap->utxo != 0 && swap->sentflag == 0 )
{
LP_availableset(swap->utxo);
swap->utxo = 0;
//LP_butxo_swapfields_set(swap->utxo);
}
swap->I.finished = (uint32_t)time(NULL);
swap->I.finished = (uint32_t)time(NULL);*/
if ( swap->I.finished == 0 )
{
if ( swap->I.iambob != 0 )
{
LP_availableset(swap->bobdeposit.utxotxid,swap->bobdeposit.utxovout);
LP_availableset(swap->bobpayment.utxotxid,swap->bobpayment.utxovout);
}
else
{
LP_availableset(swap->alicepayment.utxotxid,swap->alicepayment.utxovout);
LP_availableset(swap->myfee.utxotxid,swap->myfee.utxovout);
}
}
// save to permanent storage
basilisk_rawtx_purge(&swap->bobdeposit);
basilisk_rawtx_purge(&swap->bobpayment);
@ -139,11 +159,11 @@ void basilisk_swap_finished(struct basilisk_swap *swap)
basilisk_rawtx_purge(&swap->bobspend);
basilisk_rawtx_purge(&swap->bobrefund);
basilisk_rawtx_purge(&swap->alicereclaim);
for (i=0; i<swap->nummessages; i++)
/*for (i=0; i<swap->nummessages; i++)
if ( swap->messages[i].data != 0 )
free(swap->messages[i].data), swap->messages[i].data = 0;
free(swap->messages), swap->messages = 0;
swap->nummessages = 0;
swap->nummessages = 0;*/
if ( swap->N.pair >= 0 )
nn_close(swap->N.pair), swap->N.pair = -1;
}
@ -177,6 +197,8 @@ 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;
datalen += iguana_rwnum(1,&data[datalen],sizeof(swap->I.req.requestid),&swap->I.req.requestid);
datalen += iguana_rwnum(1,&data[datalen],sizeof(swap->I.req.quoteid),&swap->I.req.quoteid);
data[datalen++] = swap->I.aliceconfirms;
data[datalen++] = swap->I.bobconfirms;
data[datalen++] = swap->I.alicemaxconfirms;
@ -186,14 +208,22 @@ int32_t LP_pubkeys_data(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
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]);
printf("send >>>>>>>>> r.%u q.%u datalen.%d\n",swap->I.req.requestid,swap->I.req.quoteid,datalen);
return(datalen);
}
int32_t LP_pubkeys_verify(struct basilisk_swap *swap,uint8_t *data,int32_t datalen)
{
int32_t i,nonz=0,alicemaxconfirms,bobmaxconfirms,aliceconfirms,bobconfirms,len = 0; uint8_t other33[33];
if ( datalen == sizeof(swap->otherdeck)+38 )
uint32_t requestid,quoteid; int32_t i,nonz=0,alicemaxconfirms,bobmaxconfirms,aliceconfirms,bobconfirms,len = 0; uint8_t other33[33];
if ( datalen == sizeof(swap->otherdeck)+38+sizeof(uint32_t)*2 )
{
len += iguana_rwnum(0,&data[len],sizeof(requestid),&requestid);
len += iguana_rwnum(0,&data[len],sizeof(quoteid),&quoteid);
if ( requestid != swap->I.req.requestid || quoteid != swap->I.req.quoteid )
{
printf("SWAP requestid.%u quoteid.%u mismatch received r.%u q.%u\n",swap->I.req.requestid,swap->I.req.quoteid,requestid,quoteid);
return(-1);
}
aliceconfirms = data[len++];
bobconfirms = data[len++];
alicemaxconfirms = data[len++];
@ -220,7 +250,7 @@ int32_t LP_pubkeys_verify(struct basilisk_swap *swap,uint8_t *data,int32_t datal
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("mutually trusted swap, 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);
@ -233,7 +263,7 @@ int32_t LP_pubkeys_verify(struct basilisk_swap *swap,uint8_t *data,int32_t datal
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)+36);
printf("pubkeys verify size mismatch %d != %d\n",datalen,(int32_t)(sizeof(swap->otherdeck)+38+sizeof(uint32_t)*2));
return(-1);
}
@ -262,7 +292,7 @@ int32_t LP_choosei_data(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
int32_t LP_choosei_verify(struct basilisk_swap *swap,uint8_t *data,int32_t datalen)
{
int32_t otherchoosei=-1,i,len = 0; uint8_t pubkey33[33]; char str[65],str2[65];
int32_t otherchoosei=-1,i,len = 0; uint8_t pubkey33[33];
if ( datalen == sizeof(otherchoosei)+sizeof(bits256)*2 )
{
len += iguana_rwnum(0,data,sizeof(otherchoosei),&otherchoosei);
@ -275,13 +305,13 @@ int32_t LP_choosei_verify(struct basilisk_swap *swap,uint8_t *data,int32_t datal
swap->I.pubA0.bytes[i] = data[len++];
for (i=0; i<32; i++)
swap->I.pubA1.bytes[i] = data[len++];
printf("GOT pubA0/1 %s\n",bits256_str(str,swap->I.pubA0));
//printf("GOT pubA0/1 %s\n",bits256_str(str,swap->I.pubA0));
swap->I.privBn = swap->privkeys[swap->I.otherchoosei];
memset(&swap->privkeys[swap->I.otherchoosei],0,sizeof(swap->privkeys[swap->I.otherchoosei]));
revcalc_rmd160_sha256(swap->I.secretBn,swap->I.privBn);//.bytes,sizeof(swap->privBn));
vcalc_sha256(0,swap->I.secretBn256,swap->I.privBn.bytes,sizeof(swap->I.privBn));
swap->I.pubBn = bitcoin_pubkey33(swap->ctx,pubkey33,swap->I.privBn);
printf("set privBn.%s %s\n",bits256_str(str,swap->I.privBn),bits256_str(str2,*(bits256 *)swap->I.secretBn256));
//printf("set privBn.%s %s\n",bits256_str(str,swap->I.privBn),bits256_str(str2,*(bits256 *)swap->I.secretBn256));
//basilisk_bobscripts_set(swap,1,1);
}
else
@ -290,18 +320,18 @@ int32_t LP_choosei_verify(struct basilisk_swap *swap,uint8_t *data,int32_t datal
swap->I.pubB0.bytes[i] = data[len++];
for (i=0; i<32; i++)
swap->I.pubB1.bytes[i] = data[len++];
printf("GOT pubB0/1 %s\n",bits256_str(str,swap->I.pubB0));
//printf("GOT pubB0/1 %s\n",bits256_str(str,swap->I.pubB0));
swap->I.privAm = swap->privkeys[swap->I.otherchoosei];
memset(&swap->privkeys[swap->I.otherchoosei],0,sizeof(swap->privkeys[swap->I.otherchoosei]));
revcalc_rmd160_sha256(swap->I.secretAm,swap->I.privAm);//.bytes,sizeof(swap->privAm));
vcalc_sha256(0,swap->I.secretAm256,swap->I.privAm.bytes,sizeof(swap->I.privAm));
swap->I.pubAm = bitcoin_pubkey33(swap->ctx,pubkey33,swap->I.privAm);
printf("set privAm.%s %s\n",bits256_str(str,swap->I.privAm),bits256_str(str2,*(bits256 *)swap->I.secretAm256));
//printf("set privAm.%s %s\n",bits256_str(str,swap->I.privAm),bits256_str(str2,*(bits256 *)swap->I.secretAm256));
swap->bobdeposit.I.pubkey33[0] = 2;
swap->bobpayment.I.pubkey33[0] = 2;
for (i=0; i<32; i++)
swap->bobpayment.I.pubkey33[i+1] = swap->bobdeposit.I.pubkey33[i+1] = swap->I.pubA0.bytes[i];
printf("SET bobdeposit pubkey33.(02%s)\n",bits256_str(str,swap->I.pubA0));
//printf("SET bobdeposit pubkey33.(02%s)\n",bits256_str(str,swap->I.pubA0));
//basilisk_bobscripts_set(swap,0);
}
return(0);
@ -556,7 +586,12 @@ struct basilisk_rawtx *LP_swapdata_rawtx(struct basilisk_swap *swap,uint8_t *dat
int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys)
{
bits256 otherhash,myhash,txid; int64_t txfee; int32_t i,offset=0,datalen=0,retval=-1,hexlen,n; uint8_t *data; cJSON *txobj,*skey,*vouts,*vout; char *hexstr,redeemaddr[64],checkaddr[64]; uint32_t quoteid,msgbits;
bits256 otherhash,myhash,txid; int64_t txfee,val; int32_t i,offset=0,datalen=0,retval=-1,hexlen,n; uint8_t *data; cJSON *txobj,*skey,*vouts,*vout; char *hexstr,redeemaddr[64],checkaddr[64]; uint32_t quoteid,msgbits; struct iguana_info *coin;
if ( (coin= LP_coinfind(rawtx->symbol)) == 0 )
{
printf("LP_rawtx_spendscript couldnt find coin.(%s)\n",rawtx->symbol);
return(-1);
}
for (i=0; i<32; i++)
otherhash.bytes[i] = recvbuf[offset++];
for (i=0; i<32; i++)
@ -577,9 +612,9 @@ int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct ba
memcpy(rawtx->redeemscript,&data[datalen],rawtx->I.redeemlen);
//for (i=0; i<rawtx->I.redeemlen; i++)
// printf("%02x",rawtx->redeemscript[i]);
bitcoin_address(redeemaddr,rawtx->coin->taddr,rawtx->coin->p2shtype,rawtx->redeemscript,rawtx->I.redeemlen);
//printf(" received redeemscript.(%s) %s taddr.%d\n",redeemaddr,rawtx->coin->symbol,rawtx->coin->taddr);
LP_swap_coinaddr(rawtx->coin,checkaddr,0,data,datalen,0);
bitcoin_address(redeemaddr,coin->taddr,coin->p2shtype,rawtx->redeemscript,rawtx->I.redeemlen);
//printf(" received redeemscript.(%s) %s taddr.%d\n",redeemaddr,coin->symbol,coin->taddr);
LP_swap_coinaddr(coin,checkaddr,0,data,datalen,0);
if ( strcmp(redeemaddr,checkaddr) != 0 )
{
printf("REDEEMADDR MISMATCH??? %s != %s\n",redeemaddr,checkaddr);
@ -609,24 +644,27 @@ int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct ba
char str[65]; printf("rawtx.%s txid %s\n",rawtx->name,bits256_str(str,txid));
if ( bits256_cmp(txid,rawtx->I.actualtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 )
rawtx->I.actualtxid = txid;
if ( (txobj= bitcoin_data2json(rawtx->coin->taddr,rawtx->coin->pubtype,rawtx->coin->p2shtype,rawtx->coin->isPoS,height,&rawtx->I.signedtxid,&rawtx->msgtx,rawtx->extraspace,sizeof(rawtx->extraspace),data,datalen,0,suppress_pubkeys,rawtx->coin->zcash)) != 0 )
if ( (txobj= bitcoin_data2json(coin->symbol,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,height,&rawtx->I.signedtxid,&rawtx->msgtx,rawtx->extraspace,sizeof(rawtx->extraspace),data,datalen,0,suppress_pubkeys,coin->zcash)) != 0 )
{
rawtx->I.actualtxid = rawtx->I.signedtxid;
rawtx->I.locktime = rawtx->msgtx.lock_time;
if ( (vouts= jarray(&n,txobj,"vout")) != 0 && v < n )
{
vout = jitem(vouts,v);
if ( strcmp("BTC",rawtx->coin->symbol) == 0 && rawtx == &swap->otherfee )
if ( strcmp("BTC",coin->symbol) == 0 && rawtx == &swap->otherfee )
txfee = LP_MIN_TXFEE;
else
{
if ( strcmp(rawtx->coin->symbol,swap->bobcoin.symbol) == 0 )
if ( strcmp(coin->symbol,swap->I.bobstr) == 0 )
txfee = swap->I.Btxfee;
else if ( strcmp(rawtx->coin->symbol,swap->alicecoin.symbol) == 0 )
else if ( strcmp(coin->symbol,swap->I.alicestr) == 0 )
txfee = swap->I.Atxfee;
else txfee = LP_MIN_TXFEE;
}
if ( j64bits(vout,"satoshis") >= rawtx->I.amount && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 )
if ( rawtx->I.amount > 2*txfee)
val = rawtx->I.amount-2*txfee;
else val = 1;
if ( j64bits(vout,"satoshis") >= val && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 )
{
if ( (hexlen= (int32_t)strlen(hexstr) >> 1) < sizeof(rawtx->spendscript) )
{
@ -638,9 +676,9 @@ int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct ba
if ( rawtx == &swap->otherfee )
{
char str[65];
LP_swap_coinaddr(rawtx->coin,rawtx->p2shaddr,0,data,datalen,0);
LP_swap_coinaddr(coin,rawtx->p2shaddr,0,data,datalen,0);
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 bitcoin_address(rawtx->p2shaddr,coin->taddr,coin->p2shtype,rawtx->spendscript,hexlen);
}
} 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));
}
@ -656,7 +694,7 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3
{
if ( bits256_nonz(rawtx->I.signedtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 )
{
rawtx->I.actualtxid = LP_broadcast_tx(rawtx->name,rawtx->coin->symbol,rawtx->txbytes,rawtx->I.datalen);
rawtx->I.actualtxid = LP_broadcast_tx(rawtx->name,rawtx->symbol,rawtx->txbytes,rawtx->I.datalen);
if ( bits256_cmp(rawtx->I.actualtxid,rawtx->I.signedtxid) != 0 )
{
char str[65],str2[65];
@ -684,7 +722,7 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3
if ( suppress_swapsend == 0 )
{
retval = LP_swapsend(pairsock,swap,msgbits,sendbuf,sendlen,nextbits,rawtx->I.crcs);
if ( LP_waitmempool(rawtx->coin->symbol,rawtx->I.destaddr,rawtx->I.signedtxid,0,LP_SWAPSTEP_TIMEOUT*10) < 0 )
if ( LP_waitmempool(rawtx->symbol,rawtx->I.destaddr,rawtx->I.signedtxid,0,LP_SWAPSTEP_TIMEOUT*10) < 0 )
{
char str[65]; printf("failed to find %s %s %s in the mempool?\n",rawtx->name,rawtx->I.destaddr,bits256_str(str,rawtx->I.actualtxid));
retval = -1;
@ -704,22 +742,25 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3
return(0);
}
int32_t LP_swapwait(uint32_t requestid,uint32_t quoteid,int32_t duration,int32_t sleeptime)
int32_t LP_swapwait(struct basilisk_swap *swap,uint32_t requestid,uint32_t quoteid,int32_t duration,int32_t sleeptime)
{
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);
sleep(sleeptime/3);
//if ( sleeptime < divisor*60 )
// sleeptime = divisor * 60;
while ( time(NULL) < expiration )
{
if ( (retstr= basilisk_swapentry(requestid,quoteid)) != 0 )
if ( (retstr= basilisk_swapentry(requestid,quoteid,1)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( jstr(retjson,"status") != 0 && strcmp(jstr(retjson,"status"),"finished") == 0 )
{
swap->I.finished = (uint32_t)time(NULL);
break;
else printf("NOT FINISHED.(%s)\n",jprint(retjson,0));
}
//else printf("NOT FINISHED.(%s)\n",jprint(retjson,0));
free_json(retjson);
retjson = 0;
}
@ -734,7 +775,7 @@ int32_t LP_swapwait(uint32_t requestid,uint32_t quoteid,int32_t duration,int32_t
{
printf("\n>>>>>>>>>>>>>>>>>>>>>>>>>\nSWAP completed! %u-%u %s\n",requestid,quoteid,jprint(retjson,0));
free_json(retjson);
if ( (retstr= basilisk_swapentry(requestid,quoteid)) != 0 )
if ( 0 && (retstr= basilisk_swapentry(requestid,quoteid,1)) != 0 )
{
printf("second call.(%s)\n",retstr);
free(retstr);
@ -753,7 +794,7 @@ void LP_bobloop(void *_swap)
expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT;
if ( swap != 0 )
{
if ( LP_waitsend("pubkeys",60,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 )
if ( LP_waitsend("pubkeys",120,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 )
printf("error waitsend pubkeys\n");
else if ( LP_waitsend("choosei",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 )
printf("error waitsend choosei\n");
@ -768,6 +809,7 @@ void LP_bobloop(void *_swap)
basilisk_bobdeposit_refund(swap,swap->I.putduration);
//printf("depositlen.%d\n",swap->bobdeposit.I.datalen);
LP_swapsfp_update(&swap->I.req);
LP_swap_critical = (uint32_t)time(NULL);
if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT*10,LP_verify_otherfee) < 0 )
printf("error waiting for alicefee\n");
else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x200,data,maxlen,&swap->bobdeposit,0x100,0) == 0 )
@ -776,36 +818,41 @@ void LP_bobloop(void *_swap)
printf("error waiting for alicepayment\n");
else
{
LP_swap_critical = (uint32_t)time(NULL);
if ( basilisk_bobscripts_set(swap,0,1) < 0 )
printf("error bobscripts payment\n");
else
{
if ( strcmp(swap->alicecoin.symbol,"BTC") == 0 )
if ( strcmp(swap->I.alicestr,"BTC") == 0 )
m = 0;
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
while ( (n= LP_numconfirms(swap->I.alicestr,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,m,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid));
LP_swap_critical = (uint32_t)time(NULL);
char str[65];printf("%d wait for alicepayment %s numconfs.%d %s %s\n",n,swap->alicepayment.I.destaddr,m,swap->I.alicestr,bits256_str(str,swap->alicepayment.I.signedtxid));
sleep(10);
}
LP_swap_critical = (uint32_t)time(NULL);
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->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,30);
LP_swap_endcritical = (uint32_t)time(NULL);
LP_swapwait(swap,swap->I.req.requestid,swap->I.req.quoteid,LP_atomic_locktime(swap->I.bobstr,swap->I.alicestr)*2,swap->I.aliceconfirms == 0 ? 3 : 30);
}
}
}
basilisk_swap_finished(swap);
//free(swap);
} else printf("swap timed out\n");
G.LP_pendingswaps--;
basilisk_swap_finished(swap);
free(swap);
free(data);
}
void LP_aliceloop(void *_swap)
@ -818,7 +865,7 @@ void LP_aliceloop(void *_swap)
if ( swap != 0 )
{
printf("start swap iamalice pair.%d\n",swap->N.pair);
if ( LP_sendwait("pubkeys",60,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 )
if ( LP_sendwait("pubkeys",120,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 )
printf("error LP_sendwait pubkeys\n");
else if ( LP_sendwait("choosei",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 )
printf("error LP_sendwait choosei\n");
@ -829,55 +876,66 @@ void LP_aliceloop(void *_swap)
else
{
LP_swapsfp_update(&swap->I.req);
LP_swap_critical = (uint32_t)time(NULL);
if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x80,data,maxlen,&swap->myfee,0x40,0) == 0 )
printf("error sending alicefee\n");
else if ( LP_waitfor(swap->N.pair,swap,1800,LP_verify_bobdeposit) < 0 )
printf("error waiting for bobdeposit\n");
else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0) == 0 )
printf("error sending alicepayment\n");
else
{
if ( strcmp(swap->alicecoin.symbol,"BTC") == 0 )
if ( strcmp(swap->I.bobstr,"BTC") == 0 )
m = 0;
else m = swap->I.aliceconfirms;
while ( (n= LP_numconfirms(swap->alicecoin.symbol,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,1)) < m )
else m = swap->I.bobconfirms;
while ( (n= LP_numconfirms(swap->I.bobstr,swap->bobdeposit.I.destaddr,swap->bobdeposit.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,m,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid));
LP_swap_critical = (uint32_t)time(NULL);
char str[65];printf("%d wait for bobdeposit %s numconfs.%d %s %s\n",n,swap->bobdeposit.I.destaddr,m,swap->I.bobstr,bits256_str(str,swap->bobdeposit.I.signedtxid));
sleep(10);
}
swap->sentflag = 1;
if ( LP_waitfor(swap->N.pair,swap,1800,LP_verify_bobpayment) < 0 )
printf("error waiting for bobpayment\n");
if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0) == 0 )
printf("error sending alicepayment\n");
else
{
while ( (n= LP_numconfirms(swap->bobcoin.symbol,swap->bobpayment.I.destaddr,swap->bobpayment.I.signedtxid,0,1)) < swap->I.bobconfirms )
if ( strcmp(swap->I.alicestr,"BTC") == 0 )
m = 0;
else m = swap->I.aliceconfirms;
while ( (n= LP_numconfirms(swap->I.alicestr,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,1)) < m )
{
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));
LP_swap_critical = (uint32_t)time(NULL);
char str[65];printf("%d wait for alicepayment %s numconfs.%d %s %s\n",n,swap->alicepayment.I.destaddr,m,swap->I.alicestr,bits256_str(str,swap->alicepayment.I.signedtxid));
sleep(10);
}
/*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 )
//swap->sentflag = 1;
LP_swap_critical = (uint32_t)time(NULL);
if ( LP_waitfor(swap->N.pair,swap,1800,LP_verify_bobpayment) < 0 )
printf("error waiting for bobpayment\n");
else
{
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,30);
LP_swap_endcritical = (uint32_t)time(NULL);
while ( (n= LP_numconfirms(swap->I.bobstr,swap->bobpayment.I.destaddr,swap->bobpayment.I.signedtxid,0,1)) < swap->I.bobconfirms )
{
char str[65];printf("%d wait for bobpayment %s numconfs.%d %s %s\n",n,swap->bobpayment.I.destaddr,swap->I.bobconfirms,swap->I.bobstr,bits256_str(str,swap->bobpayment.I.signedtxid));
sleep(10);
}
/*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->I.alicestr,swap->alicespend.I.destaddr,swap->alicespend.I.signedtxid,0,1)) < swap->I.aliceconfirms )
{
char str[65];printf("%d wait for alicespend %s numconfs.%d %s %s\n",n,swap->alicespend.I.destaddr,swap->I.aliceconfirms,swap->I.bobstr,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_swap_endcritical = (uint32_t)time(NULL);
LP_swapwait(swap,swap->I.req.requestid,swap->I.req.quoteid,LP_atomic_locktime(swap->I.bobstr,swap->I.alicestr)*2,swap->I.aliceconfirms == 0 ? 3 : 30);
}
}
}
}
}
free(data);
if ( swap->N.pair >= 0 )
{
nn_close(swap->N.pair);
swap->N.pair = -1;
}
basilisk_swap_finished(swap);
printf("finish swap.%p\n",swap);
//free(swap);
free(swap);
G.LP_pendingswaps--;
}
@ -965,8 +1023,8 @@ void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx *
numconfirms = 0;
#endif
strcpy(rawtx->name,name);
rawtx->coin = coin;
strcpy(rawtx->I.coinstr,coin->symbol);
printf("set coin.%s %s -> %s\n",coin->symbol,coin->smartaddr,name);
strcpy(rawtx->symbol,coin->symbol);
rawtx->I.numconfirms = numconfirms;
if ( (rawtx->I.amount= satoshis) < LP_MIN_TXFEE )
rawtx->I.amount = LP_MIN_TXFEE;
@ -977,13 +1035,13 @@ void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx *
if ( strcmp(coin->symbol,"BTC") == 0 && (quoteid % 10) == 0 )
decode_hex(rawtx->I.rmd160,20,TIERNOLAN_RMD160);
else decode_hex(rawtx->I.rmd160,20,INSTANTDEX_RMD160);
bitcoin_address(rawtx->I.destaddr,rawtx->coin->taddr,rawtx->coin->pubtype,rawtx->I.rmd160,20);
bitcoin_address(rawtx->I.destaddr,coin->taddr,coin->pubtype,rawtx->I.rmd160,20);
}
if ( pubkey33 != 0 )
{
memcpy(rawtx->I.pubkey33,pubkey33,33);
bitcoin_address(rawtx->I.destaddr,rawtx->coin->taddr,rawtx->coin->pubtype,rawtx->I.pubkey33,33);
bitcoin_addr2rmd160(rawtx->coin->taddr,&rawtx->I.addrtype,rawtx->I.rmd160,rawtx->I.destaddr);
bitcoin_address(rawtx->I.destaddr,coin->taddr,coin->pubtype,rawtx->I.pubkey33,33);
bitcoin_addr2rmd160(coin->taddr,&rawtx->I.addrtype,rawtx->I.rmd160,rawtx->I.destaddr);
}
if ( rawtx->I.vouttype <= 1 && rawtx->I.destaddr[0] != 0 )
{
@ -992,26 +1050,54 @@ void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx *
} else printf("%s vouttype.%d destaddr.(%s)\n",name,rawtx->I.vouttype,rawtx->I.destaddr);
}
struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 pubkey25519,struct basilisk_swap *swap,int32_t optionduration,uint32_t statebits,struct LP_quoteinfo *qp)
struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 pubkey25519,struct basilisk_swap *swap,int32_t optionduration,uint32_t statebits,struct LP_quoteinfo *qp,int32_t dynamictrust)
{
//FILE *fp; char fname[512];
uint8_t *alicepub33=0,*bobpub33=0; int32_t jumblrflag=-2,x = -1; struct iguana_info *coin;
swap->I.Atxfee = qp->desttxfee;
swap->I.Btxfee = qp->txfee;
swap->I.putduration = swap->I.callduration = INSTANTDEX_LOCKTIME;
uint8_t *alicepub33=0,*bobpub33=0; int32_t jumblrflag=-2,x = -1; struct iguana_info *bobcoin,*alicecoin;
strcpy(swap->I.bobstr,swap->I.req.src);
strcpy(swap->I.alicestr,swap->I.req.dest);
if ( (alicecoin= LP_coinfind(swap->I.alicestr)) == 0 )
{
printf("missing alicecoin src.%p dest.%p\n",LP_coinfind(swap->I.req.src),LP_coinfind(swap->I.req.dest));
free(swap);
return(0);
}
if ( (bobcoin= LP_coinfind(swap->I.bobstr)) == 0 )
{
printf("missing bobcoin src.%p dest.%p\n",LP_coinfind(swap->I.req.src),LP_coinfind(swap->I.req.dest));
free(swap);
return(0);
}
if ( (swap->I.Atxfee= qp->desttxfee) < 0 )
{
printf("bitcoin_swapinit %s Atxfee %.8f rejected\n",swap->I.req.dest,dstr(swap->I.Atxfee));
return(0);
}
if ( (swap->I.Btxfee= qp->txfee) < 0 )
{
printf("bitcoin_swapinit %s Btxfee %.8f rejected\n",swap->I.req.src,dstr(swap->I.Btxfee));
return(0);
}
swap->I.putduration = swap->I.callduration = LP_atomic_locktime(swap->I.bobstr,swap->I.alicestr);
if ( optionduration < 0 )
swap->I.putduration -= optionduration;
else if ( optionduration > 0 )
swap->I.callduration += optionduration;
swap->I.bobsatoshis = swap->I.req.srcamount;
swap->I.alicesatoshis = swap->I.req.destamount;
if ( (swap->I.bobsatoshis= swap->I.req.srcamount) <= 0 )
{
printf("bitcoin_swapinit %s bobsatoshis %.8f rejected\n",swap->I.req.src,dstr(swap->I.bobsatoshis));
return(0);
}
if ( (swap->I.alicesatoshis= swap->I.req.destamount) <= 0 )
{
printf("bitcoin_swapinit %s alicesatoshis %.8f rejected\n",swap->I.req.dest,dstr(swap->I.alicesatoshis));
return(0);
}
if ( (swap->I.bobinsurance= (swap->I.bobsatoshis / INSTANTDEX_INSURANCEDIV)) < LP_MIN_TXFEE )
swap->I.bobinsurance = LP_MIN_TXFEE;
if ( (swap->I.aliceinsurance= (swap->I.alicesatoshis / INSTANTDEX_INSURANCEDIV)) < LP_MIN_TXFEE )
swap->I.aliceinsurance = LP_MIN_TXFEE;
strcpy(swap->I.bobstr,swap->I.req.src);
strcpy(swap->I.alicestr,swap->I.req.dest);
swap->I.started = (uint32_t)time(NULL);
swap->I.started = qp->timestamp;//(uint32_t)time(NULL);
swap->I.expiration = swap->I.req.timestamp + swap->I.putduration + swap->I.callduration;
OS_randombytes((uint8_t *)&swap->I.choosei,sizeof(swap->I.choosei));
if ( swap->I.choosei < 0 )
@ -1024,42 +1110,30 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256
swap->I.iambob = 0;
swap->I.otherhash = swap->I.req.desthash;
swap->I.aliceistrusted = 1;
swap->I.otheristrusted = swap->I.bobistrusted = LP_pubkey_istrusted(swap->I.req.srchash);
if ( dynamictrust == 0 && LP_pubkey_istrusted(swap->I.req.srchash) != 0 )
dynamictrust = 1;
swap->I.otheristrusted = swap->I.bobistrusted = dynamictrust;
}
else
{
swap->I.iambob = 1;
swap->I.otherhash = swap->I.req.srchash;
swap->I.bobistrusted = 1;
swap->I.otheristrusted = swap->I.aliceistrusted = LP_pubkey_istrusted(swap->I.req.desthash);
if ( dynamictrust == 0 && LP_pubkey_istrusted(swap->I.req.desthash) != 0 )
dynamictrust = 1;
swap->I.otheristrusted = swap->I.aliceistrusted = dynamictrust;
}
if ( bits256_nonz(privkey) == 0 || (x= instantdex_pubkeyargs(swap,2 + INSTANTDEX_DECKSIZE,privkey,swap->I.orderhash,0x02+swap->I.iambob)) != 2 + INSTANTDEX_DECKSIZE )
{
char str[65]; printf("couldnt generate privkeys %d %s\n",x,bits256_str(str,privkey));
return(0);
}
if ( (coin= LP_coinfind(swap->I.alicestr)) != 0 )
swap->alicecoin = *coin;
else
{
printf("missing bobcoin.%p or missing alicecoin.%p src.%p dest.%p\n",&swap->bobcoin,&swap->alicecoin,LP_coinfind(swap->I.req.src),LP_coinfind(swap->I.req.dest));
free(swap);
return(0);
}
if ( (coin= LP_coinfind(swap->I.bobstr)) != 0 )
swap->bobcoin = *coin;
else
{
printf("missing bobcoin.%p or missing alicecoin.%p src.%p dest.%p\n",&swap->bobcoin,&swap->alicecoin,LP_coinfind(swap->I.req.src),LP_coinfind(swap->I.req.dest));
free(swap);
return(0);
}
if ( strcmp("BTC",swap->bobcoin.symbol) == 0 )
if ( strcmp("BTC",swap->I.bobstr) == 0 )
{
swap->I.bobconfirms = (1 + sqrt(dstr(swap->I.bobsatoshis) * .1));
swap->I.aliceconfirms = BASILISK_DEFAULT_NUMCONFIRMS;
}
else if ( strcmp("BTC",swap->alicecoin.symbol) == 0 )
else if ( strcmp("BTC",swap->I.alicestr) == 0 )
{
swap->I.aliceconfirms = (1 + sqrt(dstr(swap->I.alicesatoshis) * .1));
swap->I.bobconfirms = BASILISK_DEFAULT_NUMCONFIRMS;
@ -1069,17 +1143,17 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256
swap->I.bobconfirms = BASILISK_DEFAULT_NUMCONFIRMS;
swap->I.aliceconfirms = BASILISK_DEFAULT_NUMCONFIRMS;
}
if ( swap->bobcoin.isassetchain != 0 )
if ( bobcoin->isassetchain != 0 )
swap->I.bobconfirms = 1;
if ( swap->alicecoin.isassetchain != 0 )
if ( 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 )
if ( bobcoin->userconfirms > 0 )
swap->I.bobconfirms = bobcoin->userconfirms;
if ( alicecoin->userconfirms > 0 )
swap->I.aliceconfirms = alicecoin->userconfirms;
if ( (swap->I.bobmaxconfirms= bobcoin->maxconfirms) == 0 )
swap->I.bobmaxconfirms = BASILISK_DEFAULT_MAXCONFIRMS;
if ( (swap->I.alicemaxconfirms= swap->alicecoin.maxconfirms) == 0 )
if ( (swap->I.alicemaxconfirms= alicecoin->maxconfirms) == 0 )
swap->I.alicemaxconfirms = BASILISK_DEFAULT_MAXCONFIRMS;
if ( swap->I.bobconfirms > swap->I.bobmaxconfirms )
swap->I.bobconfirms = swap->I.bobmaxconfirms;
@ -1087,57 +1161,57 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256
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);
printf(">>>>>>>>>> jumblrflag.%d <<<<<<<<< r.%u q.%u, %.8f bobconfs.%d, %.8f aliceconfs.%d taddr.%d %d\n",jumblrflag,swap->I.req.requestid,swap->I.req.quoteid,dstr(swap->I.bobsatoshis),swap->I.bobconfirms,dstr(swap->I.alicesatoshis),swap->I.aliceconfirms,bobcoin->taddr,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) + 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);
basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,bobcoin,0,0,LP_DEXFEE(swap->I.bobsatoshis) + 0*bobcoin->txfee,0,0,jumblrflag);
basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,alicecoin,0,0,LP_DEXFEE(swap->I.alicesatoshis) + 0*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) + 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);
basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,bobcoin,0,0,LP_DEXFEE(swap->I.bobsatoshis) + 0*bobcoin->txfee,0,0,jumblrflag);
basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,alicecoin,0,0,LP_DEXFEE(swap->I.alicesatoshis) + 0*alicecoin->txfee,0,0,jumblrflag);
alicepub33 = pubkey33;
}
swap->myfee.I.locktime = swap->I.started + 1;
swap->otherfee.I.locktime = swap->I.started + 1;
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);
basilisk_rawtx_setparms("bobrefund",swap->I.req.quoteid,&swap->bobrefund,&swap->bobcoin,1,4,LP_DEPOSITSATOSHIS(swap->I.bobsatoshis),1,bobpub33,jumblrflag);
basilisk_rawtx_setparms("bobdeposit",swap->I.req.quoteid,&swap->bobdeposit,bobcoin,swap->I.bobconfirms,0,LP_DEPOSITSATOSHIS(swap->I.bobsatoshis) + 2*bobcoin->txfee,4,0,jumblrflag);
basilisk_rawtx_setparms("bobrefund",swap->I.req.quoteid,&swap->bobrefund,bobcoin,1,4,LP_DEPOSITSATOSHIS(swap->I.bobsatoshis),1,bobpub33,jumblrflag);
swap->bobrefund.I.suppress_pubkeys = 1;
basilisk_rawtx_setparms("aliceclaim",swap->I.req.quoteid,&swap->aliceclaim,&swap->bobcoin,1,4,LP_DEPOSITSATOSHIS(swap->I.bobsatoshis),1,alicepub33,jumblrflag);
basilisk_rawtx_setparms("aliceclaim",swap->I.req.quoteid,&swap->aliceclaim,bobcoin,1,4,LP_DEPOSITSATOSHIS(swap->I.bobsatoshis),1,alicepub33,jumblrflag);
swap->aliceclaim.I.suppress_pubkeys = 1;
swap->aliceclaim.I.locktime = swap->I.started + swap->I.putduration+swap->I.callduration + 1;
basilisk_rawtx_setparms("bobpayment",swap->I.req.quoteid,&swap->bobpayment,&swap->bobcoin,swap->I.bobconfirms,0,swap->I.bobsatoshis + swap->bobcoin.txfee,3,0,jumblrflag);
basilisk_rawtx_setparms("alicespend",swap->I.req.quoteid,&swap->alicespend,&swap->bobcoin,swap->I.bobconfirms,3,swap->I.bobsatoshis,1,alicepub33,jumblrflag);
basilisk_rawtx_setparms("bobpayment",swap->I.req.quoteid,&swap->bobpayment,bobcoin,swap->I.bobconfirms,0,swap->I.bobsatoshis + 2*bobcoin->txfee,3,0,jumblrflag);
basilisk_rawtx_setparms("alicespend",swap->I.req.quoteid,&swap->alicespend,bobcoin,swap->I.bobconfirms,3,swap->I.bobsatoshis,1,alicepub33,jumblrflag);
swap->alicespend.I.suppress_pubkeys = 1;
basilisk_rawtx_setparms("bobreclaim",swap->I.req.quoteid,&swap->bobreclaim,&swap->bobcoin,swap->I.bobconfirms,3,swap->I.bobsatoshis,1,bobpub33,jumblrflag);
basilisk_rawtx_setparms("bobreclaim",swap->I.req.quoteid,&swap->bobreclaim,bobcoin,swap->I.bobconfirms,3,swap->I.bobsatoshis,1,bobpub33,jumblrflag);
swap->bobreclaim.I.suppress_pubkeys = 1;
swap->bobreclaim.I.locktime = swap->I.started + swap->I.putduration + 1;
basilisk_rawtx_setparms("alicepayment",swap->I.req.quoteid,&swap->alicepayment,&swap->alicecoin,swap->I.aliceconfirms,0,swap->I.alicesatoshis+swap->alicecoin.txfee,2,0,jumblrflag);
basilisk_rawtx_setparms("bobspend",swap->I.req.quoteid,&swap->bobspend,&swap->alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,bobpub33,jumblrflag);
basilisk_rawtx_setparms("alicepayment",swap->I.req.quoteid,&swap->alicepayment,alicecoin,swap->I.aliceconfirms,0,swap->I.alicesatoshis + 2*alicecoin->txfee,2,0,jumblrflag);
basilisk_rawtx_setparms("bobspend",swap->I.req.quoteid,&swap->bobspend,alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,bobpub33,jumblrflag);
swap->bobspend.I.suppress_pubkeys = 1;
basilisk_rawtx_setparms("alicereclaim",swap->I.req.quoteid,&swap->alicereclaim,&swap->alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,alicepub33,jumblrflag);
basilisk_rawtx_setparms("alicereclaim",swap->I.req.quoteid,&swap->alicereclaim,alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,alicepub33,jumblrflag);
swap->alicereclaim.I.suppress_pubkeys = 1;
swap->bobpayment.utxotxid = qp->txid, swap->bobpayment.utxovout = qp->vout;
swap->bobdeposit.utxotxid = qp->txid2, swap->bobdeposit.utxovout = qp->vout2;
swap->alicepayment.utxotxid = qp->desttxid, swap->alicepayment.utxovout = qp->destvout;
LP_mark_spent(swap->bobcoin.symbol,qp->txid,qp->vout);
LP_mark_spent(swap->bobcoin.symbol,qp->txid2,qp->vout2);
LP_mark_spent(swap->alicecoin.symbol,qp->desttxid,qp->destvout);
LP_mark_spent(swap->I.bobstr,qp->txid,qp->vout);
LP_mark_spent(swap->I.bobstr,qp->txid2,qp->vout2);
LP_mark_spent(swap->I.alicestr,qp->desttxid,qp->destvout);
if ( swap->I.iambob != 0 )
swap->otherfee.utxotxid = qp->feetxid, swap->otherfee.utxovout = qp->feevout;
else
{
swap->myfee.utxotxid = qp->feetxid, swap->myfee.utxovout = qp->feevout;
LP_mark_spent(swap->alicecoin.symbol,qp->feetxid,qp->feevout);
LP_mark_spent(swap->I.alicestr,qp->feetxid,qp->feevout);
}
char str[65],str2[65],str3[65]; printf("IAMBOB.%d %s %s %s\n",swap->I.iambob,bits256_str(str,qp->txid),bits256_str(str2,qp->txid2),bits256_str(str3,qp->feetxid));
char str[65],str2[65],str3[65]; printf("IAMBOB.%d %s %s %s [%s %s]\n",swap->I.iambob,bits256_str(str,qp->txid),bits256_str(str2,qp->txid2),bits256_str(str3,qp->feetxid),swap->I.bobstr,swap->I.alicestr);
return(swap);
}
struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp)
struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp,int32_t dynamictrust)
{
struct basilisk_swap *swap; bits256 pubkey25519; uint8_t pubkey33[33];
swap = calloc(1,sizeof(*swap));
@ -1149,14 +1223,14 @@ struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256
G.LP_skipstatus[G.LP_numskips] = ((uint64_t)rp->requestid << 32) | rp->quoteid;
if ( G.LP_numskips < sizeof(G.LP_skipstatus)/sizeof(*G.LP_skipstatus) )
G.LP_numskips++;
printf("basilisk_thread_start request.%u iambob.%d (%s/%s) quoteid.%u\n",rp->requestid,iambob,rp->src,rp->dest,rp->quoteid);
printf("LP_swapinit request.%u iambob.%d (%s/%s) quoteid.%u\n",rp->requestid,iambob,rp->src,rp->dest,rp->quoteid);
bitcoin_pubkey33(swap->ctx,pubkey33,privkey);
pubkey25519 = curve25519(privkey,curve25519_basepoint9());
swap->persistent_pubkey = pubkey25519;
swap->persistent_privkey = privkey;
memcpy(swap->persistent_pubkey33,pubkey33,33);
calc_rmd160_sha256(swap->changermd160,pubkey33,33);
if ( bitcoin_swapinit(privkey,pubkey33,pubkey25519,swap,optionduration,!iambob,qp) == 0 )
if ( bitcoin_swapinit(privkey,pubkey33,pubkey25519,swap,optionduration,!iambob,qp,dynamictrust) == 0 )
{
printf("error doing swapinit\n");
free(swap);

694
iguana/exchanges/LP_tradebots.c

@ -0,0 +1,694 @@
/******************************************************************************
* Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
//
// LP_tradebots.c
// marketmaker
//
#define TRADEBOTS_GAPTIME 120
#define LP_TRADEBOTS_MAXTRADES 10
struct LP_tradebot_trade
{
double maxprice,totalrelvolume,basevol,relvol;
uint64_t aliceid;
int32_t dispdir;
uint32_t started,finished,requestid,quoteid,tradeid,expired;
char base[65],rel[65],event[32];
};
struct LP_tradebot
{
struct LP_tradebot *next,*prev;
char name[128],base[65],rel[65];
int32_t numtrades,numpending,completed,dispdir;
double maxprice,totalrelvolume,totalbasevolume,basesum,relsum,pendbasesum,pendrelsum;
uint32_t lasttime,dead,pause,userpause,started,id;
struct LP_tradebot_trade *trades[LP_TRADEBOTS_MAXTRADES];
} *LP_tradebots;
void LP_tradebot_pauseall()
{
struct LP_tradebot *bot,*tmp;
DL_FOREACH_SAFE(LP_tradebots,bot,tmp)
{
bot->userpause = bot->pause = (uint32_t)time(NULL);
}
}
void LP_tradebot_updatestats(struct LP_tradebot *bot,struct LP_tradebot_trade *tp)
{
char *swapstr,*status; int32_t flag; cJSON *swapjson;
if ( (swapstr= basilisk_swapentry(tp->requestid,tp->quoteid,1)) != 0 )
{
flag = 0;
if ( (swapjson= cJSON_Parse(swapstr)) != 0 )
{
tp->basevol = dstr(j64bits(swapjson,"satoshis"));
tp->relvol = dstr(j64bits(swapjson,"destsatoshis"));
tp->aliceid = j64bits(swapjson,"aliceid");
if ( (status= jstr(swapjson,"status")) != 0 )
{
if ( strcmp(status,"finished") == 0 )
{
if ( tp->finished == 0 )
tp->finished = (uint32_t)time(NULL);
}
}
free_json(swapjson);
}
free(swapstr);
}
}
void LP_tradebot_calcstats(struct LP_tradebot *bot)
{
int32_t i; struct LP_tradebot_trade *tp;
bot->basesum = bot->relsum = bot->pendbasesum = bot->pendrelsum = 0.;
bot->numpending = bot->completed = 0;
for (i=0; i<bot->numtrades; i++)
{
if ( (tp= bot->trades[i]) == 0 )
continue;
if ( tp->finished == 0 && time(NULL) > tp->started+LP_atomic_locktime(bot->base,bot->rel)*2 )
{
tp->expired = tp->finished = (uint32_t)time(NULL);
printf("tradeid.%u expired\n",tp->tradeid);
}
if ( tp->finished != 0 )
{
if ( tp->expired == 0 )
{
bot->basesum += tp->basevol;
bot->relsum += tp->relvol;
bot->completed++;
}
}
else
{
if ( tp->requestid != 0 && tp->quoteid != 0 )
{
bot->pendbasesum += tp->basevol;
bot->pendrelsum += tp->relvol;
bot->numpending++;
}
}
//LP_tradebot_updatestats(bot,bot->trades[i]);
}
//printf("completed.%d (%.8f / %.8f) pending.%d (%.8f / %.8f)\n",bot->completed,bot->basesum,bot->relsum,bot->numpending,bot->pendbasesum,bot->pendrelsum);
}
double LP_pricevol_invert(double *basevolumep,double maxprice,double relvolume)
{
double price;
*basevolumep = 0.;
if ( maxprice > SMALLVAL && maxprice < SATOSHIDEN )
{
price = (1. / maxprice);
*basevolumep = (relvolume * price);
return(price);
}
return(0.);
}
cJSON *LP_tradebot_tradejson(struct LP_tradebot_trade *tp,int32_t dispflag)
{
double price,basevol; cJSON *item = cJSON_CreateObject();
if ( tp == 0 )
return(cJSON_Parse("{}"));
if ( tp->event[0] != 0 )
jaddstr(item,"status",tp->event);
if ( tp->requestid != 0 && tp->quoteid != 0 )
{
jaddnum(item,"requestid",tp->requestid);
jaddnum(item,"quoteid",tp->quoteid);
} else jaddnum(item,"tradeid",tp->tradeid);
if ( tp->aliceid != 0 )
jadd64bits(item,"aliceid",tp->aliceid);
if ( tp->basevol > SMALLVAL && tp->relvol > SMALLVAL )
{
if ( dispflag > 0 )
{
jaddnum(item,"price",tp->relvol/tp->basevol);
jaddnum(item,"volume",tp->relvol);
}
else
{
price = LP_pricevol_invert(&basevol,tp->relvol / tp->basevol,tp->relvol);
jaddnum(item,"price",price);
jaddnum(item,"volume",basevol);
}
}
return(item);
}
cJSON *LP_tradebot_json(struct LP_tradebot *bot)
{
int32_t i; double aveprice,basevolume,vol; cJSON *json,*array;
LP_tradebot_calcstats(bot);
json = cJSON_CreateObject();
jaddstr(json,"result","success");
jaddstr(json,"name",bot->name);
jaddnum(json,"botid",bot->id);
jaddnum(json,"started",bot->started);
if ( bot->pause != 0 || bot->userpause != 0 )
jaddnum(json,"paused",bot->userpause != 0 ? bot->userpause : bot->pause);
if ( bot->dead != 0 )
jaddnum(json,"stopped",bot->dead);
if ( bot->dispdir > 0 )
{
jaddstr(json,"action","buy");
jaddstr(json,"base",bot->base);
jaddstr(json,"rel",bot->rel);
jaddnum(json,"maxprice",bot->maxprice);
jaddnum(json,"totalrelvolume",bot->totalrelvolume);
jaddnum(json,"totalbasevolume",bot->totalbasevolume);
if ( (vol= bot->relsum) > SMALLVAL && bot->basesum > SMALLVAL )
{
jaddnum(json,"aveprice",vol/bot->basesum);
jaddnum(json,"volume",vol);
}
}
else
{
jaddstr(json,"action","sell");
jaddstr(json,"base",bot->rel);
jaddstr(json,"rel",bot->base);
aveprice = LP_pricevol_invert(&basevolume,bot->maxprice,bot->totalrelvolume);
jaddnum(json,"minprice",aveprice);
jaddnum(json,"totalbasevolume",bot->totalrelvolume);
jaddnum(json,"totalrelvolume",basevolume);
if ( (vol= bot->relsum) > SMALLVAL && bot->basesum > SMALLVAL )
{
aveprice = LP_pricevol_invert(&basevolume,vol/bot->basesum,vol);
jaddnum(json,"aveprice",aveprice);
jaddnum(json,"volume",basevolume);
}
}
array = cJSON_CreateArray();
for (i=0; i<bot->numtrades; i++)
jaddi(array,LP_tradebot_tradejson(bot->trades[i],bot->dispdir));
jadd(json,"trades",array);
if ( bot->basesum > SMALLVAL && bot->relsum > SMALLVAL && bot->completed > 0 )
{
jadd(json,"complete",bot->completed!=0?jtrue():jfalse());
jaddnum(json,"percentage",100. * (bot->relsum / bot->totalrelvolume));
if ( bot->dispdir > 0 )
{
jaddnum(json,"aveprice",bot->relsum / bot->basesum);
jaddnum(json,"volume",bot->relsum);
}
else
{
jaddnum(json,"aveprice",bot->basesum / bot->relsum);
jaddnum(json,"volume",bot->basesum);
}
}
if ( bot->pendbasesum > SMALLVAL && bot->pendrelsum > SMALLVAL && bot->numpending > 0 )
{
jaddnum(json,"pending",bot->numpending);
if ( bot->dispdir > 0 )
{
jaddnum(json,"pendingprice",bot->pendrelsum / bot->pendbasesum);
jaddnum(json,"pendingvolume",bot->pendrelsum);
}
else
{
jaddnum(json,"pendingprice",bot->pendbasesum / bot->pendrelsum);
jaddnum(json,"pendingvolume",bot->pendbasesum);
}
}
return(json);
}
struct LP_tradebot *_LP_tradebotfind(uint32_t botid)
{
struct LP_tradebot *tmp,*bot,*retbot = 0;
DL_FOREACH_SAFE(LP_tradebots,bot,tmp)
{
if ( botid == bot->id )
{
retbot = bot;
break;
}
}
return(retbot);
}
struct LP_tradebot *LP_tradebotfind(uint32_t botid)
{
struct LP_tradebot *retbot = 0;
portable_mutex_lock(&LP_tradebotsmutex);
retbot = _LP_tradebotfind(botid);
portable_mutex_unlock(&LP_tradebotsmutex);
return(retbot);
}
void LP_tradebotadd(struct LP_tradebot *bot)
{
portable_mutex_lock(&LP_tradebotsmutex);
while ( _LP_tradebotfind(bot->id) != 0 )
{
printf("BOT collision at %u, ok if rare\n",bot->id);
bot->id++;
}
DL_APPEND(LP_tradebots,bot);
portable_mutex_unlock(&LP_tradebotsmutex);
}
struct LP_tradebot_trade *LP_tradebot_pending(struct LP_tradebot *bot,cJSON *pending,uint32_t tradeid)
{
struct LP_tradebot_trade *tp;
tp = calloc(1,sizeof(*tp));
tp->tradeid = tradeid;
tp->maxprice = bot->maxprice;
tp->totalrelvolume = bot->totalrelvolume;
tp->started = (uint32_t)time(NULL);
tp->dispdir = bot->dispdir;
strcpy(tp->base,bot->base);
strcpy(tp->rel,bot->rel);
tp->aliceid = j64bits(pending,"aliceid");
tp->basevol = jdouble(pending,"basevalue");
tp->relvol = jdouble(pending,"relvalue");
printf("tradebot pending basevol %.8f relvol %.8f\n",tp->basevol,tp->relvol);
return(tp);
}
double LP_orderbook_maxrel(char *base,char *rel,double maxprice)
{
char *retstr; int32_t i,numasks; cJSON *retjson,*asks,*item; double maxvol,maxrel = 0.;
if ( (retstr= LP_orderbook(base,rel,0)) != 0 )
{
//printf("maxprice %.8f %s/%s\n",maxprice,base,rel);
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (asks= jarray(&numasks,retjson,"asks")) != 0 )
{
for (i=0; i<numasks; i++)
{
item = jitem(asks,i);
if ( jdouble(item,"price") > maxprice )
break;
maxvol = jdouble(item,"maxvolume");
//printf("(%s) -> %.8f\n",jprint(item,0),maxvol);
if ( maxvol > maxrel )
maxrel = maxvol;
}
}
free_json(retjson);
}
free(retstr);
}
return(maxrel);
}
void LP_tradebot_timeslice(void *ctx,struct LP_tradebot *bot)
{
double remaining,maxrel; struct LP_tradebot_trade *tp; int32_t i,maxiters = 10; uint32_t tradeid; bits256 destpubkey; char *retstr,*liststr; cJSON *retjson,*retjson2,*pending;
memset(destpubkey.bytes,0,sizeof(destpubkey));
LP_tradebot_calcstats(bot);
if ( bot->dead == 0 && bot->pause == 0 && bot->userpause == 0 && bot->numtrades < sizeof(bot->trades)/sizeof(*bot->trades) )
{
if ( (liststr= LP_recent_swaps(0)) != 0 )
{
if ( (retjson= cJSON_Parse(liststr)) != 0 )
{
if ( jobj(retjson,"pending") == 0 )
{
remaining = bot->totalrelvolume - (bot->relsum + bot->pendrelsum);
maxrel = LP_orderbook_maxrel(bot->base,bot->rel,bot->maxprice);
printf("try autobuy %s/%s remaining %.8f maxprice %.8f maxrel %.8f\n",bot->base,bot->rel,remaining,bot->maxprice,maxrel);
if ( maxrel < remaining )
remaining = maxrel;
tradeid = LP_rand();
for (i=1; i<=maxiters; i++)
{
if ( remaining < 0.001 )
break;
if ( (retstr= LP_autobuy(ctx,LP_myipaddr,LP_mypubsock,bot->base,bot->rel,bot->maxprice,remaining/i,0,0,G.gui,0,destpubkey,tradeid)) != 0 )
{
if ( (retjson2= cJSON_Parse(retstr)) != 0 )
{
if ( (pending= jobj(retjson2,"pending")) != 0 && juint(pending,"tradeid") == tradeid )
{
bot->trades[bot->numtrades++] = tp = LP_tradebot_pending(bot,pending,tradeid);
printf("issued bot trade.%u %s\n",tradeid,retstr);
free_json(retjson2);
free(retstr);
break;
} else printf("iter.%d/%d %.8f didnt get any trade pending %s %s\n\n",i,maxiters,remaining/i,bot->name,retstr);
free_json(retjson2);
} else printf("iter.%d/%d %.8f %s\n",i,maxiters,remaining/i,retstr);
free(retstr);
}
}
LP_tradebot_calcstats(bot);
}
free_json(retjson);
}
free(liststr);
}
}
else if ( bot->pause == 0 )
bot->pause = (uint32_t)time(NULL);
}
void LP_aliceid(uint32_t tradeid,uint64_t aliceid,char *event,uint32_t requestid,uint32_t quoteid)
{
struct LP_tradebot *bot,*tmp; int32_t i,matched = 0; struct LP_tradebot_trade *tp;
if ( tradeid == 0 )
return;
DL_FOREACH_SAFE(LP_tradebots,bot,tmp)
{
for (i=0; i<bot->numtrades; i++)
{
if ( (tp= bot->trades[i]) != 0 )
{
if ( tp->finished == 0 && tp->tradeid == tradeid )
{
tp->aliceid = aliceid;
printf("bot event tradeid.%u aliceid.%llu (%s) r.%u q.%u\n",tradeid,(long long)aliceid,event,requestid,quoteid);
if ( requestid != 0 && quoteid != 0 )
{
tp->requestid = requestid;
tp->quoteid = quoteid;
}
strcpy(tp->event,event);
matched = 1;
break;
} else printf("tradeid.%u finished.%u\n",tp->tradeid,tp->finished);
}
}
if ( matched != 0 )
break;
}
if ( 0 && matched == 0 )
printf("NO MATCH: bot event tradeid.%u aliceid.%llu (%s) r.%u q.%u\n",tradeid,(long long)aliceid,event,requestid,quoteid);
}
void LP_tradebot_finished(uint32_t tradeid,uint32_t requestid,uint32_t quoteid)
{
struct LP_tradebot *bot,*tmp; int32_t i; struct LP_tradebot_trade *tp;
DL_FOREACH_SAFE(LP_tradebots,bot,tmp)
{
for (i=0; i<bot->numtrades; i++)
{
if ( (tp= bot->trades[i]) != 0 && tp->finished == 0 && tp->tradeid == tradeid )
{
tp->requestid = requestid;
tp->quoteid = quoteid;
printf("bot.%u detected completion tradeid.%u aliceid.%llu r.%u q.%u, numpending.%d completed.%d\n",bot->id,tp->tradeid,(long long)tp->aliceid,tp->requestid,tp->quoteid,bot->numpending,bot->completed);
tp->finished = (uint32_t)time(NULL);
strcpy(tp->event,"finished");
break;
}
}
}
}
void LP_tradebots_timeslice(void *ctx)
{
static uint32_t lastnumfinished = 0;
struct iguana_info *relcoin; bits256 zero; struct LP_tradebot *bot,*tmp;
DL_FOREACH_SAFE(LP_tradebots,bot,tmp)
{
memset(zero.bytes,0,sizeof(zero));
if ( (relcoin= LP_coinfind(bot->rel)) != 0 )
LP_listunspent_issue(bot->rel,relcoin->smartaddr,1,zero,zero);
if ( bot->relsum >= 0.99*bot->totalrelvolume-SMALLVAL || bot->basesum >= 0.99*bot->totalbasevolume-SMALLVAL )
bot->dead = (uint32_t)time(NULL);
else if ( (bot->pendrelsum+bot->relsum) >= 0.99*bot->totalrelvolume-SMALLVAL || (bot->basesum+bot->pendbasesum) >= 0.99*bot->totalbasevolume-SMALLVAL )
bot->pause = (uint32_t)time(NULL);
else if ( bot->userpause == 0 )
bot->pause = 0;
if ( bot->numpending == 0 && time(NULL) > bot->lasttime+TRADEBOTS_GAPTIME )
{
LP_tradebot_timeslice(ctx,bot);
bot->lasttime = (uint32_t)time(NULL);
}
}
lastnumfinished = LP_numfinished;
}
char *LP_tradebot_list(void *ctx,int32_t pubsock,cJSON *argjson)
{
struct LP_tradebot *bot,*tmp; cJSON *array = cJSON_CreateArray();
DL_FOREACH_SAFE(LP_tradebots,bot,tmp)
{
jaddinum(array,bot->id);
}
return(jprint(array,1));
}
char *LP_tradebot_statuslist(void *ctx,int32_t pubsock,cJSON *argjson)
{
struct LP_tradebot *bot,*tmp; cJSON *array = cJSON_CreateArray();
DL_FOREACH_SAFE(LP_tradebots,bot,tmp)
{
jaddi(array,LP_tradebot_json(bot));
}
return(jprint(array,1));
}
char *LP_tradebot_buy(int32_t dispdir,char *base,char *rel,double maxprice,double relvolume)
{
struct LP_tradebot *bot; char *retstr; double shortfall; cJSON *retjson; uint64_t sum,txfee,txfees,balance=0,abalance=0; struct iguana_info *basecoin,*relcoin;
basecoin = LP_coinfind(base);
relcoin = LP_coinfind(rel);
if ( basecoin == 0 || relcoin == 0 || basecoin->inactive != 0 || relcoin->inactive != 0 )
return(clonestr("{\"error\":\"one or more coins inactive\"}"));
/*if ( (array= LP_inventory(rel)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 && is_cJSON_Array(array) != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
abalance += j64bits(item,"satoshis");
}
}
free_json(array);
}*/
if ( (retstr= LP_orderbook(base,rel,0)) != 0 )
free(retstr);
txfee = LP_txfeecalc(relcoin,0,0);
txfees = 10 * txfee;
if ( relcoin->electrum != 0 )
balance = LP_unspents_load(relcoin->symbol,relcoin->smartaddr);
else balance = LP_RTsmartbalance(relcoin);
sum = (SATOSHIDEN*relvolume+2*dstr(txfees)) + 3 * ((SATOSHIDEN*relvolume+2*dstr(txfees))/777);
printf("%s inventory balance %.8f, relvolume %.8f + txfees %.8f, utxobal %.8f sum %.8f\n",rel,dstr(abalance),relvolume,dstr(txfees),dstr(balance),dstr(sum));
//if ( (abalance < SATOSHIDEN*relvolume + txfees) || ((balance-abalance) < (uint64_t)(SATOSHIDEN*relvolume)/777 + txfees) )
if ( balance < sum+2*txfee )
{
retjson = cJSON_CreateObject();
jaddstr(retjson,"error","not enough funds");
jaddstr(retjson,"coin",rel);
jaddnum(retjson,"abalance",dstr(abalance));
jaddnum(retjson,"balance",dstr(balance));
jaddnum(retjson,"relvolume",relvolume);
jaddnum(retjson,"txfees",dstr(txfees));
shortfall = (relvolume + dstr(txfees)) - dstr(balance);
jaddnum(retjson,"shortfall",shortfall);
/*if ( balance > sum+2*txfee )
{
char *withdrawstr; cJSON *outputjson,*withdrawjson,*outputs,*item;
outputjson = cJSON_CreateObject();
outputs = cJSON_CreateArray();
item = cJSON_CreateObject();
jaddnum(item,relcoin->smartaddr,relvolume+2*dstr(txfees));
jaddi(outputs,item);
item = cJSON_CreateObject();
jaddnum(item,relcoin->smartaddr,(relvolume+2*dstr(txfees))/777);
jaddi(outputs,item);
item = cJSON_CreateObject();
jaddnum(item,relcoin->smartaddr,(relvolume+2*dstr(txfees))/777);
jaddi(outputs,item);
item = cJSON_CreateObject();
jaddnum(item,relcoin->smartaddr,(relvolume+2*dstr(txfees))/777);
jaddi(outputs,item);
jadd(outputjson,"outputs",outputs);
if ( (withdrawstr= LP_withdraw(relcoin,outputjson)) != 0 )
{
if ( (withdrawjson= cJSON_Parse(withdrawstr)) != 0 )
jadd(retjson,"withdraw",withdrawjson);
free(withdrawstr);
}
free_json(outputjson);
}*/
return(jprint(retjson,1));
}
printf("disp.%d tradebot_buy(%s / %s) maxprice %.8f relvolume %.8f\n",dispdir,base,rel,maxprice,relvolume);
if ( (bot= calloc(1,sizeof(*bot))) != 0 )
{
safecopy(bot->base,base,sizeof(bot->base));
safecopy(bot->rel,rel,sizeof(bot->rel));
bot->dispdir = dispdir;
bot->maxprice = maxprice;
bot->totalrelvolume = relvolume;
LP_pricevol_invert(&bot->totalbasevolume,maxprice,relvolume);
bot->started = (uint32_t)time(NULL);
if ( dispdir > 0 )
sprintf(bot->name,"buy_%s_%s.%d",base,rel,bot->started);
else sprintf(bot->name,"sell_%s_%s.%d",rel,base,bot->started);
bot->id = calc_crc32(0,(uint8_t *)bot,sizeof(*bot));
LP_tradebotadd(bot);
return(jprint(LP_tradebot_json(bot),1));
}
return(0);
}
char *LP_tradebot_limitbuy(void *ctx,int32_t pubsock,cJSON *argjson)
{
double relvolume,maxprice; char *base,*rel;
base = jstr(argjson,"base");
rel = jstr(argjson,"rel");
maxprice = jdouble(argjson,"maxprice");
relvolume = jdouble(argjson,"relvolume");
printf("limit buy %s/%s %.8f %.8f\n",base,rel,maxprice,relvolume);
if ( LP_priceinfofind(base) != 0 && LP_priceinfofind(rel) != 0 && maxprice > SMALLVAL && maxprice < SATOSHIDEN && relvolume > 0.0001 && relvolume < SATOSHIDEN )
return(LP_tradebot_buy(1,base,rel,maxprice,relvolume));
return(clonestr("{\"error\":\"invalid parameter\"}"));
}
char *LP_tradebot_limitsell(void *ctx,int32_t pubsock,cJSON *argjson)
{
double relvolume,maxprice,price,basevolume,p,v; char *base,*rel;
base = jstr(argjson,"base");
rel = jstr(argjson,"rel");
price = jdouble(argjson,"minprice");
basevolume = jdouble(argjson,"basevolume");
if ( LP_priceinfofind(base) != 0 && LP_priceinfofind(rel) != 0 && price > SMALLVAL && price < SATOSHIDEN && basevolume > 0.0001 && basevolume < SATOSHIDEN )
{
maxprice = price;
relvolume = (price * basevolume);
p = LP_pricevol_invert(&v,maxprice,relvolume);
printf("minprice %.8f basevolume %.8f -> (%.8f %.8f) -> (%.8f %.8f)\n",price,basevolume,maxprice,relvolume,1./p,v);
return(LP_tradebot_buy(-1,rel,base,p,v));
}
return(clonestr("{\"error\":\"invalid parameter\"}"));
}
char *LP_tradebot_settings(void *ctx,int32_t pubsock,cJSON *argjson,uint32_t botid)
{
struct LP_tradebot *bot; double newprice,newvolume;
if ( (bot= LP_tradebotfind(botid)) != 0 )
{
if ( bot->dead != 0 )
return(clonestr("{\"error\":\"botid aleady stopped\"}"));
newprice = jdouble(argjson,"newprice");
newvolume = jdouble(argjson,"newvolume");
if ( (newprice > SMALLVAL && newprice < SATOSHIDEN) || (newvolume > 0.0001 && newvolume < SATOSHIDEN) )
{
if ( bot->dispdir < 0 )
{
if ( newprice > SMALLVAL )
bot->maxprice = 1. / newprice;
if ( newvolume > SMALLVAL )
bot->totalrelvolume = (bot->maxprice * newvolume);
}
else
{
if ( newprice > SMALLVAL )
bot->maxprice = newprice;
if ( newvolume > SMALLVAL )
bot->totalrelvolume = newvolume;
}
}
return(jprint(LP_tradebot_json(bot),1));
}
return(clonestr("{\"error\":\"couldnt find botid\"}"));
}
char *LP_tradebot_status(void *ctx,int32_t pubsock,cJSON *argjson,uint32_t botid)
{
struct LP_tradebot *bot;
if ( (bot= LP_tradebotfind(botid)) != 0 )
return(jprint(LP_tradebot_json(bot),1));
return(clonestr("{\"error\":\"couldnt find botid\"}"));
}
char *LP_tradebot_stop(void *ctx,int32_t pubsock,cJSON *argjson,uint32_t botid)
{
struct LP_tradebot *bot;
if ( (bot= LP_tradebotfind(botid)) != 0 )
{
bot->dead = (uint32_t)time(NULL);
return(clonestr("{\"result\":\"success\"}"));
}
return(clonestr("{\"error\":\"couldnt find botid\"}"));
}
char *LP_tradebot_pause(void *ctx,int32_t pubsock,cJSON *argjson,uint32_t botid)
{
struct LP_tradebot *bot;
if ( (bot= LP_tradebotfind(botid)) != 0 )
{
if ( bot->dead != 0 )
return(clonestr("{\"error\":\"botid aleady stopped\"}"));
bot->userpause = (uint32_t)time(NULL);
return(clonestr("{\"result\":\"success\"}"));
}
return(clonestr("{\"error\":\"couldnt find botid\"}"));
}
char *LP_tradebot_resume(void *ctx,int32_t pubsock,cJSON *argjson,uint32_t botid)
{
struct LP_tradebot *bot;
if ( (bot= LP_tradebotfind(botid)) != 0 )
{
if ( bot->dead != 0 )
return(clonestr("{\"error\":\"botid aleady stopped\"}"));
if ( bot->userpause == 0 )
return(clonestr("{\"result\":\"success\",\"status\":\"botid not paused\"}"));
bot->userpause = 0;
return(clonestr("{\"result\":\"success\"}"));
}
return(clonestr("{\"error\":\"couldnt find botid\"}"));
}
char *LP_istradebots_command(void *ctx,int32_t pubsock,char *method,cJSON *argjson)
{
uint32_t botid;
//printf("LP_istradebots_command check %s\n",method);
if ( strncmp("bot_",method,strlen("bot_")) != 0 )
return(0);
if ( strcmp(method,"bot_list") == 0 )
return(LP_tradebot_list(ctx,pubsock,argjson));
else if ( strcmp(method,"bot_statuslist") == 0 )
return(LP_tradebot_statuslist(ctx,pubsock,argjson));
else if ( strcmp(method,"bot_buy") == 0 )
return(LP_tradebot_limitbuy(ctx,pubsock,argjson));
else if ( strcmp(method,"bot_sell") == 0 )
return(LP_tradebot_limitsell(ctx,pubsock,argjson));
if ( (botid= juint(argjson,"botid")) == 0 )
return(clonestr("{\"error\":\"no botid specified\"}"));
else
{
if ( strcmp(method,"bot_status") == 0 )
return(LP_tradebot_status(ctx,pubsock,argjson,botid));
else if ( strcmp(method,"bot_settings") == 0 )
return(LP_tradebot_settings(ctx,pubsock,argjson,botid));
else if ( strcmp(method,"bot_stop") == 0 )
return(LP_tradebot_stop(ctx,pubsock,argjson,botid));
else if ( strcmp(method,"bot_pause") == 0 )
return(LP_tradebot_pause(ctx,pubsock,argjson,botid));
else if ( strcmp(method,"bot_resume") == 0 )
return(LP_tradebot_resume(ctx,pubsock,argjson,botid));
}
return(0);
}

1133
iguana/exchanges/LP_transaction.c

File diff suppressed because it is too large

729
iguana/exchanges/LP_utxo.c

File diff suppressed because it is too large

808
iguana/exchanges/LP_utxos.c

@ -1,808 +0,0 @@
/******************************************************************************
* Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
//
// LP_utxos.c
// marketmaker
//
int32_t LP_ismine(struct LP_utxoinfo *utxo)
{
if ( utxo != 0 && bits256_cmp(utxo->pubkey,G.LP_mypub25519) == 0 )
return(1);
else return(0);
}
int32_t LP_isavailable(struct LP_utxoinfo *utxo)
{
if ( time(NULL) > utxo->T.swappending )
utxo->T.swappending = 0;
if ( utxo != 0 && utxo->T.swappending == 0 && utxo->S.swap == 0 )
return(1);
else return(0);
}
int32_t LP_isunspent(struct LP_utxoinfo *utxo)
{
struct LP_address_utxo *up; struct _LP_utxoinfo u; struct iguana_info *coin;
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);
}
struct LP_utxoinfo *LP_utxopairfind(int32_t iambob,bits256 txid,int32_t vout,bits256 txid2,int32_t vout2)
{
struct LP_utxoinfo *utxo=0; struct _LP_utxoinfo u;
if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 )
{
u = (iambob != 0) ? utxo->deposit : utxo->fee;
if (vout2 == u.vout && bits256_cmp(u.txid,txid2) == 0 )
return(utxo);
}
return(0);
}
struct LP_utxoinfo *LP_utxofinds(int32_t iambob,bits256 txid,int32_t vout,bits256 txid2,int32_t vout2)
{
struct LP_utxoinfo *utxo;
if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 || (utxo= LP_utxofind(iambob,txid2,vout2)) != 0 || (utxo= LP_utxo2find(iambob,txid,vout)) != 0 || (utxo= LP_utxo2find(iambob,txid2,vout2)) != 0 )
return(utxo);
else return(0);
}
int32_t LP_utxoaddptrs(struct LP_utxoinfo *ptrs[],int32_t n,struct LP_utxoinfo *utxo)
{
int32_t i;
for (i=0; i<n; i++)
if ( ptrs[i] == utxo )
return(n);
ptrs[n++] = utxo;
return(n);
}
int32_t LP_utxocollisions(struct LP_utxoinfo *ptrs[],struct LP_utxoinfo *refutxo)
{
int32_t iambob,n = 0; struct LP_utxoinfo *utxo; struct _LP_utxoinfo u;
if ( refutxo == 0 )
return(0);
portable_mutex_lock(&LP_utxomutex);
for (iambob=0; iambob<=1; iambob++)
{
if ( (utxo= _LP_utxofind(iambob,refutxo->payment.txid,refutxo->payment.vout)) != 0 && utxo != refutxo )
n = LP_utxoaddptrs(ptrs,n,utxo);
if ( (utxo= _LP_utxo2find(iambob,refutxo->payment.txid,refutxo->payment.vout)) != 0 && utxo != refutxo )
n = LP_utxoaddptrs(ptrs,n,utxo);
u = (refutxo->iambob != 0) ? refutxo->deposit : refutxo->fee;
if ( (utxo= _LP_utxofind(iambob,u.txid,u.vout)) != 0 && utxo != refutxo )
n = LP_utxoaddptrs(ptrs,n,utxo);
if ( (utxo= _LP_utxo2find(iambob,u.txid,u.vout)) != 0 && utxo != refutxo )
n = LP_utxoaddptrs(ptrs,n,utxo);
}
portable_mutex_unlock(&LP_utxomutex);
if ( 0 && n > 0 )
printf("LP_utxocollisions n.%d\n",n);
return(n);
}
int32_t _LP_availableset(struct LP_utxoinfo *utxo)
{
int32_t flag = 0;
if ( utxo != 0 )
{
if ( bits256_nonz(utxo->S.otherpubkey) != 0 )
flag = 1, memset(&utxo->S.otherpubkey,0,sizeof(utxo->S.otherpubkey));
if ( utxo->S.swap != 0 )
flag = 1, utxo->S.swap = 0;
if ( utxo->T.swappending != 0 )
flag = 1, utxo->T.swappending = 0;
return(flag);
}
return(0);
}
void _LP_unavailableset(struct LP_utxoinfo *utxo,bits256 otherpubkey)
{
if ( utxo != 0 )
{
utxo->T.swappending = (uint32_t)(time(NULL) + LP_RESERVETIME);
utxo->S.otherpubkey = otherpubkey;
}
}
void LP_unavailableset(struct LP_utxoinfo *utxo,bits256 otherpubkey)
{
struct LP_utxoinfo *ptrs[8]; int32_t i,n; struct _LP_utxoinfo u;
memset(ptrs,0,sizeof(ptrs));
if ( (n= LP_utxocollisions(ptrs,utxo)) > 0 )
{
for (i=0; i<n; i++)
_LP_unavailableset(ptrs[i],otherpubkey);
}
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee;
char str[65],str2[65]; printf("UTXO.[%d] RESERVED %s/v%d %s/v%d collisions.%d\n",utxo->iambob,bits256_str(str,utxo->payment.txid),utxo->payment.vout,bits256_str(str2,u.txid),u.vout,n);
_LP_unavailableset(utxo,otherpubkey);
}
void LP_availableset(struct LP_utxoinfo *utxo)
{
struct LP_utxoinfo *ptrs[8]; int32_t i,n,count = 0; struct _LP_utxoinfo u;
if ( utxo != 0 )
{
memset(ptrs,0,sizeof(ptrs));
if ( (n= LP_utxocollisions(ptrs,utxo)) > 0 )
{
for (i=0; i<n; i++)
count += _LP_availableset(ptrs[i]);
}
count += _LP_availableset(utxo);
if ( count > 0 )
{
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee;
char str[65],str2[65]; printf("UTXO.[%d] AVAIL %s/v%d %s/v%d collisions.%d\n",utxo->iambob,bits256_str(str,utxo->payment.txid),utxo->payment.vout,bits256_str(str2,u.txid),u.vout,n);
}
}
}
cJSON *LP_inventoryjson(cJSON *item,struct LP_utxoinfo *utxo)
{
struct _LP_utxoinfo u;
//jaddstr(item,"method","oldutxo");
if ( utxo == 0 )
return(item);
if ( utxo->gui[0] != 0 )
jaddstr(item,"gui",utxo->gui);
jaddstr(item,"coin",utxo->coin);
//jaddnum(item,"now",time(NULL));
jaddnum(item,"iambob",utxo->iambob);
jaddstr(item,"address",utxo->coinaddr);
jaddbits256(item,"txid",utxo->payment.txid);
jaddnum(item,"vout",utxo->payment.vout);
jadd64bits(item,"value",utxo->payment.value);
jadd64bits(item,"satoshis",utxo->S.satoshis);
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee;
if ( bits256_nonz(u.txid) != 0 )
{
jaddbits256(item,"txid2",u.txid);
jaddnum(item,"vout2",u.vout);
jadd64bits(item,"value2",u.value);
}
if ( utxo->T.swappending != 0 )
jaddnum(item,"pending",utxo->T.swappending);
if ( utxo->iambob != 0 )
{
jaddbits256(item,"srchash",utxo->pubkey);//LP_mypub25519);
if ( bits256_nonz(utxo->S.otherpubkey) != 0 )
jaddbits256(item,"desthash",utxo->S.otherpubkey);
}
else
{
jaddbits256(item,"desthash",utxo->pubkey);//LP_mypub25519);
if ( bits256_nonz(utxo->S.otherpubkey) != 0 )
jaddbits256(item,"srchash",utxo->S.otherpubkey);
}
if ( utxo->S.swap != 0 )
jaddstr(item,"swap","in progress");
if ( utxo->T.spentflag != 0 )
jaddnum(item,"spent",utxo->T.spentflag);
jaddnum(item,"session",utxo->T.sessionid);
return(item);
}
cJSON *LP_utxojson(struct LP_utxoinfo *utxo)
{
cJSON *item = cJSON_CreateObject();
item = LP_inventoryjson(item,utxo);
jaddbits256(item,"pubkey",utxo->pubkey);
//jaddnum(item,"profit",utxo->S.profitmargin);
jaddstr(item,"base",utxo->coin);
//jaddstr(item,"script",utxo->spendscript);
return(item);
}
struct LP_utxoinfo *LP_utxo_bestfit(char *symbol,uint64_t destsatoshis)
{
uint64_t srcvalue,srcvalue2; struct LP_utxoinfo *utxo,*tmp,*bestutxo = 0; int32_t iambob = 0;
if ( symbol == 0 || destsatoshis == 0 )
{
printf("LP_utxo_bestfit error symbol.%p %.8f\n",symbol,dstr(destsatoshis));
return(0);
}
// jl777 remove mempool
HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,tmp)
{
//char str[65]; printf("s%u %d [%.8f vs %.8f] check %s.%s avail.%d ismine.%d >= %d\n",utxo->T.spentflag,LP_iseligible(&srcvalue,&srcvalue2,utxo->iambob,symbol,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,utxo->fee.txid,utxo->fee.vout),dstr(destsatoshis),dstr(utxo->S.satoshis),utxo->coin,bits256_str(str,utxo->payment.txid),LP_isavailable(utxo) > 0,LP_ismine(utxo) > 0,utxo->S.satoshis >= destsatoshis);
if ( strcmp(symbol,utxo->coin) != 0 )
continue;
if ( LP_isavailable(utxo) > 0 && LP_ismine(utxo) > 0 )
{
if ( utxo->S.satoshis >= destsatoshis && (bestutxo == 0 || (bestutxo->S.satoshis < destsatoshis && utxo->S.satoshis >= destsatoshis) || (bestutxo->S.satoshis >= destsatoshis && utxo->S.satoshis < bestutxo->S.satoshis)) )
{
if ( LP_iseligible(&srcvalue,&srcvalue2,utxo->iambob,symbol,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,utxo->fee.txid,utxo->fee.vout) == 0 )
{
//if ( utxo->T.spentflag == 0 )
// utxo->T.spentflag = (uint32_t)time(NULL);
continue;
}
bestutxo = utxo;
} //else printf("skip alice utxo %.8f vs dest %.8f\n",dstr(utxo->S.satoshis),dstr(destsatoshis));
}
}
return(bestutxo);
}
void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector)
{
if ( utxo == 0 )
return;
utxo->T.spentflag = (uint32_t)time(NULL);
}
struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t vout,int64_t value,bits256 txid2,int32_t vout2,int64_t value2,char *coinaddr,bits256 pubkey,char *gui,uint32_t sessionid)
{
uint64_t val,val2=0,tmpsatoshis,txfee; int32_t spendvini,numconfirms,selector; bits256 spendtxid; struct iguana_info *coin; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo = 0;
if ( symbol == 0 || symbol[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 || vout < 0 || vout2 < 0 || value <= 0 || value2 <= 0 )//|| sessionid == 0 )
{
char str[65],str2[65]; printf("REJECT %s iambob.%d %s utxoadd.(%.8f %.8f) %s/v%d %s/v%d\n",coinaddr,iambob,symbol,dstr(value),dstr(value2),bits256_str(str,txid),vout,bits256_str(str2,txid2),vout2);
printf("session.%u addutxo %d %d %d %d %d %d %d %d\n",sessionid,symbol == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(txid2) == 0,vout < 0,vout2 < 0,value <= 0,value2 <= 0);
return(0);
}
if ( (coin= LP_coinfind(symbol)) == 0 || (IAMLP == 0 && coin->inactive != 0) )
{
//printf("LP_utxoadd reject inactive %s\n",symbol);
return(0);
}
txfee = LP_txfeecalc(coin,0,0);
if ( iambob != 0 && value2 < 9 * (value >> 3) + 2*txfee ) // big txfee padding
{
if ( value2 > 2*txfee )
tmpsatoshis = (((value2 - 2*txfee) / 9) << 3);
else
{
printf("value2 %.8f <= 2 * %.8f\n",dstr(value2),dstr(txfee));
return(0);
}
} else tmpsatoshis = (value - txfee);
char str[65],str2[65],dispflag = 0;//(iambob == 0);
if ( iambob == 0 && bits256_cmp(pubkey,G.LP_mypub25519) != 0 )
{
printf("trying to add Alice utxo when not mine? %s/v%d\n",bits256_str(str,txid),vout);
return(0);
}
if ( coin->inactive == 0 )
{
if ( LP_iseligible(&val,&val2,iambob,symbol,txid,vout,tmpsatoshis,txid2,vout2) <= 0 )
{
static uint32_t counter;
if ( counter++ < 3 )
printf("iambob.%d utxoadd %s inactive.%u got ineligible txid value %.8f:%.8f, value2 %.8f:%.8f, tmpsatoshis %.8f\n",iambob,symbol,coin->inactive,dstr(value),dstr(val),dstr(value2),dstr(val2),dstr(tmpsatoshis));
return(0);
}
if ( (numconfirms= LP_numconfirms(symbol,coinaddr,txid,vout,0)) <= 0 )
{
printf("LP_utxoadd reject numconfirms.%d %s.%s\n",numconfirms,symbol,bits256_str(str,txid));
return(0);
}
if ( (numconfirms= LP_numconfirms(symbol,coinaddr,txid2,vout2,0)) <= 0 )
{
printf("LP_utxoadd reject2 numconfirms.%d %s %s/v%d\n",numconfirms,symbol,bits256_str(str,txid2),vout2);
return(0);
}
}
else
{
val = value;
val2 = value2;
}
dispflag = 0;
if ( dispflag != 0 )
printf("%.8f %.8f %s iambob.%d %s utxoadd.(%.8f %.8f) %s %s\n",dstr(val),dstr(val2),coinaddr,iambob,symbol,dstr(value),dstr(value2),bits256_str(str,txid),bits256_str(str2,txid2));
dispflag = 1;
if ( (utxo= LP_utxofinds(iambob,txid,vout,txid2,vout2)) != 0 )
{
if ( 0 && LP_ismine(utxo) == 0 )
{
char str2[65],str3[65]; printf("iambob.%d %s %s utxoadd.(%.8f %.8f) %s %s\n",iambob,bits256_str(str3,pubkey),symbol,dstr(value),dstr(value2),bits256_str(str,txid),bits256_str(str2,txid2));
printf("duplicate %.8f %.8f %.8f vs utxo.(%.8f %.8f %.8f)\n",dstr(value),dstr(value2),dstr(tmpsatoshis),dstr(utxo->payment.value),dstr(utxo->deposit.value),dstr(utxo->S.satoshis));
}
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee;
if ( bits256_cmp(txid,utxo->payment.txid) != 0 || bits256_cmp(txid2,u.txid) != 0 || vout != utxo->payment.vout || value != utxo->payment.value || tmpsatoshis != utxo->S.satoshis || vout2 != u.vout || value2 != u.value || strcmp(symbol,utxo->coin) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || bits256_cmp(pubkey,utxo->pubkey) != 0 )
{
utxo->T.errors++;
char str[65],str2[65],str3[65],str4[65],str5[65],str6[65];
if ( utxo->T.spentflag != 0 || LP_txvalue(0,utxo->coin,utxo->payment.txid,utxo->payment.vout) < utxo->payment.value || LP_txvalue(0,utxo->coin,u.txid,u.vout) < u.value )
{
//if ( utxo->T.spentflag == 0 )
// utxo->T.spentflag = (uint32_t)time(NULL);
printf("original utxo pair not valid\n");
if ( dispflag != 0 )
printf("error on subsequent utxo iambob.%d %.8f %.8f add.(%s %s) when.(%s %s) %d %d %d %d %d %d %d %d %d %d pubkeys.(%s vs %s)\n",iambob,dstr(val),dstr(val2),bits256_str(str,txid),bits256_str(str2,txid2),bits256_str(str3,utxo->payment.txid),bits256_str(str4,utxo->deposit.txid),bits256_cmp(txid,utxo->payment.txid) != 0,bits256_cmp(txid2,u.txid) != 0,vout != utxo->payment.vout,tmpsatoshis != utxo->S.satoshis,vout2 != u.vout,value2 != u.value,strcmp(symbol,utxo->coin) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,bits256_cmp(pubkey,utxo->pubkey) != 0,value != utxo->payment.value,bits256_str(str5,pubkey),bits256_str(str6,utxo->pubkey));
utxo = 0;
}
}
if ( utxo != 0 )
{
if ( utxo->T.sessionid == 0 )
utxo->T.sessionid = sessionid;
//else if ( profitmargin > SMALLVAL )
// utxo->S.profitmargin = profitmargin;
utxo->T.lasttime = (uint32_t)time(NULL);
//printf("return existing utxo[%d] %s %s\n",iambob,bits256_str(str,utxo->payment.txid),bits256_str(str2,iambob != 0 ? utxo->deposit.txid : utxo->fee.txid));
return(utxo);
}
}
utxo = calloc(1,sizeof(*utxo));
//utxo->S.profitmargin = profitmargin;
utxo->pubkey = pubkey;
safecopy(utxo->gui,gui,sizeof(utxo->gui));
safecopy(utxo->coin,symbol,sizeof(utxo->coin));
safecopy(utxo->coinaddr,coinaddr,sizeof(utxo->coinaddr));
//safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript));
utxo->payment.txid = txid;
utxo->payment.vout = vout;
utxo->payment.value = value;
utxo->S.satoshis = tmpsatoshis;
if ( (utxo->iambob= iambob) != 0 )
{
utxo->deposit.txid = txid2;
utxo->deposit.vout = vout2;
utxo->deposit.value = value2;
}
else
{
utxo->fee.txid = txid2;
utxo->fee.vout = vout2;
utxo->fee.value = value2;
}
LP_utxosetkey(utxo->key,txid,vout);
LP_utxosetkey(utxo->key2,txid2,vout2);
if ( LP_ismine(utxo) > 0 )
utxo->T.sessionid = G.LP_sessionid;
else utxo->T.sessionid = sessionid;
if ( coin->inactive == 0 && (selector= LP_mempool_vinscan(&spendtxid,&spendvini,symbol,coinaddr,txid,vout,txid2,vout2)) >= 0 )
{
printf("utxoadd selector.%d spent in mempool %s vini.%d",selector,bits256_str(str,spendtxid),spendvini);
utxo->T.spentflag = (uint32_t)time(NULL);
}
//printf(" %s %.8f %.8f %p addutxo.%d (%s %s) session.%u iambob.%d <<<<<<<<<<<<<<<\n",symbol,dstr(value),dstr(value2),utxo,LP_ismine(utxo) > 0,bits256_str(str,utxo->payment.txid),bits256_str(str2,iambob != 0 ? utxo->deposit.txid : utxo->fee.txid),utxo->T.sessionid,iambob);
portable_mutex_lock(&LP_utxomutex);
HASH_ADD_KEYPTR(hh,G.LP_utxoinfos[iambob],utxo->key,sizeof(utxo->key),utxo);
if ( _LP_utxo2find(iambob,txid2,vout2) == 0 )
HASH_ADD_KEYPTR(hh2,G.LP_utxoinfos2[iambob],utxo->key2,sizeof(utxo->key2),utxo);
portable_mutex_unlock(&LP_utxomutex);
if ( iambob != 0 )
{
if ( LP_ismine(utxo) > 0 )
{
//LP_utxo_clientpublish(utxo);
if ( LP_mypeer != 0 )
utxo->T.lasttime = (uint32_t)time(NULL);
}
}
return(utxo);
}
cJSON *LP_inventory(char *symbol)
{
struct LP_utxoinfo *utxo,*tmp; struct _LP_utxoinfo u; char *myipaddr; cJSON *array; uint64_t val,val2; int32_t iambob = 0; struct iguana_info *coin;
array = cJSON_CreateArray();
if ( LP_mypeer != 0 )
myipaddr = LP_mypeer->ipaddr;
else myipaddr = "127.0.0.1";
if ( (coin= LP_coinfind(symbol)) != 0 )
LP_listunspent_both(symbol,coin->smartaddr,0);
HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,tmp)
{
char str[65];
//printf("iambob.%d iterate %s\n",iambob,bits256_str(str,LP_mypub25519));
if ( LP_isunspent(utxo) != 0 && strcmp(symbol,utxo->coin) == 0 && utxo->iambob == iambob && LP_ismine(utxo) > 0 )
{
u = (iambob != 0) ? utxo->deposit : utxo->fee;
if ( LP_iseligible(&val,&val2,iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,u.txid,u.vout) == 0 )
{
//if ( utxo->T.spentflag == 0 )
// utxo->T.spentflag = (uint32_t)time(NULL);
printf("%s %s ineligible %.8f %.8f\n",utxo->coin,bits256_str(str,u.txid),dstr(val),dstr(val2));
continue;
}
//if ( iambob != 0 )
// LP_utxo_clientpublish(utxo);
jaddi(array,LP_inventoryjson(cJSON_CreateObject(),utxo));
}
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);
}
int32_t LP_maxvalue(uint64_t *values,int32_t n)
{
int32_t i,maxi = -1; uint64_t maxval = 0;
for (i=0; i<n; i++)
if ( values[i] > maxval )
{
maxi = i;
maxval = values[i];
}
return(maxi);
}
int32_t LP_nearestvalue(int32_t iambob,uint64_t *values,int32_t n,uint64_t targetval)
{
int32_t i,mini = -1; int64_t dist; uint64_t mindist = (1 << 31);
for (i=0; i<n; i++)
{
dist = (values[i] - targetval);
if ( iambob != 0 && dist < 0 && -dist < values[i]/10 )
dist = -dist;
//printf("(%.8f %.8f %.8f).%d ",dstr(values[i]),dstr(dist),dstr(mindist),mini);
if ( dist >= 0 && dist < mindist )
{
mini = i;
mindist = dist;
}
}
return(mini);
}
int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 myprivkey,bits256 mypub)
{
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 || (IAMLP == 0 && coin->inactive != 0) )
{
//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,0);
LP_address(coin,coin->smartaddr);
if ( coin->inactive == 0 && (array= LP_listunspent(coin->symbol,coin->smartaddr)) != 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));
for (iambob=0; iambob<=1; iambob++)
{
if ( iambob == 0 )
values = calloc(n,sizeof(*values));
else memset(values,0,n * sizeof(*values));
used = 0;
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( coin->electrum == 0 )
{
txid = jbits256(item,"txid");
vout = juint(item,"vout");
value = LP_value_extract(item,0);
height = LP_txheight(coin,txid);//LP_getheight(coin) - jint(item,"confirmations") + 1;
}
else
{
txid = jbits256(item,"tx_hash");
vout = juint(item,"tx_pos");
value = j64bits(item,"value");
height = jint(item,"height");
}
satoshis = LP_txvalue(destaddr,coin->symbol,txid,vout);
if ( satoshis != 0 && satoshis != value )
printf("%s %s unexpected privkey_init value mismatch %.8f vs %.8f (%s) %.8f %.8f\n",coin->symbol,coin->smartaddr,dstr(satoshis),dstr(value),jprint(item,0),jdouble(item,"amount"),jdouble(item,"interest"));
if ( LP_inventory_prevent(iambob,coin->symbol,txid,vout) == 0 && height > 0 )
{
//printf("%s\n",jprint(item,0));
values[i] = satoshis;
//flag += LP_address_utxoadd(coin,destaddr,txid,vout,satoshis,height,-1);
} else used++;
}
//printf("array.%d\n",n);
while ( used < n-1 )
{
//for (i=0; i<n; i++)
// printf("%.8f ",dstr(values[i]));
//printf("used.%d of n.%d\n",used,n);
if ( (i= LP_maxvalue(values,n)) >= 0 )
{
item = jitem(array,i);
if ( coin->electrum == 0 )
{
deposittxid = jbits256(item,"txid");
depositvout = juint(item,"vout");
script = jstr(item,"scriptPubKey");
}
else
{
deposittxid = jbits256(item,"tx_hash");
depositvout = juint(item,"tx_pos");
script = coin->smartaddr;
}
depositval = values[i];
values[i] = 0, used++;
if ( iambob == 0 )
targetval = (depositval / 776) + txfee;
else targetval = (depositval / 9) * 8 + 2*txfee;
if ( targetval < txfee*2 )
targetval = txfee*2;
//printf("iambob.%d i.%d deposit %.8f min %.8f target %.8f\n",iambob,i,dstr(depositval),dstr((1+LP_MINSIZE_TXFEEMULT)*txfee),dstr(targetval));
if ( depositval < (1+LP_MINSIZE_TXFEEMULT)*txfee )
continue;
i = -1;
if ( iambob != 0 )
{
if ( (i= LP_nearestvalue(iambob,values,n,targetval)) < 0 )
targetval /= 4;
if ( targetval < txfee*(1+LP_MINSIZE_TXFEEMULT) )
continue;
}
if ( i >= 0 || (i= LP_nearestvalue(iambob,values,n,targetval)) >= 0 )
{
//printf("iambob.%d i.%d %.8f target %.8f\n",iambob,i,dstr(depositval),dstr(targetval));
item = jitem(array,i);
cmpflag = 0;
if ( coin->electrum == 0 )
{
txid = jbits256(item,"txid");
vout = juint(item,"vout");
if ( jstr(item,"scriptPubKey") != 0 && strcmp(script,jstr(item,"scriptPubKey")) == 0 )
cmpflag = 1;
}
else
{
txid = jbits256(item,"tx_hash");
vout = juint(item,"tx_pos");
cmpflag = 1;
}
if ( cmpflag != 0 )
{
value = values[i];
values[i] = 0, used++;
portable_mutex_lock(&LP_UTXOmutex);
if ( iambob != 0 )
{
if ( (utxo= LP_utxoadd(1,coin->symbol,txid,vout,value,deposittxid,depositvout,depositval,coin->smartaddr,mypub,LP_gui,G.LP_sessionid)) != 0 )
{
}
}
else
{
//printf("call utxoadd\n");
if ( (utxo= LP_utxoadd(0,coin->symbol,deposittxid,depositvout,depositval,txid,vout,value,coin->smartaddr,mypub,LP_gui,G.LP_sessionid)) != 0 )
{
}
}
portable_mutex_unlock(&LP_UTXOmutex);
total += value;
} // else printf("scriptmismatch.(%s) vs %s\n",script,jprint(item,0));
} //else printf("nothing near i.%d\n",i);
} else break;
}
if ( enable_utxos == 0 )
break;
}
}
free_json(array);
if ( flag != 0 )
LP_postutxos(coin->symbol,coin->smartaddr);
}
if ( values != 0 )
free(values);
//printf("privkey.%s %.8f\n",symbol,dstr(total));
return(flag);
}
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 )
n = 16;
else if ( n > 777 )
n = 777;
conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase));
bitcoin_priv2pub(ctx,pubkey33,coinaddr,privkey,taddr,pubtype);
printf("generator (%s) secrets.[%d] <%s> t.%u p.%u\n",coinaddr,n,passphrase,taddr,pubtype);
sprintf(output,"\"addresses\":[");
for (i=0; i<n; 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);
bitcoin_wif2priv(0,&tmptype,&checkprivkey,wifstr);
bitcoin_addr2rmd160(taddr,&tmptype,rmd160,coinaddr);
if ( bits256_cmp(checkprivkey,privkey) != 0 )
{
printf("WIF.(%s) error -> %s vs %s?\n",wifstr,bits256_str(str,privkey),bits256_str(str2,checkprivkey));
free_json(retjson);
return(clonestr("{\"error\":\"couldnt validate wifstr\"}"));
}
else if ( tmptype != pubtype )
{
printf("checktype.%d != pubtype.%d\n",tmptype,pubtype);
free_json(retjson);
return(clonestr("{\"error\":\"couldnt validate pubtype\"}"));
}
jaddstr(retjson,coinaddr,wifstr);
sprintf(output+strlen(output),"\\\"%s\\\"%c ",coinaddr,i<n-1?',':' ');
printf("./komodo-cli jumblr_secret %s\n",coinaddr);
}
printf("%s]\n",output);
return(jprint(retjson,1));
}
bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguana_info *coin,char *passphrase,char *wifstr)
{
//static uint32_t counter;
bits256 privkey,userpub,userpass,checkkey; char tmpstr[128]; cJSON *retjson; uint8_t tmptype;
if ( passphrase != 0 && passphrase[0] != 0 )
{
conv_NXTpassword(privkey.bytes,pubkeyp->bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase));
//vcalc_sha256(0,checkkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase));
//printf("SHA256.(%s) ",bits256_str(pstr,checkkey));
//printf("privkey.(%s)\n",bits256_str(pstr,privkey));
}
else
{
bitcoin_wif2priv(coin->wiftaddr,&tmptype,&privkey,wifstr);
if ( 0 )
{
char str[65],str2[65];
checkkey = iguana_wif2privkey(wifstr);
if ( bits256_cmp(checkkey,privkey) != 0 )
printf("WIF.(%s) -> %s or %s?\n",wifstr,bits256_str(str,privkey),bits256_str(str2,checkkey));
}
}
privkey.bytes[0] &= 248, privkey.bytes[31] &= 127, privkey.bytes[31] |= 64;
bitcoin_priv2pub(ctx,coin->pubkey33,coin->smartaddr,privkey,coin->taddr,coin->pubtype);
if ( coin->counter == 0 )
{
coin->counter++;
memcpy(G.LP_pubsecp,coin->pubkey33,33);
bitcoin_priv2wif(coin->wiftaddr,tmpstr,privkey,coin->wiftype);
bitcoin_addr2rmd160(coin->taddr,&tmptype,G.LP_myrmd160,coin->smartaddr);
LP_privkeyadd(privkey,G.LP_myrmd160);
G.LP_privkey = privkey;
if ( 0 && (coin->pubtype != 60 || strcmp(coin->symbol,"KMD") == 0) )
printf("%s (%s) %d wif.(%s) (%s)\n",coin->symbol,coin->smartaddr,coin->pubtype,tmpstr,passphrase);
if ( G.counter++ == 0 )
{
bitcoin_priv2wif(coin->wiftaddr,G.USERPASS_WIFSTR,privkey,188);
bitcoin_wif2priv(coin->wiftaddr,&tmptype,&checkkey,G.USERPASS_WIFSTR);
if ( bits256_cmp(checkkey,privkey) != 0 )
{
char str[65],str2[65];
printf("FATAL ERROR converting USERPASS_WIFSTR %s -> %s != %s\n",G.USERPASS_WIFSTR,bits256_str(str,checkkey),bits256_str(str2,privkey));
exit(-1);
}
conv_NXTpassword(userpass.bytes,pubkeyp->bytes,(uint8_t *)G.USERPASS_WIFSTR,(int32_t)strlen(G.USERPASS_WIFSTR));
userpub = curve25519(userpass,curve25519_basepoint9());
printf("userpass.(%s)\n",bits256_str(G.USERPASS,userpub));
}
if ( coin->electrum == 0 && coin->userpass[0] != 0 )
{
LP_listunspent_issue(coin->symbol,coin->smartaddr,0);
if ( (retjson= LP_importprivkey(coin->symbol,tmpstr,coin->smartaddr,-1)) != 0 )
{
if ( jobj(retjson,"error") != 0 )
{
printf("cant importprivkey.%s -> (%s), abort session\n",coin->symbol,jprint(retjson,1));
exit(-1);
}
} else free_json(retjson);
}
}
vcalc_sha256(0,checkkey.bytes,privkey.bytes,sizeof(privkey));
checkkey.bytes[0] &= 248, checkkey.bytes[31] &= 127, checkkey.bytes[31] |= 64;
G.LP_mypub25519 = *pubkeyp = curve25519(checkkey,curve25519_basepoint9());
G.LP_mypriv25519 = checkkey;
LP_pubkeyadd(G.LP_mypub25519);
return(privkey);
}
void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase)
{
struct iguana_info *coin,*tmp; bits256 pubkey,privkey; uint8_t pubkey33[33]; int32_t initonly;
initonly = (passphrase != 0);
memset(privkey.bytes,0,sizeof(privkey));
memset(pubkey.bytes,0,sizeof(pubkey));
//printf("Total coins: %d\n", HASH_COUNT(LP_coins));
//int num_iter = 0;
HASH_ITER(hh,LP_coins,coin,tmp)
{
//printf("LP_privkey_updates [%02d / %02d]\n", num_iter++, HASH_COUNT(LP_coins));
if ( initonly != 0 )
{
coin->counter = 0;
memset(coin->smartaddr,0,sizeof(coin->smartaddr));
if ( bits256_nonz(privkey) == 0 || coin->smartaddr[0] == 0 )
privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,coin,passphrase,"");
}
//printf("i.%d of %d\n",i,LP_numcoins);
else if ( IAMLP == 0 || coin->inactive == 0 )
{
//printf("from updates %s\n",coin->symbol);
if ( LP_privkey_init(pubsock,coin,G.LP_privkey,G.LP_mypub25519) == 0 && (rand() % 10) == 0 )
LP_postutxos(coin->symbol,coin->smartaddr);
}
}
}
int32_t LP_passphrase_init(char *passphrase,char *gui)
{
static void *ctx; int32_t iambob,counter; struct LP_utxoinfo *utxo,*tmp;
if ( ctx == 0 )
ctx = bitcoin_ctx();
if ( G.LP_pendingswaps != 0 )
return(-1);
G.initializing = 1;
if ( gui == 0 )
gui = "cli";
counter = G.USERPASS_COUNTER;
while ( G.waiting == 0 )
{
printf("waiting for G.waiting\n");
sleep(5);
}
for (iambob=0; iambob<2; iambob++)
{
if ( G.LP_utxoinfos[iambob] != 0 )
{
HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,tmp)
{
HASH_DELETE(hh,G.LP_utxoinfos[iambob],utxo);
//free(utxo);
}
}
if ( G.LP_utxoinfos2[iambob] != 0 )
{
G.LP_utxoinfos2[iambob] = 0;
/*HASH_ITER(hh,G.LP_utxoinfos2[iambob],utxo,tmp)
{
HASH_DELETE(hh,G.LP_utxoinfos2[iambob],utxo);
free(utxo);
}*/
}
}
memset(&G,0,sizeof(G));
LP_privkey_updates(ctx,LP_mypubsock,passphrase);
init_hexbytes_noT(G.LP_myrmd160str,G.LP_myrmd160,20);
G.LP_sessionid = (uint32_t)time(NULL);
safecopy(G.gui,gui,sizeof(G.gui));
G.USERPASS_COUNTER = counter;
return(0);
}

9
iguana/exchanges/Makefile

@ -1,10 +1,15 @@
#cd ..
#emcc -s ASSERTIONS=1 -s ASYNCIFY=1 -s TOTAL_MEMORY=134217728 --preload-file coins.json -D__PNACL -DFROM_JS -O2 -I../includes -I../crypto777 -s PTHREAD_POOL_SIZE=8 -s USE_PTHREADS=1 -o /var/www/html/index.html exchanges/mm.c $(CRYPTO777_SRCS) mini-gmp.c secp256k1/src/secp256k1.c -lm -lc
#include ../crypto777/crypto777.sources
#emcc -s ASSERTIONS=1 -s ASYNCIFY=1 -s TOTAL_MEMORY=134217728 --preload-file coins.json -D__PNACL -DFROM_JS -O2 -I../includes -I../crypto777 -o /var/www/html/index.html exchanges/mm.c $(CRYPTO777_SRCS) mini-gmp.c secp256k1/src/secp256k1.c -lm -lc
#emcc -s WASM=1 -s EXPORTED_FUNCTIONS="['_main', '_barterDEX']" -s ABORTING_MALLOC=0 -s ASSERTIONS=1 -s ASYNCIFY=1 -s TOTAL_MEMORY=167772160 --embed-file coins.json -DFROM_JS -O2 -I../includes -I../crypto777 -o /var/www/html/index.html exchanges/mm.c ../crypto777/*.c ../crypto777/jpeg/*.c ../crypto777/jpeg/unix/*.c mini-gmp.c secp256k1/src/secp256k1.c -lm
#emcc -s WASM=1 -s EXPORTED_FUNCTIONS="['_barterDEX', '_main']" -s ABORTING_MALLOC=0 -s ASSERTIONS=1 -s ASYNCIFY=1 -s TOTAL_MEMORY=167772160 --embed-file coins.json -DFROM_JS -I../includes -I../crypto777 -o /var/www/html/index.hmtl exchanges/mm.c ../crypto777/*.c ../crypto777/jpeg/*.c ../crypto777/jpeg/unix/*.c mini-gmp.c secp256k1/src/secp256k1.c -lm
#emcc -s EXPORTED_FUNCTIONS="['_main', '_barterDEX']" -s ABORTING_MALLOC=0 -s ASSERTIONS=1 -s ASYNCIFY=1 -s TOTAL_MEMORY=167772160 --embed-file coins.json -DFROM_JS -I../includes -I../crypto777 -o /var/www/html/barterDEX.js exchanges/barterDEX.c
all:
emcc -s PTHREAD_POOL_SIZE=8 -s USE_PTHREADS=1 -s ABORTING_MALLOC=0 -s ASSERTIONS=1 -s ASYNCIFY=1 -s TOTAL_MEMORY=536870912 --preload-file coins.json -DFROM_JS -O2 -I../includes -I../crypto777 -s PTHREAD_POOL_SIZE=8 -s USE_PTHREADS=1 -o /var/www/html/index.html exchanges/mm.c ../crypto777/*.c ../crypto777/jpeg/*.c ../crypto777/jpeg/unix/*.c mini-gmp.c secp256k1/src/secp256k1.c -lm -lpthread
emcc -s WASM=1 -s EXPORTED_FUNCTIONS="['_main', '_barterDEX']" -s ABORTING_MALLOC=0 -s ASSERTIONS=1 -s ASYNCIFY=1 -s TOTAL_MEMORY=167772160 --embed-file coins.json -DFROM_JS -O2 -I../includes -I../crypto777 -o /var/www/html/index.html exchanges/mm.c ../crypto777/*.c ../crypto777/jpeg/*.c ../crypto777/jpeg/unix/*.c mini-gmp.c secp256k1/src/secp256k1.c -lm

2
iguana/exchanges/auto_chipsbtc

@ -0,0 +1,2 @@
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"CHIPS\",\"rel\":\"BTC\",\"margin\":0.01,\"refbase\":\"chips\",\"refrel\":\"coinmarketcap\"}"

2
iguana/exchanges/auto_chipskmd

@ -0,0 +1,2 @@
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"CHIPS\",\"rel\":\"KMD\",\"margin\":0.01,\"refbase\":\"chips\",\"refrel\":\"coinmarketcap\"}"

3
iguana/exchanges/balances

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

14
iguana/exchanges/barterDEX.c

@ -0,0 +1,14 @@
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
char *barterDEX(char *jsonstr)
{
char *retstr,*str = "{\"result\":\"success\"}";
printf("barterDEX.(%s)\n",jsonstr);
retstr = malloc(strlen(str)+1);
strcpy(retstr,str);
return(retstr);
}

3
iguana/exchanges/bot_buy

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

3
iguana/exchanges/bot_list

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

3
iguana/exchanges/bot_pause

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

3
iguana/exchanges/bot_resume

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

3
iguana/exchanges/bot_sell

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"bot_sell\",\"base\":\"REVS\",\"rel\":\"KMD\",\"minprice\":2,\"basevolume\":5.0}"

3
iguana/exchanges/bot_settings

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

3
iguana/exchanges/bot_status

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

3
iguana/exchanges/bot_statuslist

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

3
iguana/exchanges/bot_stop

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

4
iguana/exchanges/bots

@ -0,0 +1,4 @@
#!/bin/bash
source userpass
# this will only work for watchonly addresses that have been rescanned and with active coins
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RNdqHx26GWy9bk8MtmH1UiXjQcXE4RKK2P\",\"divisor\":1000000}"

3
iguana/exchanges/claim

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

2
iguana/exchanges/coins

File diff suppressed because one or more lines are too long

6
iguana/exchanges/coins.json

File diff suppressed because one or more lines are too long

3
iguana/exchanges/deposit1

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

3
iguana/exchanges/deposit10

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

4
iguana/exchanges/dex

@ -0,0 +1,4 @@
#!/bin/bash
source userpass
# this will only work for watchonly addresses that have been rescanned and with active coins
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf\",\"divisor\":1000000}"

3
iguana/exchanges/dynamictrust

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

14
iguana/exchanges/enable

@ -1,5 +1,15 @@
#!/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\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"KMD\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"BTC\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"SUPERNET\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"CRYPTO\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"DEX\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"BOTS\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"BET\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"HODL\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"MSHARK\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"MGW\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"PANGEA\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"JUMBLR\"}"

4
iguana/exchanges/fundvalue

@ -0,0 +1,4 @@
#!/bin/bash
source userpass
# this will only work for watchonly addresses that have been rescanned and with active coins
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":13000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":10000}, {\"coin\":\"syscoin\",\"balance\":20000000}, {\"coin\":\"waves\",\"balance\":700000}, {\"coin\":\"bitcoin\",\"balance\":625}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":375000}, {\"coin\":\"chips\",\"balance\":2577006 }, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }],\"divisor\":650000}"

4
iguana/exchanges/hodl

@ -0,0 +1,4 @@
#!/bin/bash
source userpass
# this will only work for watchonly addresses that have been rescanned and with active coins
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RNcUaMUEFLxVwtTo7rgruhwYanGk1jTkeU\",\"holdings\":[{\"coin\":\"siacoin\",\"balance\":185000000,\"comment\":\"using siafunds equal to million siacoin\"}],\"divisor\":10000000}"

2
iguana/exchanges/install

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

4
iguana/exchanges/invreset

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

4
iguana/exchanges/jumblr

@ -0,0 +1,4 @@
#!/bin/bash
source userpass
# this will only work for watchonly addresses that have been rescanned and with active coins
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RGhxXpXSSBTBm9EvNsXnTQczthMCxHX91t\",\"divisor\":1000000}"

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

Loading…
Cancel
Save