diff --git a/.gitignore b/.gitignore index a61814789..c65237e28 100755 --- a/.gitignore +++ b/.gitignore @@ -170,7 +170,6 @@ iguana/help.json iguana/index7778.html -*.json iguana/DB/KMD/utxo.dat @@ -235,3 +234,13 @@ iguana/marketmaker.dSYM/Contents/Resources/DWARF/marketmaker iguana/marketmaker.dSYM/Contents/Info.plist iguana/confs/97f18454bb61e9eb7a827cfbefe42fbf7ae2832dc74c4812bdaef8bcf5c10474 + +iguana/DB/PRICES/.tmpmarker + +iguana/DB/KMD/0/.tmpmarker + +*.swp + +iguana/myipaddr + +iguana/DB/UNSPENTS/.tmpmarker diff --git a/OSlibs/js/libnanomsg.a b/OSlibs/js/libnanomsg.a new file mode 100644 index 000000000..fb2a83981 Binary files /dev/null and b/OSlibs/js/libnanomsg.a differ diff --git a/OSlibs/js/libnanomsg.so b/OSlibs/js/libnanomsg.so new file mode 100644 index 000000000..a8f7ea8ef Binary files /dev/null and b/OSlibs/js/libnanomsg.so differ diff --git a/OSlibs/win/mingw.h b/OSlibs/win/mingw.h index 6be81f99b..2c35aa78c 100755 --- a/OSlibs/win/mingw.h +++ b/OSlibs/win/mingw.h @@ -5,6 +5,8 @@ #include #define _USE_W32_SOCKETS 1 +#define WIN32_LEAN_AND_MEAN +#include #include #define PTW32_STATIC_LIB #include "pthread.h" @@ -38,6 +40,9 @@ * @author - fadedreamz@gmail.com */ //TODO: need to update other values to match with WSAPoll() function +#define POLLRDNORM 0x0100 +#define POLLRDBAND 0x0200 +#define POLLWRNORM 0x0010 #define POLLIN POLLRDNORM | POLLRDBAND /* There is data to read */ #define POLLOUT POLLWRNORM /* Writing now will not block */ #else @@ -56,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) /* diff --git a/README_decker.md b/README_decker.md new file mode 100644 index 000000000..a9cccd878 --- /dev/null +++ b/README_decker.md @@ -0,0 +1,25 @@ +## What's this? + +This is a first build of **MarketMaker** app from barterDEX for Windows (64-bit) platform. This branch includes all that you need to build marketmaker for Windows. 64-bit build uses MSVC 2015 as a default C/C++ compiler, to build - simply open *marketmaker.sln* project file via File -> Open -> Project/Solution ... next choose Release / x64 configuration and build solution. Your binaries will be placed x64\Release folder. To run marketmaker you also need following dll libraries: + +- libcurl.dll +- nanomsg.dll +- curl.exe (win64 curl binary, used is scripts) + +It already included in this branch. + +## How to use? + +Please, refer to original barterDEX documentation and Komodo Platform + SuperNET resources to learn how to work this it. Later i will add some examples and useful links here. + +Important, coins.json on Windows shouldn't contain coins which haven't running daemons. Add to coins.json only coins that you plan to use, in other case starting marketmaker will too long: about 4 seconds on each not-running coin. + +Get the latest binary release from release section and step-by-step run cmd files: + +- 1-client.cmd - this runs marketmaker with passphrase taken from a passphrase file. +- 2-getuserpass.cmd - this will save and output your userpass in userpass file for future use. +- 3-orderbook.cmd - to get an orderbook (if u downloaded binary release from release section - it's have only REVS in coins.json and orderbook will be shown at KMD/REVS coins pair). + +Other scripts will be post later ... this is just for example that it works. + + \ No newline at end of file diff --git a/basilisk/basilisk_bitcoin.c b/basilisk/basilisk_bitcoin.c index ae7937fe9..942539260 100755 --- a/basilisk/basilisk_bitcoin.c +++ b/basilisk/basilisk_bitcoin.c @@ -602,7 +602,7 @@ char *iguana_utxoduplicates(struct supernet_info *myinfo,struct iguana_info *coi free_json(vins); return(rawtx); } - printf("splitfunds tx.(%s) vins.(%s)\n",rawtx,jprint(vins,0)); + printf("%s splitfunds tx.(%s) vins.(%s)\n",coin->symbol,rawtx,jprint(vins,0)); if ( signedtxidp != 0 ) { if ( (signedtx= iguana_signrawtx(myinfo,coin,0,signedtxidp,completedp,vins,rawtx,0,0)) != 0 ) @@ -615,7 +615,7 @@ char *iguana_utxoduplicates(struct supernet_info *myinfo,struct iguana_info *coi free(rawtx); rawtx = signedtx, signedtx = 0; } - } else printf("error signing raw utxoduplicates tx\n"); + } else printf("error signing raw %s utxoduplicates tx\n",coin->symbol); } } if ( vins != 0 ) diff --git a/crypto777/OS_nonportable.c b/crypto777/OS_nonportable.c index 9e4e3f281..87e167afb 100755 --- a/crypto777/OS_nonportable.c +++ b/crypto777/OS_nonportable.c @@ -26,10 +26,10 @@ * not from the mingw header, so we need to include the windows header * if we are compiling in windows 64bit */ -#if defined(_M_X64) -#define WIN32_LEAN_AND_MEAN -#include -#endif +//#if defined(_M_X64) +//#define WIN32_LEAN_AND_MEAN +//#include +//#endif #include "OS_portable.h" diff --git a/crypto777/OS_portable.c b/crypto777/OS_portable.c index 3b9c4d271..422b51427 100755 --- a/crypto777/OS_portable.c +++ b/crypto777/OS_portable.c @@ -249,13 +249,13 @@ void *OS_portable_tmpalloc(char *dirname,char *name,struct OS_memspace *mem,long if ( mem->totalsize > origsize ) size = mem->totalsize; else size = origsize; - fprintf(stderr,"filealloc.(%s) -> ",fname); + printf("filealloc.(%s) -> ",fname); if ( OS_filealloc(&mem->M,fname,mem,size) == 0 ) { printf("couldnt map tmpfile %s\n",fname); return(0); } - fprintf(stderr,"created\n"); + printf("created\n"); } ptr = iguana_memalloc(mem,origsize,1); if ( mem->threadsafe != 0 ) diff --git a/crypto777/OS_portable.h b/crypto777/OS_portable.h index 84ba44794..3d90521bd 100755 --- a/crypto777/OS_portable.h +++ b/crypto777/OS_portable.h @@ -40,7 +40,7 @@ #include #include -#ifdef WIN32 +#ifdef _WIN32 #define sleep(x) Sleep(1000*(x)) #include "../OSlibs/win/mingw.h" #include "../OSlibs/win/mman.h" @@ -134,7 +134,7 @@ int32_t hseek(HUFF *hp,int32_t offset,int32_t mode); struct allocitem { uint32_t allocsize,type; } PACKED; struct queueitem { struct queueitem *next,*prev; uint32_t allocsize,type; } PACKED; -struct stritem { struct queueitem DL; char str[]; }; +struct stritem { struct queueitem DL; void **retptrp; uint32_t expiration; char str[]; }; typedef struct queue { @@ -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); diff --git a/crypto777/OS_time.c b/crypto777/OS_time.c index 03489f03e..b5d2efc09 100755 --- a/crypto777/OS_time.c +++ b/crypto777/OS_time.c @@ -357,7 +357,7 @@ struct tai tai_now() #ifndef DISABLE_LEAPS UTC_ADJUST = -36; #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); + //printf("TAINOW.%llu %03.3f UTC.%u vs %u [diff %d]\n",(long long)t.x,t.millis,First_utc,tai2utc(t),UTC_ADJUST); } return(t); } diff --git a/crypto777/bitcoind_RPC.c b/crypto777/bitcoind_RPC.c index fd27643d3..f624cd342 100755 --- a/crypto777/bitcoind_RPC.c +++ b/crypto777/bitcoind_RPC.c @@ -13,9 +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 #include @@ -30,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); /************************************************************************ @@ -54,17 +72,20 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char * long i,j,len; char *retstr = 0; cJSON *json,*result,*error; +#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 ) { if ( strcmp(command,"signrawtransaction") != 0 && strcmp(command,"getrawtransaction") != 0 ) - printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr); + printf("<<<<<<<<<<< A bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,params); return(rpcstr); } json = cJSON_Parse(rpcstr); if ( json == 0 ) { - printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s can't parse.(%s) params.(%s)\n",debugstr,command,rpcstr,params); + printf("<<<<<<<<<<< B bitcoind_RPC: %s post_process_bitcoind_RPC.%s can't parse.(%s) params.(%s)\n",debugstr,command,rpcstr,params); free(rpcstr); return(0); } @@ -74,7 +95,7 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char * { if ( (error->type&0xff) == cJSON_NULL && (result->type&0xff) != cJSON_NULL ) { - retstr = cJSON_Print(result); + retstr = jprint(result,0); len = strlen(retstr); if ( retstr[0] == '"' && retstr[len-1] == '"' ) { @@ -118,8 +139,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; @@ -143,14 +165,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 ) @@ -205,45 +237,46 @@ try_again: 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); + free(chunk.memory); //free(s.ptr); 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(chunk.memory);//free(s.ptr); return(0); } - free(s.ptr); + free(chunk.memory);//free(s.ptr); sleep((1< (%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"); @@ -290,13 +323,23 @@ 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); + 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 ) @@ -371,3 +414,4 @@ void *curl_post(void **cHandlep,char *url,char *userpass,char *postfields,char * return(clonestr("{\"error\":\"curl is disabled\"}")); } #endif +#endif diff --git a/crypto777/cJSON.c b/crypto777/cJSON.c index 8bce48b19..54df964f5 100755 --- a/crypto777/cJSON.c +++ b/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;ichild,*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;it 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 && ichild=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); +} diff --git a/crypto777/crypto777.sources b/crypto777/crypto777.sources index 7c30d39d4..3d5142a01 100755 --- a/crypto777/crypto777.sources +++ b/crypto777/crypto777.sources @@ -36,11 +36,11 @@ TRANSPORTS_TCPMUX = $(NANOSRC)/transports/tcpmux/atcpmux.c $(NANOSRC)/transports NANOMSG_PROTOCOLS = $(PROTOCOLS_UTILS) $(PROTOCOLS_PUBSUB) $(PROTOCOLS_PAIR) $(PROTOCOLS_REQREP) $(PROTOCOLS_BUS) $(PROTOCOLS_PIPELINE) $(PROTOCOLS_SURVEY) -NANOMSG_TRANSPORTS = $(TRANSPORTS_UTILS) $(TRANSPORTS_TCP) $(TRANSPORTS_IPC) $(TRANSPORTS_INPROC) +NANOMSG_TRANSPORTS = $(TRANSPORTS_UTILS) $(TRANSPORTS_TCP) $(TRANSPORTS_IPC) $(TRANSPORTS_INPROC) $(TRANSPORTS_WS) NANOMSG = $(NANOMSG_CORE) $(NANOMSG_AIO) $(NANOMSG_UTILS) $(NANOMSG_DEVICES) $(NANOMSG_TRANSPORTS) $(NANOMSG_PROTOCOLS) -JPEG_SRCS := ../crypto777/jpeg/jaricom.c ../crypto777/jpeg/jcapimin.c ../crypto777/jpeg/jcapistd.c ../crypto777/jpeg/jcarith.c ../crypto777/jpeg/jccoefct.c ../crypto777/jpeg/jccolor.c ../crypto777/jpeg/jcdctmgr.c ../crypto777/jpeg/jchuff.c ../crypto777/jpeg/jcinit.c ../crypto777/jpeg/jcmainct.c ../crypto777/jpeg/jcmarker.c ../crypto777/jpeg/jcmaster.c ../crypto777/jpeg/jcomapi.c ../crypto777/jpeg/jcparam.c ../crypto777/jpeg/jcprepct.c ../crypto777/jpeg/jcsample.c ../crypto777/jpeg/jctrans.c ../crypto777/jpeg/jdapimin.c ../crypto777/jpeg/jdapistd.c ../crypto777/jpeg/jdarith.c ../crypto777/jpeg/jdatadst.c ../crypto777/jpeg/jdatasrc.c ../crypto777/jpeg/jdcoefct.c ../crypto777/jpeg/jdcolor.c ../crypto777/jpeg/jddctmgr.c ../crypto777/jpeg/jdhuff.c ../crypto777/jpeg/jdinput.c ../crypto777/jpeg/jdmainct.c ../crypto777/jpeg/jdmarker.c ../crypto777/jpeg/jdmaster.c ../crypto777/jpeg/jdmerge.c ../crypto777/jpeg/jdpostct.c ../crypto777/jpeg/jdsample.c ../crypto777/jpeg/jdtrans.c ../crypto777/jpeg/jerror.c ../crypto777/jpeg/jfdctflt.c ../crypto777/jpeg/jfdctfst.c ../crypto777/jpeg/jfdctint.c ../crypto777/jpeg/jidctflt.c ../crypto777/jpeg/jidctfst.c ../crypto777/jpeg/jidctint.c ../crypto777/jpeg/jquant1.c ../crypto777/jpeg/jquant2.c ../crypto777/jpeg/jutils.c ../crypto777/jpeg/misc/jmemnobs.c ../crypto777/jpeg/jmemmgr.c +JPEG_SRCS = ../crypto777/jpeg/jaricom.c ../crypto777/jpeg/jcapimin.c ../crypto777/jpeg/jcapistd.c ../crypto777/jpeg/jcarith.c ../crypto777/jpeg/jccoefct.c ../crypto777/jpeg/jccolor.c ../crypto777/jpeg/jcdctmgr.c ../crypto777/jpeg/jchuff.c ../crypto777/jpeg/jcinit.c ../crypto777/jpeg/jcmainct.c ../crypto777/jpeg/jcmarker.c ../crypto777/jpeg/jcmaster.c ../crypto777/jpeg/jcomapi.c ../crypto777/jpeg/jcparam.c ../crypto777/jpeg/jcprepct.c ../crypto777/jpeg/jcsample.c ../crypto777/jpeg/jctrans.c ../crypto777/jpeg/jdapimin.c ../crypto777/jpeg/jdapistd.c ../crypto777/jpeg/jdarith.c ../crypto777/jpeg/jdatadst.c ../crypto777/jpeg/jdatasrc.c ../crypto777/jpeg/jdcoefct.c ../crypto777/jpeg/jdcolor.c ../crypto777/jpeg/jddctmgr.c ../crypto777/jpeg/jdhuff.c ../crypto777/jpeg/jdinput.c ../crypto777/jpeg/jdmainct.c ../crypto777/jpeg/jdmarker.c ../crypto777/jpeg/jdmaster.c ../crypto777/jpeg/jdmerge.c ../crypto777/jpeg/jdpostct.c ../crypto777/jpeg/jdsample.c ../crypto777/jpeg/jdtrans.c ../crypto777/jpeg/jerror.c ../crypto777/jpeg/jfdctflt.c ../crypto777/jpeg/jfdctfst.c ../crypto777/jpeg/jfdctint.c ../crypto777/jpeg/jidctflt.c ../crypto777/jpeg/jidctfst.c ../crypto777/jpeg/jidctint.c ../crypto777/jpeg/jquant1.c ../crypto777/jpeg/jquant2.c ../crypto777/jpeg/jutils.c ../crypto777/jpeg/misc/jmemnobs.c ../crypto777/jpeg/jmemmgr.c -CRYPTO777_SRCS := ../crypto777/tweetnacl.c ../crypto777/scrypt.c ../crypto777/bitcoind_RPC.c ../crypto777/cJSON.c ../crypto777/iguana_utils.c ../crypto777/OS_nonportable.c ../crypto777/curve25519-donna.c ../crypto777/inet.c ../crypto777/OS_portable.c ../crypto777/curve25519.c ../crypto777/OS_time.c ../crypto777/hmac_sha512.c ../crypto777/ramcoder.c ../crypto777/SaM.c ../crypto777/iguana_OS.c ../crypto777/iguana_serdes.c $(JPEG_SRCS) $(NANOMSG) +CRYPTO777_SRCS = ../crypto777/tweetnacl.c ../crypto777/scrypt.c ../crypto777/bitcoind_RPC.c ../crypto777/cJSON.c ../crypto777/iguana_utils.c ../crypto777/OS_nonportable.c ../crypto777/curve25519-donna.c ../crypto777/inet.c ../crypto777/OS_portable.c ../crypto777/curve25519.c ../crypto777/OS_time.c ../crypto777/hmac_sha512.c ../crypto777/ramcoder.c ../crypto777/SaM.c ../crypto777/iguana_OS.c ../crypto777/iguana_serdes.c $(JPEG_SRCS) $(NANOMSG) diff --git a/crypto777/iguana_OS.c b/crypto777/iguana_OS.c index 504905ee1..2000651a9 100755 --- a/crypto777/iguana_OS.c +++ b/crypto777/iguana_OS.c @@ -30,7 +30,7 @@ char *OS_mvstr() { -#ifdef __WIN32 +#ifdef _WIN32 return("rename"); #else return("mv"); @@ -297,11 +297,11 @@ void *queue_dequeue(queue_t *queue)//,int32_t offsetflag) void *queue_delete(queue_t *queue,struct queueitem *copy,int32_t copysize,int32_t freeitem) { struct allocitem *ptr; - struct queueitem *item = 0; + struct queueitem *tmp,*item = 0; lock_queue(queue); if ( queue->list != 0 ) { - DL_FOREACH(queue->list,item) + DL_FOREACH_SAFE(queue->list,item,tmp) { ptr = (void *)((long)item - sizeof(struct allocitem)); if ( item == copy || (ptr->allocsize == copysize && memcmp((void *)((long)item + sizeof(struct queueitem)),(void *)((long)item + sizeof(struct queueitem)),copysize) == 0) ) @@ -321,11 +321,11 @@ void *queue_delete(queue_t *queue,struct queueitem *copy,int32_t copysize,int32_ void *queue_free(queue_t *queue) { - struct queueitem *item = 0; + struct queueitem *tmp,*item = 0; lock_queue(queue); if ( queue->list != 0 ) { - DL_FOREACH(queue->list,item) + DL_FOREACH_SAFE(queue->list,item,tmp) { DL_DELETE(queue->list,item); myfree(item,sizeof(struct queueitem)); @@ -338,11 +338,11 @@ void *queue_free(queue_t *queue) void *queue_clone(queue_t *clone,queue_t *queue,int32_t size) { - struct queueitem *ptr,*item = 0; + struct queueitem *ptr,*tmp,*item = 0; lock_queue(queue); if ( queue->list != 0 ) { - DL_FOREACH(queue->list,item) + DL_FOREACH_SAFE(queue->list,item,tmp) { ptr = mycalloc('c',1,sizeof(*ptr)); memcpy(ptr,item,size); @@ -659,7 +659,7 @@ int64_t OS_copyfile(char *src,char *dest,int32_t cmpflag) { if ( (destfp= fopen(OS_compatible_path(dest),"wb")) != 0 ) { -#ifdef WIN32 +#ifdef _WIN32 allocsize = 1024 * 1024 * 8L; #else allocsize = 1024 * 1024 * 128L; @@ -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 diff --git a/crypto777/iguana_serdes.c b/crypto777/iguana_serdes.c index 996743c78..a0b905bfd 100755 --- a/crypto777/iguana_serdes.c +++ b/crypto777/iguana_serdes.c @@ -13,10 +13,11 @@ * * ******************************************************************************/ +#ifndef FROM_JS #include "OS_portable.h" #include "../includes/curve25519.h" -// threadsafe +// threadsafe int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp) { int32_t i; uint64_t x; @@ -213,3 +214,4 @@ int32_t iguana_rwmem(int32_t rwflag,uint8_t *serialized,int32_t len,void *endian else memcpy(serialized,endianedp,len); return(len); } +#endif diff --git a/crypto777/iguana_utils.c b/crypto777/iguana_utils.c index 5b0ce5743..2e8f8e18b 100755 --- a/crypto777/iguana_utils.c +++ b/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 diff --git a/crypto777/jpeg/unix/jmemname.c b/crypto777/jpeg/unix/jmemname.c index 9db4408eb..fd09935aa 100755 --- a/crypto777/jpeg/unix/jmemname.c +++ b/crypto777/jpeg/unix/jmemname.c @@ -11,7 +11,7 @@ * Also, the problem of determining the amount of memory available * is shoved onto the user. */ -#ifndef WIN32 +#ifndef _WIN32 #include #endif diff --git a/crypto777/nanosrc/aio/usock_posix.c b/crypto777/nanosrc/aio/usock_posix.c index 44a8acb65..2f85e559c 100755 --- a/crypto777/nanosrc/aio/usock_posix.c +++ b/crypto777/nanosrc/aio/usock_posix.c @@ -167,7 +167,7 @@ int nn_usock_start (struct nn_usock *self, int domain, int type, int protocol) s = socket (domain, type, protocol); if (nn_slow (s < 0)) return -errno; - //PNACL_message("got socket s.%d\n",s); + //printf("got socket s.%d\n",s); nn_usock_init_from_fd (self, s); /* Start the state machine. */ @@ -286,11 +286,14 @@ int nn_usock_bind (struct nn_usock *self, const struct sockaddr *addr, /* Allow re-using the address. */ opt = 1; + printf("call setsockopt %d SOL_SOCKET.%d SO_REUSEADDR.%d in nn_usock_bind\n",self->s,SOL_SOCKET,SO_REUSEADDR); rc = setsockopt (self->s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)); - errno_assert (rc == 0); + printf("called setsockopt in nn_usock_bind returns %d\n",rc); + // ignore SO_REUSEADDR failures + //errno_assert (rc == 0); rc = bind (self->s, addr, (socklen_t) addrlen); - //printf("usock.%d -> bind rc.%d errno.%d %s\n",self->s,rc,errno,nn_strerror(errno)); + printf("usock.%d -> bind rc.%d errno.%d %s\n",self->s,rc,errno,nn_strerror(errno)); if (nn_slow (rc != 0)) return -errno; @@ -306,7 +309,7 @@ int nn_usock_listen (struct nn_usock *self, int backlog) /* Start listening for incoming connections. */ rc = listen (self->s, backlog); - //printf("usock.%d -> listen rc.%d errno.%d %s\n",self->s,rc,errno,nn_strerror(errno)); + printf("usock.%d -> listen rc.%d errno.%d %s\n",self->s,rc,errno,nn_strerror(errno)); if (nn_slow (rc != 0)) return -errno; @@ -333,7 +336,7 @@ void nn_usock_accept (struct nn_usock *self, struct nn_usock *listener) #else s = accept (listener->s, NULL, NULL); #endif - //printf("usock.%d -> accept errno.%d s.%d %s\n",self->s,errno,s,nn_strerror(errno)); + printf("usock.%d -> accept errno.%d s.%d %s\n",self->s,errno,s,nn_strerror(errno)); /* Immediate success. */ if (nn_fast (s >= 0)) { @@ -366,7 +369,7 @@ void nn_usock_accept (struct nn_usock *self, struct nn_usock *listener) and allow processing other events in the meantime */ if (nn_slow (errno != EAGAIN && errno != EWOULDBLOCK && errno != ECONNABORTED && errno != listener->errnum)) { - PNACL_message("listen errno.%d\n",errno); + printf("listen errno.%d\n",errno); listener->errnum = errno; listener->state = NN_USOCK_STATE_ACCEPTING_ERROR; nn_fsm_raise (&listener->fsm, @@ -393,7 +396,7 @@ void nn_usock_connect (struct nn_usock *self, const struct sockaddr *addr, /* Do the connect itself. */ rc = connect(self->s,addr,(socklen_t)addrlen); - //printf("usock.%d <- connect (%llx) rc.%d errno.%d %s\n",self->s,*(long long *)addr,rc,errno,nn_strerror(errno)); + printf("usock.%d <- connect (%llx) rc.%d errno.%d %s\n",self->s,*(long long *)addr,rc,errno,nn_strerror(errno)); /* Immediate success. */ if ( nn_fast(rc == 0) ) { @@ -404,7 +407,7 @@ void nn_usock_connect (struct nn_usock *self, const struct sockaddr *addr, if ( nn_slow(errno != EINPROGRESS) ) { self->errnum = errno; - PNACL_message("error.%d not EINPROGRESS\n",errno); + printf("error.%d not EINPROGRESS\n",errno); nn_fsm_action (&self->fsm, NN_USOCK_ACTION_ERROR); return; } @@ -433,13 +436,13 @@ void nn_usock_send (struct nn_usock *self, const struct nn_iovec *iov, self->out.iov [out].iov_base = iov [i].iov_base; self->out.iov [out].iov_len = iov [i].iov_len; out++; - //PNACL_message("{%d} ",(int)iov [i].iov_len); + printf("{%d} ",(int)iov [i].iov_len); } - //PNACL_message("iov[%d]\n",out); self->out.hdr.msg_iovlen = out; /* Try to send the data immediately. */ rc = nn_usock_send_raw (self, &self->out.hdr); + printf("iov[%d] nn_usock_send_raw -> rc.%d\n",out,rc); /* Success. */ if (nn_fast (rc == 0)) { @@ -472,17 +475,17 @@ void nn_usock_recv (struct nn_usock *self, void *buf, size_t len, int *fd) rc = nn_usock_recv_raw (self, buf, &nbytes); if (nn_slow (rc < 0)) { errnum_assert (rc == -ECONNRESET, -rc); - //PNACL_message("rc.%d vs ECONNRESET\n",rc,ECONNRESET); + //printf("rc.%d vs ECONNRESET\n",rc,ECONNRESET); nn_fsm_action (&self->fsm, NN_USOCK_ACTION_ERROR); return; } //int i; //for (i=0; i<16&&ifsm, &self->event_received, NN_USOCK_RECEIVED); return; } @@ -1021,19 +1024,19 @@ int32_t nn_getiovec_size(uint8_t *buf,int32_t maxlen,struct msghdr *hdr) if ( nn_slow(iov->iov_len == NN_MSG) ) { errno = EINVAL; - PNACL_message("ERROR: iov->iov_len == NN_MSG\n"); + printf("ERROR: iov->iov_len == NN_MSG\n"); return(-1); } if ( nn_slow(!iov->iov_base && iov->iov_len) ) { errno = EFAULT; - PNACL_message("ERROR: !iov->iov_base && iov->iov_len\n"); + printf("ERROR: !iov->iov_base && iov->iov_len\n"); return(-1); } if ( maxlen > 0 && nn_slow(size + iov->iov_len > maxlen) ) { errno = EINVAL; - PNACL_message("ERROR: sz.%d + iov->iov_len.%d < maxlen.%d\n",(int32_t)size,(int32_t)iov->iov_len,maxlen); + printf("ERROR: sz.%d + iov->iov_len.%d < maxlen.%d\n",(int32_t)size,(int32_t)iov->iov_len,maxlen); return(-1); } if ( iov->iov_len > 0 ) @@ -1054,7 +1057,7 @@ ssize_t mysendmsg(int32_t usock,struct msghdr *hdr,int32_t flags) clen = hdr->msg_controllen; if ( hdr->msg_control == 0 ) clen = 0; - nn_assert(clen == 0); // no supporty control messagies + nn_assert(clen == 0); // no support control messagies if ( veclen > sizeof(_buf) ) // - clen - 5) ) buf = malloc(veclen);// + clen + 5); else buf = _buf; @@ -1069,10 +1072,10 @@ ssize_t mysendmsg(int32_t usock,struct msghdr *hdr,int32_t flags) if ( nn_getiovec_size(&buf[offset],veclen,hdr) == veclen ) { nbytes = send(usock,buf,offset + veclen,0); - //PNACL_message(">>>>>>>>> send.[%d %d %d %d] (n.%d v.%d c.%d)-> usock.%d nbytes.%d\n",buf[offset],buf[offset+1],buf[offset+2],buf[offset+3],(int32_t)offset+veclen,veclen,clen,usock,(int32_t)nbytes); + printf(">>>>>>>>> send.[%d %d %d %d] (n.%d v.%d c.%d)-> usock.%d nbytes.%d\n",buf[offset],buf[offset+1],buf[offset+2],buf[offset+3],(int32_t)offset+veclen,veclen,clen,usock,(int32_t)nbytes); if ( nbytes != offset + veclen ) { - //PNACL_message("nbytes.%d != offset.%d veclen.%d errno.%d usock.%d\n",(int32_t)nbytes,(int32_t)offset,veclen,errno,usock); + printf("nbytes.%d != offset.%d veclen.%d errno.%d usock.%d\n",(int32_t)nbytes,(int32_t)offset,veclen,errno,usock); } if ( nbytes >= offset ) nbytes -= offset; @@ -1080,19 +1083,19 @@ ssize_t mysendmsg(int32_t usock,struct msghdr *hdr,int32_t flags) else { err = -errno; - PNACL_message("mysendmsg: unexpected nn_getiovec_size error %d\n",err); + printf("mysendmsg: unexpected nn_getiovec_size error %d\n",err); } if ( buf != _buf ) free(buf); if ( err != 0 ) { - PNACL_message("nn_usock_send_raw errno.%d err.%d\n",errno,err); + printf("nn_usock_send_raw errno.%d err.%d\n",errno,err); return(-errno); } } else { - PNACL_message("nn_usock_send_raw errno.%d invalid iovec size\n",errno); + printf("nn_usock_send_raw errno.%d invalid iovec size\n",errno); return(-errno); } return(nbytes); @@ -1104,32 +1107,32 @@ ssize_t myrecvmsg(int32_t usock,struct msghdr *hdr,int32_t flags,int32_t len) iov = hdr->msg_iov; /*if ( (n= (int32_t)recv(usock,lens,sizeof(lens),0)) != sizeof(lens) ) { - PNACL_message("error getting veclen/clen n.%d vs %d from usock.%d\n",n,(int32_t)sizeof(lens),usock); + printf("error getting veclen/clen n.%d vs %d from usock.%d\n",n,(int32_t)sizeof(lens),usock); return(0); - } else PNACL_message("GOT %d bytes from usock.%d\n",n,usock); + } else printf("GOT %d bytes from usock.%d\n",n,usock); offset = 0; veclen = lens[offset++]; veclen |= ((int32_t)lens[offset++] << 8); veclen |= ((int32_t)lens[offset++] << 16); clen = lens[offset++]; clen |= ((int32_t)lens[offset++] << 8); - PNACL_message("veclen.%d clen.%d waiting in usock.%d\n",veclen,clen,usock); + printf("veclen.%d clen.%d waiting in usock.%d\n",veclen,clen,usock); if ( clen > 0 ) { if ( (cbytes= (int32_t)recv(usock,hdr->msg_control,clen,0)) != clen ) { - PNACL_message("myrecvmsg: unexpected cbytes.%d vs clen.%d\n",cbytes,clen); + printf("myrecvmsg: unexpected cbytes.%d vs clen.%d\n",cbytes,clen); } } else cbytes = 0;*/ hdr->msg_controllen = 0; if ( (nbytes= (int32_t)recv(usock,iov->iov_base,len,0)) != len ) { - //PNACL_message("myrecvmsg: partial nbytes.%d vs veclen.%d\n",(int32_t)nbytes,len); + //printf("myrecvmsg: partial nbytes.%d vs veclen.%d\n",(int32_t)nbytes,len); } - //PNACL_message("GOT nbytes.%d of len.%d from usock.%d\n",(int32_t)nbytes,len,usock); + //printf("GOT nbytes.%d of len.%d from usock.%d\n",(int32_t)nbytes,len,usock); if ( 0 && nbytes > 0 ) { - PNACL_message("got nbytes.%d from usock.%d [%d %d %d %d]\n",(int32_t)nbytes,usock,((uint8_t *)iov->iov_base)[0],((uint8_t *)iov->iov_base)[1],((uint8_t *)iov->iov_base)[2],((uint8_t *)iov->iov_base)[3]); + printf("got nbytes.%d from usock.%d [%d %d %d %d]\n",(int32_t)nbytes,usock,((uint8_t *)iov->iov_base)[0],((uint8_t *)iov->iov_base)[1],((uint8_t *)iov->iov_base)[2],((uint8_t *)iov->iov_base)[3]); } return(nbytes); } @@ -1144,7 +1147,7 @@ static int nn_usock_send_raw (struct nn_usock *self, struct msghdr *hdr) nbytes = sendmsg(self->s,hdr,MSG_NOSIGNAL); #else nbytes = sendmsg(self->s,hdr,0); - //printf("sendmsg nbytes.%d\n",(int32_t)nbytes); + printf("nn_usock_send_raw nbytes.%d\n",(int32_t)nbytes); #endif #endif /* Handle errors. */ @@ -1199,13 +1202,13 @@ int32_t nn_process_cmsg(struct nn_usock *self,struct msghdr *hdr) memcpy(&retval,(int32_t *)CMSG_DATA(cmsg),sizeof(int32_t)); if ( self->in.pfd ) { - PNACL_message("CMSG set self->in.pfd (%d)\n",retval); + printf("CMSG set self->in.pfd (%d)\n",retval); *self->in.pfd = retval; self->in.pfd = NULL; } else { - PNACL_message("CMSG nn_closefd(%d)\n",retval); + printf("CMSG nn_closefd(%d)\n",retval); nn_closefd(retval); } break; @@ -1257,7 +1260,7 @@ static int nn_usock_recv_raw(struct nn_usock *self, void *buf, size_t *len) if (!length) return 0; } -#ifdef NN_USE_MYMSG +#if NN_USE_MYMSG usebuf = (length >= NN_USOCK_BATCH_SIZE); #else usebuf = (length >= NN_USOCK_BATCH_SIZE); @@ -1286,7 +1289,7 @@ static int nn_usock_recv_raw(struct nn_usock *self, void *buf, size_t *len) #if NN_USE_MYMSG nbytes = myrecvmsg(self->s,&hdr,0,(int32_t)iov.iov_len); - //printf("got nbytes.%d from recvmsg errno.%d %s\n",(int32_t)nbytes,errno,nn_strerror(errno)); + printf("got nbytes.%d from recvmsg errno.%d %s\n",(int32_t)nbytes,errno,nn_strerror(errno)); #else nbytes = recvmsg (self->s, &hdr, 0); #endif @@ -1310,7 +1313,7 @@ static int nn_usock_recv_raw(struct nn_usock *self, void *buf, size_t *len) } } else if ( hdr.msg_controllen > 0 ) nn_process_cmsg(self,&hdr); - //PNACL_message("nbytes.%d length.%d *len %d\n",(int)nbytes,(int)length,(int)*len); + printf("nbytes.%d length.%d *len %d\n",(int)nbytes,(int)length,(int)*len); // If the data were received directly into the place we can return straight away if ( usebuf != 0 ) diff --git a/crypto777/nanosrc/aio/usock_posix.c_dev b/crypto777/nanosrc/aio/usock_posix.c_dev index 954b3045f..244b0753c 100755 --- a/crypto777/nanosrc/aio/usock_posix.c_dev +++ b/crypto777/nanosrc/aio/usock_posix.c_dev @@ -31,11 +31,11 @@ #include #include #include -#ifndef __PNACL +//#ifndef __PNACL #include -#else -#include -#endif +//#else +//#include +//#endif #define NN_USOCK_STATE_IDLE 1 #define NN_USOCK_STATE_STARTING 2 @@ -287,7 +287,8 @@ int nn_usock_bind (struct nn_usock *self, const struct sockaddr *addr, /* Allow re-using the address. */ opt = 1; rc = setsockopt (self->s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)); - errno_assert (rc == 0); + // ignore SO_REUSEADDR failures + //errno_assert (rc == 0); rc = bind (self->s, addr, (socklen_t) addrlen); if (nn_slow (rc != 0)) @@ -999,7 +1000,7 @@ static int32_t nn_usock_send_raw(struct nn_usock *self,struct msghdr *hdr) #else nbytes = sendmsg(self->s,hdr,0); #endif - PostMessage("nn_usock_send_raw nbytes.%d for sock.%d\n",(int32_t)nbytes,self->s); + printf("nn_usock_send_raw nbytes.%d for sock.%d\n",(int32_t)nbytes,self->s); if ( nn_slow(nbytes < 0) ) // Handle errors { if ( nn_fast(errno == EAGAIN || errno == EWOULDBLOCK) ) diff --git a/crypto777/nanosrc/aio/usock_posix.h b/crypto777/nanosrc/aio/usock_posix.h index 4a189a2bb..9286dcf24 100755 --- a/crypto777/nanosrc/aio/usock_posix.h +++ b/crypto777/nanosrc/aio/usock_posix.h @@ -25,11 +25,7 @@ #include #include -#ifndef __PNACL #include -#else -#include -#endif struct nn_usock { diff --git a/crypto777/nanosrc/aio/usock_win.c b/crypto777/nanosrc/aio/usock_win.c index 5eedfb60f..6e9f92427 100755 --- a/crypto777/nanosrc/aio/usock_win.c +++ b/crypto777/nanosrc/aio/usock_win.c @@ -126,7 +126,7 @@ int nn_usock_start (struct nn_usock *self, int domain, int type, int protocol) #if defined HANDLE_FLAG_INHERIT BOOL brc; #endif - +printf("nn_usock_start protocol %d\n",protocol); /* NamedPipes aren't sockets. They don't need all the socket initialisation stuff. */ if (domain != AF_UNIX) { diff --git a/crypto777/nanosrc/aio/worker_posix.c b/crypto777/nanosrc/aio/worker_posix.c index 070a87a86..550aa31f4 100755 --- a/crypto777/nanosrc/aio/worker_posix.c +++ b/crypto777/nanosrc/aio/worker_posix.c @@ -102,29 +102,28 @@ void nn_worker_task_term (struct nn_worker_task *self) int nn_worker_init(struct nn_worker *self) { int32_t rc; - PNACL_message("nn_worker_init %p\n",self); - //sleep(1); + //PNACL_msg("nn_worker_init %p\n",self); rc = nn_efd_init(&self->efd); - PNACL_message("efd init: rc.%d\n",rc); + //PNACL_msg("efd init: rc.%d\n",rc); if ( rc < 0 ) return rc; - PNACL_message("nn_mutex_init\n"); + //PNACL_msg("nn_mutex_init\n"); nn_mutex_init(&self->sync); - PNACL_message("nn_queue_init\n"); + //PNACL_msg("nn_queue_init\n"); nn_queue_init(&self->tasks); - PNACL_message("nn_queue_item_init\n"); + //PNACL_msg("nn_queue_item_init\n"); nn_queue_item_init(&self->stop); - PNACL_message("nn_poller_init\n"); + //PNACL_msg("nn_poller_init\n"); nn_poller_init(&self->poller); - PNACL_message("nn_poller_add\n"); + //PNACL_msg("nn_poller_add\n"); nn_poller_add(&self->poller,nn_efd_getfd(&self->efd),&self->efd_hndl); - PNACL_message("nn_poller_set_in\n"); + //PNACL_msg("nn_poller_set_in\n"); nn_poller_set_in(&self->poller, &self->efd_hndl); - PNACL_message("nn_timerset_init\n"); + //PNACL_msg("nn_timerset_init\n"); nn_timerset_init(&self->timerset); - PNACL_message("nn_thread_init\n"); + //PNACL_msg("nn_thread_init\n"); nn_thread_init(&self->thread,nn_worker_routine, self); - PNACL_message("finished nn_worker_init\n"); + //PNACL_msg("finished nn_worker_init\n"); return 0; } @@ -174,9 +173,11 @@ static void nn_worker_routine (void *arg) struct nn_worker_task *task; struct nn_worker_fd *fd; struct nn_worker_timer *timer; - PNACL_message("nn_worker_routine started\n"); + printf("nn_worker_routine started\n"); self = (struct nn_worker*) arg; +#ifndef FROM_JS while ( 1 ) // Infinite loop. It will be interrupted only when the object is shut down. +#endif { // Wait for new events and/or timeouts. rc = nn_poller_wait(&self->poller,nn_timerset_timeout (&self->timerset)); @@ -186,7 +187,7 @@ static void nn_worker_routine (void *arg) rc = nn_timerset_event(&self->timerset, &thndl); if ( rc == -EAGAIN ) break; - PNACL_message("nn_worker process expired user\n"); + printf("nn_worker process expired user\n"); errnum_assert(rc == 0, -rc); timer = nn_cont(thndl, struct nn_worker_timer, hndl); nn_ctx_enter(timer->owner->ctx); @@ -198,7 +199,7 @@ static void nn_worker_routine (void *arg) rc = nn_poller_event(&self->poller,&pevent,&phndl); // Get next poller event, such as IN or OUT if ( nn_slow(rc == -EAGAIN) ) break; - PNACL_message("nn_worker process all events from the poller\n"); + printf("nn_worker process all events from the poller\n"); if ( phndl == &self->efd_hndl ) // If there are any new incoming worker tasks, process them { nn_assert (pevent == NN_POLLER_IN); @@ -213,31 +214,36 @@ static void nn_worker_routine (void *arg) item = nn_queue_pop(&tasks); // Next worker task if ( nn_slow(!item) ) break; - PNACL_message("nn_worker next worker task\n"); + printf("nn_worker next worker task\n"); if ( nn_slow(item == &self->stop) ) // If the worker thread is asked to stop, do so { nn_queue_term(&tasks); return; } // It's a user-defined task. Notify the user that it has arrived in the worker thread - PNACL_message("nn_worker user defined task\n"); + printf("nn_worker user defined task\n"); task = nn_cont(item,struct nn_worker_task,item); nn_ctx_enter(task->owner->ctx); nn_fsm_feed(task->owner,task->src,NN_WORKER_TASK_EXECUTE,task); nn_ctx_leave (task->owner->ctx); } nn_queue_term (&tasks); +#ifdef FROM_JS + printf("done worker ITER\n"); + return; +#else continue; +#endif } - PNACL_message("nn_worker true i/o, invoke handler\n"); + printf("nn_worker true i/o, invoke handler\n"); fd = nn_cont(phndl,struct nn_worker_fd,hndl); // It's a true I/O event. Invoke the handler - PNACL_message("nn_worker true i/o, fd.%p\n",fd); + printf("nn_worker true i/o, fd.%p\n",fd); nn_ctx_enter(fd->owner->ctx); - PNACL_message("nn_worker true i/o, after nn_ctx_enter\n"); + printf("nn_worker true i/o, after nn_ctx_enter\n"); nn_fsm_feed(fd->owner,fd->src,pevent,fd); - PNACL_message("nn_worker true i/o, after nn_fsm_feed leave.%p\n",fd->owner->ctx); + printf("nn_worker true i/o, after nn_fsm_feed leave.%p\n",fd->owner->ctx); nn_ctx_leave(fd->owner->ctx); - PNACL_message("nn_worker true i/o, after nn_ctx_leave\n"); + printf("nn_worker true i/o, after nn_ctx_leave\n"); } } } diff --git a/crypto777/nanosrc/core/global.c b/crypto777/nanosrc/core/global.c index e8f750f88..83b8e63d0 100755 --- a/crypto777/nanosrc/core/global.c +++ b/crypto777/nanosrc/core/global.c @@ -201,9 +201,9 @@ static void nn_global_add_transport (struct nn_transport *transport) static void nn_global_add_socktype (struct nn_socktype *socktype) { - PNACL_message("add socktype %p -> %p\n",socktype,&SELF.socktypes); + PNACL_msg("add socktype %p -> %p\n",socktype,&SELF.socktypes); nn_list_insert (&SELF.socktypes, &socktype->item,nn_list_end (&SELF.socktypes)); - PNACL_message("added socktype %p -> %p\n",socktype,&SELF.socktypes); + PNACL_msg("added socktype %p -> %p\n",socktype,&SELF.socktypes); } void nn_global_init (void) { @@ -218,7 +218,7 @@ void nn_global_init (void) nn_assert (LOBYTE (data.wVersion) == 2 && HIBYTE (data.wVersion) == 2); #endif - PNACL_message("nn_global_init\n"); + PNACL_msg("nn_global_init\n"); nn_alloc_init(); // Initialise the memory allocation subsystem nn_random_seed(); // Seed the pseudo-random number generator // Allocate the global table of SP sockets. @@ -227,7 +227,7 @@ void nn_global_init (void) for (i=0; imsg_iovlen < 0) ) { + printf("nn_sendmsg.(%d) emsgsize\n",s); errno = EMSGSIZE; return -1; } @@ -689,6 +692,7 @@ int32_t nn_sendmsg(int32_t s,const struct nn_msghdr *msghdr,int32_t flags) chunk = *(void **)msghdr->msg_iov[0].iov_base; if ( nn_slow(chunk == NULL) ) { + printf("nn_sendmsg.(%d) efault\n",s); errno = EFAULT; return -1; } @@ -731,6 +735,7 @@ int32_t nn_sendmsg(int32_t s,const struct nn_msghdr *msghdr,int32_t flags) } nn_assert(msghdr->msg_control == 0); // cant support msgs until sendmsg()/recvmsg() native to pnacl rc = nn_sock_send(SELF.socks[s],&msg,flags); // Send it further down the stack + printf("rc from nn_socksend.%d\n",rc); if ( nn_slow(rc < 0) ) { // If we are dealing with user-supplied buffer, detach it from the message object @@ -772,13 +777,13 @@ int32_t nn_recvmsg(int32_t s,struct nn_msghdr *msghdr,int32_t flags) chunk = nn_chunkref_getchunk(&msg.body); *(void **)(msghdr->msg_iov[0].iov_base) = chunk; sz = nn_chunk_size(chunk); - //PNACL_message("got message -> iov_base.%p sz.%d\n",msghdr->msg_iov[0].iov_base,(int32_t)sz); + //PNACL_msg("got message -> iov_base.%p sz.%d\n",msghdr->msg_iov[0].iov_base,(int32_t)sz); } else // Copy the message content into the supplied gather array { data = nn_chunkref_data(&msg.body); sz = nn_chunkref_size(&msg.body); - //PNACL_message("got message -> data.%p sz.%d\n",data,(int32_t)sz); + //PNACL_msg("got message -> data.%p sz.%d\n",data,(int32_t)sz); for (i=0; i!=msghdr->msg_iovlen; i++) { iov = &msghdr->msg_iov[i]; @@ -809,15 +814,17 @@ int32_t nn_recvmsg(int32_t s,struct nn_msghdr *msghdr,int32_t flags) int32_t nn_sendmsg(int32_t s,const struct nn_msghdr *msghdr,int32_t flags) { int32_t rc,i,nnmsg; size_t sz,spsz; struct nn_iovec *iov; struct nn_msg msg; void *chunk; struct nn_cmsghdr *cmsg; - //PNACL_message("nn_sendmsg.(%d) \n",s); + printf("nn_sendmsg.(%d) \n",s); NN_BASIC_CHECKS; if ( nn_slow(!msghdr) ) { + printf("nn_sendmsg.EINVAL\n"); errno = EINVAL; return -1; } if ( nn_slow(msghdr->msg_iovlen < 0) ) { + printf("nn_sendmsg.EMSGSIZE\n"); errno = EMSGSIZE; return -1; } @@ -827,6 +834,7 @@ int32_t nn_sendmsg(int32_t s,const struct nn_msghdr *msghdr,int32_t flags) if ( nn_slow(chunk == NULL) ) { errno = EFAULT; + printf("nn_sendmsg.EFAULT\n"); return -1; } sz = nn_chunk_size(chunk); @@ -905,6 +913,7 @@ int32_t nn_sendmsg(int32_t s,const struct nn_msghdr *msghdr,int32_t flags) /* Send it further down the stack. */ rc = nn_sock_send (SELF.socks [s], &msg, flags); + printf("nn_sock_send rc.%d\n",rc); if (nn_slow (rc < 0)) { /* If we are dealing with user-supplied buffer, detach it from @@ -928,7 +937,7 @@ int32_t nn_recvmsg(int32_t s,struct nn_msghdr *msghdr,int32_t flags) { struct nn_msg msg; uint8_t *data; struct nn_iovec *iov; void *chunk,*ctrl; struct nn_cmsghdr *chdr; int32_t i,rc; size_t sz,hdrssz,ctrlsz,spsz,sptotalsz; - //PNACL_message("nn_recvmsg.(%d) \n",s); + //PNACL_msg("nn_recvmsg.(%d) \n",s); NN_BASIC_CHECKS; if ( nn_slow(!msghdr) ) { @@ -940,7 +949,7 @@ int32_t nn_recvmsg(int32_t s,struct nn_msghdr *msghdr,int32_t flags) errno = EMSGSIZE; return -1; } - //PNACL_message("get a message from sock.%d\n",s); + //PNACL_msg("get a message from sock.%d\n",s); rc = nn_sock_recv(SELF.socks[s],&msg,flags); // Get a message if ( nn_slow(rc < 0) ) { @@ -952,13 +961,13 @@ int32_t nn_recvmsg(int32_t s,struct nn_msghdr *msghdr,int32_t flags) chunk = nn_chunkref_getchunk(&msg.body); *(void **)(msghdr->msg_iov[0].iov_base) = chunk; sz = nn_chunk_size(chunk); - //PNACL_message("got message -> iov_base.%p sz.%d\n",msghdr->msg_iov[0].iov_base,(int32_t)sz); + //PNACL_msg("got message -> iov_base.%p sz.%d\n",msghdr->msg_iov[0].iov_base,(int32_t)sz); } else // Copy the message content into the supplied gather array { data = nn_chunkref_data(&msg.body); sz = nn_chunkref_size (&msg.body); - //PNACL_message("got message -> data.%p sz.%d\n",data,(int32_t)sz); + //PNACL_msg("got message -> data.%p sz.%d\n",data,(int32_t)sz); for (i=0; i!=msghdr->msg_iovlen; i++) { iov = &msghdr->msg_iov[i]; @@ -1150,7 +1159,7 @@ static void nn_global_submit_errors (int i, struct nn_sock *s, len = snprintf (curbuf, buf_left, " nanomsg: Endpoint %d [%s] error: %s\n", ep->eid, nn_ep_getaddr (ep), nn_strerror (ep->last_errno)); - PNACL_message("%s\n",curbuf); + PNACL_msg("%s\n",curbuf); #endif if (buf_left < len) break; @@ -1244,12 +1253,12 @@ static int nn_global_create_ep (int s, const char *addr, int bind) return -EINVAL; protosz = delim - addr; addr += protosz + 3; -#ifdef NN_USE_MYMSG - if ( strncmp("inproc",proto,strlen("inproc")) != 0 && strncmp("ipc",proto,strlen("ipc")) != 0 && strncmp("tcp",proto,strlen("tcp")) != 0 ) +#if NN_USE_MYMSG + if ( strncmp("inproc",proto,strlen("inproc")) != 0 && strncmp("ipc",proto,strlen("ipc")) != 0 && strncmp("tcp",proto,strlen("tcp")) && strncmp("ws",proto,strlen("ws")) != 0 ) { - PNACL_message("only ipc, inproc and tcp transport is supported\n"); - printf("only ipc, inproc and tcp transport is supported\n"); - fprintf(stderr,"only ipc, inproc and tcp transport is supported\n"); + PNACL_msg("only ipc, inproc, ws and tcp transport is supported\n"); + printf("only ipc, inproc, ws and tcp transport is supported\n"); + fprintf(stderr,"only ipc, inproc, ws and tcp transport is supported\n"); exit(-1); return -EPROTONOSUPPORT; } @@ -1267,7 +1276,10 @@ static int nn_global_create_ep (int s, const char *addr, int bind) tp = NULL; } if ( !tp ) // The protocol specified doesn't match any known protocol + { + printf("unknown protocol\n"); return -EPROTONOSUPPORT; + } rc = nn_sock_add_ep (SELF.socks [s], tp, bind, addr); // Ask the socket to create the endpoint return rc; } @@ -1324,12 +1336,12 @@ static void nn_global_handler (struct nn_fsm *myself,int src, int type, NN_UNUSE nn_timer_start (&global->stat_timer, 10000); // Start statistics collection timer return; default: - PNACL_message("bad action %d type %d\n",src,type); + PNACL_msg("bad action %d type %d\n",src,type); nn_fsm_bad_action(global->state, src, type); } default: - PNACL_message("bad source %d\n",src); + PNACL_msg("bad source %d\n",src); nn_fsm_bad_source(global->state, src, type); } diff --git a/crypto777/nanosrc/core/pipe.c b/crypto777/nanosrc/core/pipe.c index 2b674db44..1b1cd1dc6 100755 --- a/crypto777/nanosrc/core/pipe.c +++ b/crypto777/nanosrc/core/pipe.c @@ -58,7 +58,7 @@ void nn_pipebase_init(struct nn_pipebase *self,const struct nn_pipebase_vfptr *v memcpy(&self->options,&epbase->ep->options,sizeof(struct nn_ep_options)); nn_fsm_event_init(&self->in); nn_fsm_event_init(&self->out); - PNACL_message("pipebase_init vfptr.%p recv.%p rcvprio.%d\n",vfptr,vfptr->recv,self->options.rcvprio); + PNACL_msg("pipebase_init vfptr.%p recv.%p rcvprio.%d\n",vfptr,vfptr->recv,self->options.rcvprio); } void nn_pipebase_term (struct nn_pipebase *self) @@ -78,7 +78,7 @@ int nn_pipebase_start (struct nn_pipebase *self) self->instate = NN_PIPEBASE_INSTATE_ASYNC; self->outstate = NN_PIPEBASE_OUTSTATE_IDLE; rc = nn_sock_add(self->sock,(struct nn_pipe *)self); - PNACL_message("nn_pipebase_start self.%p rc.%d\n",self,rc); + PNACL_msg("nn_pipebase_start self.%p rc.%d\n",self,rc); if ( nn_slow(rc < 0) ) { self->state = NN_PIPEBASE_STATE_FAILED; @@ -98,7 +98,7 @@ void nn_pipebase_stop(struct nn_pipebase *self) void nn_pipebase_received(struct nn_pipebase *self) { - PNACL_message("nn_pipebase_received\n"); + PNACL_msg("nn_pipebase_received\n"); if ( nn_fast(self->instate == NN_PIPEBASE_INSTATE_RECEIVING) ) { self->instate = NN_PIPEBASE_INSTATE_RECEIVED; @@ -176,6 +176,7 @@ int nn_pipe_send(struct nn_pipe *self,struct nn_msg *msg) int rc; struct nn_pipebase *pipebase; pipebase = (struct nn_pipebase *)self; + printf("pipesend\n"); nn_assert (pipebase->outstate == NN_PIPEBASE_OUTSTATE_IDLE); pipebase->outstate = NN_PIPEBASE_OUTSTATE_SENDING; rc = pipebase->vfptr->send(pipebase,msg); @@ -196,7 +197,7 @@ int nn_pipe_recv(struct nn_pipe *self,struct nn_msg *msg) pipebase = (struct nn_pipebase*) self; nn_assert (pipebase->instate == NN_PIPEBASE_INSTATE_IDLE); pipebase->instate = NN_PIPEBASE_INSTATE_RECEIVING; - PNACL_message("call pipebase recv\n"); + PNACL_msg("call pipebase recv\n"); rc = pipebase->vfptr->recv (pipebase,msg); errnum_assert (rc >= 0, -rc); if ( nn_fast(pipebase->instate == NN_PIPEBASE_INSTATE_RECEIVED) ) diff --git a/crypto777/nanosrc/core/sock.c b/crypto777/nanosrc/core/sock.c index 6ba4bf5b1..ee95034a8 100755 --- a/crypto777/nanosrc/core/sock.c +++ b/crypto777/nanosrc/core/sock.c @@ -477,6 +477,7 @@ struct nn_ep *nn_find_ep(struct nn_sock *self,int32_t eid,const char *addr,struc int nn_sock_add_ep(struct nn_sock *self,struct nn_transport *transport,int32_t bind,const char *addr) { int rc,eid; struct nn_ep *ep; + printf("nn_sock_add_ep\n"); nn_ctx_enter (&self->ctx); if ( (ep= nn_find_ep(self,0,addr,transport,bind)) == NULL ) // The endpoint doesn't exist { @@ -484,16 +485,17 @@ int nn_sock_add_ep(struct nn_sock *self,struct nn_transport *transport,int32_t b rc = nn_ep_init(ep,NN_SOCK_SRC_EP,self,self->eid,transport,bind,addr); if ( nn_slow(rc < 0) ) { + printf("nn_sock_add_ep nn_ep_init rc.%d\n",rc); nn_free(ep); nn_ctx_leave(&self->ctx); return rc; } nn_ep_start(ep); - PNACL_message("ep sock.(%s) started %s://(%s) bind.%d\n",self->socket_name,transport->name,addr,bind); + printf("ep sock.(%s) started %s://(%s) bind.%d\n",self->socket_name,transport->name,addr,bind); eid = self->eid++; // Increase the endpoint ID for the next endpoint nn_list_insert(&self->eps,&ep->item,nn_list_end(&self->eps)); // Add to the list of active endpoints nn_ctx_leave (&self->ctx); - } else PNACL_message("self->sock.(%s) %p already has (%s)\n",self->socket_name,self->sockbase->sock,addr); + } else printf("self->sock.(%s) %p already has (%s)\n",self->socket_name,self->sockbase->sock,addr); return(ep->eid); } @@ -548,6 +550,7 @@ int nn_sock_send(struct nn_sock *self, struct nn_msg *msg, int flags) /* Try to send the message in a non-blocking way. */ rc = self->sockbase->vfptr->send (self->sockbase, msg); +printf("sockbase send rc.%d\n",rc); if (nn_fast (rc == 0)) { nn_ctx_leave (&self->ctx); return 0; @@ -560,8 +563,7 @@ int nn_sock_send(struct nn_sock *self, struct nn_msg *msg, int flags) return rc; } - /* If the message cannot be sent at the moment and the send call - is non-blocking, return immediately. */ + // If the message cannot be sent at the moment and the send call is non-blocking, return immediately. if (nn_fast (flags & NN_DONTWAIT)) { nn_ctx_leave (&self->ctx); return -EAGAIN; @@ -673,6 +675,7 @@ int nn_sock_add(struct nn_sock *self, struct nn_pipe *pipe) { int rc; rc = self->sockbase->vfptr->add(self->sockbase,pipe); + printf("nn_sock_add rc.%d\n",rc); if (nn_slow (rc >= 0)) { nn_sock_stat_increment (self, NN_STAT_CURRENT_CONNECTIONS, 1); } @@ -973,12 +976,12 @@ void nn_sock_report_error(struct nn_sock *self,struct nn_ep *ep,int32_t errnum,c if ( ep != 0 ) { fprintf(stderr,"nanomsg: socket.%s[%s]: Error: %s\n",self->socket_name,nn_ep_getaddr(ep),nn_strerror(errnum)); - PNACL_message("nanomsg: socket.%s[%s]: [%s:%d] Error: %s\n",self->socket_name,nn_ep_getaddr(ep),fname,linenum,nn_strerror(errnum)); + PNACL_msg("nanomsg: socket.%s[%s]: [%s:%d] Error: %s\n",self->socket_name,nn_ep_getaddr(ep),fname,linenum,nn_strerror(errnum)); } else { fprintf(stderr,"nanomsg: socket.%s: Error: %s\n",self->socket_name, nn_strerror(errnum)); - PNACL_message("nanomsg: socket.%s: [%s:%d] Error: %s\n",self->socket_name,fname,linenum,nn_strerror(errnum)); + PNACL_msg("nanomsg: socket.%s: [%s:%d] Error: %s\n",self->socket_name,fname,linenum,nn_strerror(errnum)); } } diff --git a/crypto777/nanosrc/devices/tcpmuxd.c b/crypto777/nanosrc/devices/tcpmuxd.c index c95c2a899..abd3b7706 100755 --- a/crypto777/nanosrc/devices/tcpmuxd.c +++ b/crypto777/nanosrc/devices/tcpmuxd.c @@ -53,12 +53,7 @@ int nn_tcpmuxd (int port) #include #include #include -#ifndef __PNACL #include -#else -#include -#include -#endif #include #include #include @@ -101,7 +96,8 @@ int nn_tcpmuxd (int port) opt = 1; rc = setsockopt (tcp_listener, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)); - if (rc != 0) { return -1; } + // ignore SO_REUSEADDR failures + //if (rc != 0) { return -1; } memset (&tcp_addr, 0, sizeof (tcp_addr)); tcp_addr.sin_family = AF_INET; tcp_addr.sin_port = htons (port); diff --git a/crypto777/nanosrc/nn.h b/crypto777/nanosrc/nn.h index 3d6e7c598..0127338f3 100755 --- a/crypto777/nanosrc/nn.h +++ b/crypto777/nanosrc/nn.h @@ -30,6 +30,7 @@ extern "C" { #include #include +#include #include "nn_config.h" /* Handle DSO symbol visibility */ diff --git a/crypto777/nanosrc/nn_config.h b/crypto777/nanosrc/nn_config.h index d9e9c6468..74edc6229 100755 --- a/crypto777/nanosrc/nn_config.h +++ b/crypto777/nanosrc/nn_config.h @@ -32,8 +32,8 @@ // need one of following 3, listed in order of precedence, used by efd* //#define NN_HAVE_EVENTFD 1 -//#define NN_HAVE_PIPE 1 -#define NN_HAVE_SOCKETPAIR 1 +#define NN_HAVE_PIPE 1 +//#define NN_HAVE_SOCKETPAIR 1 // need one of following 3, listed in order of precedence, used by poller* #define NN_USE_POLL 1 @@ -46,21 +46,13 @@ #define NN_HAVE_MSG_CONTROL 0 //#define STANDALONE 1 +#define PNACL_msg(...) -#ifdef __PNACL -//#define FD_CLOEXEC 1 - -void PNACL_message(const char* format, ...); -#include -#include -#else #if !defined(WIN32) //#define NN_ENABLE_EXTRA 1 -#define PNACL_message printf #include #include #endif -#endif /* Size of the buffer used for batch-reads of inbound data. To keep the performance optimal make sure that this value is larger than network MTU. */ diff --git a/crypto777/nanosrc/protocols/pipeline/xpush.c b/crypto777/nanosrc/protocols/pipeline/xpush.c index 2d938bd1f..10c5cf480 100755 --- a/crypto777/nanosrc/protocols/pipeline/xpush.c +++ b/crypto777/nanosrc/protocols/pipeline/xpush.c @@ -115,7 +115,7 @@ static int nn_xpush_add (struct nn_sockbase *self, struct nn_pipe *pipe) alloc_assert (data); nn_pipe_setdata (pipe, data); nn_lb_add (&xpush->lb, &data->lb, pipe, sndprio); - + printf("nn_xpush_add\n"); return 0; } @@ -160,6 +160,7 @@ static int nn_xpush_events (struct nn_sockbase *self) static int nn_xpush_send (struct nn_sockbase *self, struct nn_msg *msg) { + printf("nn_xpush_send\n"); return nn_lb_send (&nn_cont (self, struct nn_xpush, sockbase)->lb, msg, NULL); } diff --git a/crypto777/nanosrc/protocols/reqrep/xreq.c b/crypto777/nanosrc/protocols/reqrep/xreq.c index 7b96ba744..7ab93d201 100755 --- a/crypto777/nanosrc/protocols/reqrep/xreq.c +++ b/crypto777/nanosrc/protocols/reqrep/xreq.c @@ -101,7 +101,7 @@ int nn_xreq_add(struct nn_sockbase *self, struct nn_pipe *pipe) nn_pipe_setdata(pipe,data); nn_lb_add(&xreq->lb,&data->lb,pipe,sndprio); nn_fq_add(&xreq->fq,&data->fq,pipe,rcvprio); - + printf("nn_xreq_add\n"); return 0; } diff --git a/crypto777/nanosrc/protocols/utils/lb.c b/crypto777/nanosrc/protocols/utils/lb.c index f0e2e88e3..cbff61f2f 100755 --- a/crypto777/nanosrc/protocols/utils/lb.c +++ b/crypto777/nanosrc/protocols/utils/lb.c @@ -37,8 +37,7 @@ void nn_lb_term (struct nn_lb *self) nn_priolist_term (&self->priolist); } -void nn_lb_add (struct nn_lb *self, struct nn_lb_data *data, - struct nn_pipe *pipe, int priority) +void nn_lb_add (struct nn_lb *self, struct nn_lb_data *data,struct nn_pipe *pipe, int priority) { nn_priolist_add (&self->priolist, &data->priodata, pipe, priority); } @@ -68,14 +67,16 @@ int nn_lb_send (struct nn_lb *self, struct nn_msg *msg, struct nn_pipe **to) { int rc; struct nn_pipe *pipe; - + printf("nn_lb_send\n"); /* Pipe is NULL only when there are no avialable pipes. */ pipe = nn_priolist_getpipe (&self->priolist); + printf("nn_lb_send pipe.%p\n",pipe); if (nn_slow (!pipe)) return -EAGAIN; /* Send the messsage. */ rc = nn_pipe_send (pipe, msg); + printf("nn_pipe_send rc.%d\n",rc); errnum_assert (rc >= 0, -rc); /* Move to the next pipe. */ diff --git a/crypto777/nanosrc/protocols/utils/priolist.c b/crypto777/nanosrc/protocols/utils/priolist.c index a72b5d535..5b6cb5401 100755 --- a/crypto777/nanosrc/protocols/utils/priolist.c +++ b/crypto777/nanosrc/protocols/utils/priolist.c @@ -54,7 +54,7 @@ void nn_priolist_add(struct nn_priolist *self,struct nn_priolist_data *data, str { data->pipe = pipe; data->priority = priority; - //printf("nn_priolist_add.%p data.%p priority.%d\n",self,data,priority); + printf("nn_priolist_add.%p data.%p priority.%d\n",self,data,priority); nn_list_item_init (&data->item); } @@ -139,7 +139,7 @@ struct nn_pipe *nn_priolist_getpipe(struct nn_priolist *self) //printf("nn_priolist_getpipe.%p -1 current it is\n",self); return NULL; } - //printf("nn_priolist_getpipe.%p current.%d slot.%p\n",self,self->current,self->slots[self->current - 1].current->pipe); + printf("nn_priolist_getpipe.%p current.%d slot.%p\n",self,self->current,self->slots[self->current - 1].current->pipe); return self->slots[self->current - 1].current->pipe; } diff --git a/crypto777/nanosrc/protocols/utils/priolist.h b/crypto777/nanosrc/protocols/utils/priolist.h index 9d4a9cad7..358faae79 100755 --- a/crypto777/nanosrc/protocols/utils/priolist.h +++ b/crypto777/nanosrc/protocols/utils/priolist.h @@ -86,8 +86,7 @@ void nn_priolist_activate (struct nn_priolist *self, struct nn_priolist_data *da 0 otherwise. */ int nn_priolist_is_active (struct nn_priolist *self); -/* Get the pointer to the current pipe. If there's no pipe in the list, - NULL is returned. */ +// Get the pointer to the current pipe. If there's no pipe in the list, NULL is returned. struct nn_pipe *nn_priolist_getpipe (struct nn_priolist *self); /* Moves to the next pipe in the list. If 'release' is set to 1, the current diff --git a/crypto777/nanosrc/tests/testutil.h b/crypto777/nanosrc/tests/testutil.h index fd3d5b68c..04d26edbb 100755 --- a/crypto777/nanosrc/tests/testutil.h +++ b/crypto777/nanosrc/tests/testutil.h @@ -26,9 +26,9 @@ #include #include -#ifdef __PNACL -#define printf PostMessage -#endif +//#ifdef __PNACL +//#define printf PostMessage +//#endif #include "../utils/attr.h" #include "../utils/err.h" diff --git a/crypto777/nanosrc/transports/ipc/bipc.c b/crypto777/nanosrc/transports/ipc/bipc.c index 76a6f9256..8527e45a6 100755 --- a/crypto777/nanosrc/transports/ipc/bipc.c +++ b/crypto777/nanosrc/transports/ipc/bipc.c @@ -39,12 +39,8 @@ #include "../../utils/win.h" #else #include -#ifndef __PNACL #include #include -#else -#include -#endif #include #endif diff --git a/crypto777/nanosrc/transports/ipc/cipc.c b/crypto777/nanosrc/transports/ipc/cipc.c index 56dcbc83d..1f6c3b7de 100755 --- a/crypto777/nanosrc/transports/ipc/cipc.c +++ b/crypto777/nanosrc/transports/ipc/cipc.c @@ -39,13 +39,8 @@ #include "../../utils/win.h" #else #include -#ifndef __PNACL #include #include -#else -#include -#include -#endif #endif #define NN_CIPC_STATE_IDLE 1 diff --git a/crypto777/nanosrc/transports/ipc/ipc.c b/crypto777/nanosrc/transports/ipc/ipc.c index 1421ec276..45d3851ce 100755 --- a/crypto777/nanosrc/transports/ipc/ipc.c +++ b/crypto777/nanosrc/transports/ipc/ipc.c @@ -37,11 +37,7 @@ #include "../../utils/win.h" #else #include -#ifndef __PNACL #include -#else -#include -#endif #include #endif diff --git a/crypto777/nanosrc/transports/tcpmux/btcpmux.c b/crypto777/nanosrc/transports/tcpmux/btcpmux.c index 51fd16a64..2dd554272 100755 --- a/crypto777/nanosrc/transports/tcpmux/btcpmux.c +++ b/crypto777/nanosrc/transports/tcpmux/btcpmux.c @@ -44,12 +44,8 @@ #include "../../utils/win.h" #else #include -#ifndef __PNACL #include #include -#else -#include -#endif #include #endif diff --git a/crypto777/nanosrc/transports/utils/tcpmux.c b/crypto777/nanosrc/transports/utils/tcpmux.c index b4f7f0105..9f2cc3a60 100755 --- a/crypto777/nanosrc/transports/utils/tcpmux.c +++ b/crypto777/nanosrc/transports/utils/tcpmux.c @@ -28,11 +28,7 @@ #else #include #include -#ifndef __PNACL #include -#else -#include -#endif #endif #include "tcpmux.h" @@ -87,7 +83,7 @@ int tcpmux_accept (int s) memset (&hdr, 0, sizeof (hdr)); hdr.msg_iov = &iov; hdr.msg_iovlen = 1; -#ifndef NN_USE_MYMSG +#if !NN_USE_MYMSG unsigned char buf [256]; hdr.msg_control = buf; hdr.msg_controllen = sizeof (buf); diff --git a/crypto777/nanosrc/transports/ws/cws.c b/crypto777/nanosrc/transports/ws/cws.c index 57e66c91a..905e90405 100755 --- a/crypto777/nanosrc/transports/ws/cws.c +++ b/crypto777/nanosrc/transports/ws/cws.c @@ -329,7 +329,7 @@ static void nn_cws_handler (struct nn_fsm *self, int src, int type, struct nn_cws *cws; cws = nn_cont (self, struct nn_cws, fsm); - + printf("cws_handler src.%d type.%d state.%d\n",src,type,cws->state); switch (cws->state) { /******************************************************************************/ @@ -409,6 +409,7 @@ static void nn_cws_handler (struct nn_fsm *self, int src, int type, case NN_CWS_SRC_USOCK: switch (type) { case NN_USOCK_CONNECTED: + printf("cws connected\n"); nn_sws_start (&cws->sws, &cws->usock, NN_WS_CLIENT, nn_chunkref_data (&cws->resource), nn_chunkref_data (&cws->remote_host)); @@ -421,6 +422,7 @@ static void nn_cws_handler (struct nn_fsm *self, int src, int type, nn_epbase_clear_error (&cws->epbase); return; case NN_USOCK_ERROR: + printf("cws NN_USOCK_ERROR\n"); nn_epbase_set_error (&cws->epbase,nn_usock_geterrno (&cws->usock),__FILE__,__LINE__); nn_usock_stop(&cws->usock); cws->state = NN_CWS_STATE_STOPPING_USOCK; diff --git a/crypto777/nanosrc/transports/ws/sws.c b/crypto777/nanosrc/transports/ws/sws.c index 45f5430cc..627c5590f 100755 --- a/crypto777/nanosrc/transports/ws/sws.c +++ b/crypto777/nanosrc/transports/ws/sws.c @@ -370,7 +370,7 @@ static int nn_sws_send (struct nn_pipebase *self, struct nn_msg *msg) struct nn_cmsghdr *cmsg; struct nn_msghdr msghdr; uint8_t rand_mask [NN_SWS_FRAME_SIZE_MASK]; - +printf("nn_sws_send\n"); sws = nn_cont (self, struct nn_sws, pipebase); nn_assert_state (sws, NN_SWS_STATE_ACTIVE); @@ -884,7 +884,7 @@ static void nn_sws_handler (struct nn_fsm *self, int src, int type, int rc; sws = nn_cont (self, struct nn_sws, fsm); - + printf("sws src.%d type.%d state.%d\n",src,type,sws->state); switch (sws->state) { /******************************************************************************/ diff --git a/crypto777/nanosrc/transports/ws/sws.h b/crypto777/nanosrc/transports/ws/sws.h index d83f3f0fd..b482d1f19 100755 --- a/crypto777/nanosrc/transports/ws/sws.h +++ b/crypto777/nanosrc/transports/ws/sws.h @@ -152,7 +152,7 @@ struct nn_sws { uint8_t inmsg_control [NN_SWS_PAYLOAD_MAX_LENGTH]; /* Reason this connection is closing to send as closing handshake. */ - char fail_msg [NN_SWS_PAYLOAD_MAX_LENGTH]; + uint8_t fail_msg [NN_SWS_PAYLOAD_MAX_LENGTH]; size_t fail_msg_len; /* State of the outbound state machine. */ diff --git a/crypto777/nanosrc/transports/ws/ws.c b/crypto777/nanosrc/transports/ws/ws.c index 0e91e9474..3a9288284 100755 --- a/crypto777/nanosrc/transports/ws/ws.c +++ b/crypto777/nanosrc/transports/ws/ws.c @@ -156,7 +156,7 @@ int nn_ws_send (int s, const void *msg, size_t len, uint8_t msg_type, int flags) struct nn_msghdr hdr; struct nn_cmsghdr *cmsg; size_t cmsgsz; - +printf("nn_ws_send\n"); iov.iov_base = (void*) msg; iov.iov_len = len; diff --git a/crypto777/nanosrc/transports/ws/ws_handshake.c b/crypto777/nanosrc/transports/ws/ws_handshake.c index 52b8e3f40..eca21d44a 100755 --- a/crypto777/nanosrc/transports/ws/ws_handshake.c +++ b/crypto777/nanosrc/transports/ws/ws_handshake.c @@ -1213,7 +1213,7 @@ static void nn_ws_handshake_client_request (struct nn_ws_handshake *self) nn_random_generate (rand_key, sizeof (rand_key)); - rc = nn_base64_encode (rand_key, sizeof (rand_key), + rc = _nn_base64_encode (rand_key, sizeof (rand_key), encoded_key, sizeof (encoded_key)); encoded_key_len = strlen (encoded_key); @@ -1355,7 +1355,7 @@ static int nn_ws_handshake_hash_key (const char *key, size_t key_len, for (i = 0; i < strlen (NN_WS_HANDSHAKE_MAGIC_GUID); i++) nn_sha1_hashbyte (&hash, NN_WS_HANDSHAKE_MAGIC_GUID [i]); - rc = nn_base64_encode (nn_sha1_result (&hash), + rc = _nn_base64_encode (nn_sha1_result (&hash), sizeof (hash.state), hashed, hashed_len); return rc; diff --git a/crypto777/nanosrc/utils/efd_eventfd.c b/crypto777/nanosrc/utils/efd_eventfd.c index ae3449c15..f659296e7 100755 --- a/crypto777/nanosrc/utils/efd_eventfd.c +++ b/crypto777/nanosrc/utils/efd_eventfd.c @@ -32,9 +32,9 @@ int nn_efd_init(struct nn_efd *self) { int rc; int flags; - //PostMessage("inside efd_init eventfd\n"); + PNACL_msg("inside efd_init eventfd\n"); self->efd = eventfd(0, EFD_CLOEXEC); - //PostMessage("self->efd: %d\n",self->efd); + PNACL_msg("self->efd: %d\n",self->efd); if (self->efd == -1 && (errno == EMFILE || errno == ENFILE)) return -EMFILE; errno_assert(self->efd != -1); diff --git a/crypto777/nanosrc/utils/efd_pipe.c b/crypto777/nanosrc/utils/efd_pipe.c index 4df5fd3b3..59472d5d8 100755 --- a/crypto777/nanosrc/utils/efd_pipe.c +++ b/crypto777/nanosrc/utils/efd_pipe.c @@ -33,14 +33,14 @@ int nn_efd_init(struct nn_efd *self) { int rc,flags,p[2]; - PNACL_message("inside efd_init: pipe\n"); + PNACL_msg("inside efd_init: pipe\n"); //sleep(1); #if defined NN_HAVE_PIPE2 rc = pipe2(p, O_NONBLOCK | O_CLOEXEC); #else rc = pipe(p); #endif - PNACL_message("rc efd_init: %d\n",rc); + PNACL_msg("rc efd_init: %d\n",rc); //sleep(1); if (rc != 0 && (errno == EMFILE || errno == ENFILE)) return -EMFILE; @@ -50,20 +50,20 @@ int nn_efd_init(struct nn_efd *self) #if !defined NN_HAVE_PIPE2 && defined FD_CLOEXEC rc = fcntl (self->r, F_SETFD, FD_CLOEXEC); - PNACL_message("pipe efd_init: F_SETFDr rc %d\n",rc); + PNACL_msg("pipe efd_init: F_SETFDr rc %d\n",rc); errno_assert(rc != -1); rc = fcntl(self->w, F_SETFD, FD_CLOEXEC); - PNACL_message("pipe efd_init: F_SETFDw rc %d\n",rc); + PNACL_msg("pipe efd_init: F_SETFDw rc %d\n",rc); errno_assert(rc != -1); #endif #if !defined NN_HAVE_PIPE2 flags = fcntl(self->r, F_GETFL, 0); - PNACL_message("pipe efd_init: flags %d\n",flags); + PNACL_msg("pipe efd_init: flags %d\n",flags); if ( flags == -1 ) flags = 0; rc = fcntl(self->r, F_SETFL, flags | O_NONBLOCK); - PNACL_message("pipe efd_init: rc %d flags.%d\n",rc,flags); + PNACL_msg("pipe efd_init: rc %d flags.%d\n",rc,flags); errno_assert (rc != -1); #endif diff --git a/crypto777/nanosrc/utils/efd_socketpair.c b/crypto777/nanosrc/utils/efd_socketpair.c index aba164fa7..e04a4935e 100755 --- a/crypto777/nanosrc/utils/efd_socketpair.c +++ b/crypto777/nanosrc/utils/efd_socketpair.c @@ -35,7 +35,7 @@ int nn_efd_init (struct nn_efd *self) int rc; int flags; int sp [2]; - + PNACL_msg("socketpair efdinit\n"); #if defined SOCK_CLOEXEC rc = socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sp); #else diff --git a/crypto777/nanosrc/utils/efd_win.c b/crypto777/nanosrc/utils/efd_win.c index 8d253408f..5678ba7d5 100755 --- a/crypto777/nanosrc/utils/efd_win.c +++ b/crypto777/nanosrc/utils/efd_win.c @@ -84,8 +84,9 @@ int nn_efd_init (struct nn_efd *self) reuseaddr = 1; rc = setsockopt (listener, SOL_SOCKET, SO_REUSEADDR, (char*) &reuseaddr, sizeof (reuseaddr)); - if (nn_slow (rc == SOCKET_ERROR)) - goto wsafail; + // ignore SO_REUSEADDR failures + // if (nn_slow (rc == SOCKET_ERROR)) + // goto wsafail; /* Bind the listening socket to the local port. */ memset (&addr, 0, sizeof (addr)); diff --git a/crypto777/nanosrc/utils/err.c b/crypto777/nanosrc/utils/err.c index 6f5bc42a6..afca3471b 100755 --- a/crypto777/nanosrc/utils/err.c +++ b/crypto777/nanosrc/utils/err.c @@ -30,7 +30,7 @@ void nn_err_abort(void) { - PNACL_message("nn_err_abort\n"); + PNACL_msg("nn_err_abort\n"); while ( 1 ) { printf("exit due to error\n"); @@ -111,7 +111,7 @@ const char *nn_err_strerror(int32_t errnum) #pragma warning (push) #pragma warning (disable:4996) #endif - PNACL_message("nanomsg: errno.%d (%s)\n",errnum,strerror(errnum)); + PNACL_msg("nanomsg: errno.%d (%s)\n",errnum,strerror(errnum)); getchar(); return strerror (errnum); #if defined _MSC_VER diff --git a/crypto777/nanosrc/utils/err.h b/crypto777/nanosrc/utils/err.h index a9485549e..e932766e1 100755 --- a/crypto777/nanosrc/utils/err.h +++ b/crypto777/nanosrc/utils/err.h @@ -26,6 +26,7 @@ #include #include #include +#define PNACL_msg(...) /* Include nn.h header to define nanomsg-specific error codes. */ #include "../nn.h" @@ -44,7 +45,7 @@ #define nn_assert(x) \ do {\ if (nn_slow (!(x))) {\ - PNACL_message("Assertion failed: %s (%s:%d)\n", #x, \ + PNACL_msg("Assertion failed: %s (%s:%d)\n", #x, \ __FILE__, __LINE__);\ fflush (stderr);\ nn_err_abort ();\ @@ -54,7 +55,7 @@ #define nn_assert_state(obj, state_name) \ do {\ if (nn_slow ((obj)->state != state_name)) {\ - PNACL_message( \ + PNACL_msg( \ "Assertion failed: %d == %s (%s:%d)\n", \ (obj)->state, #state_name, \ __FILE__, __LINE__);\ @@ -66,7 +67,7 @@ #define alloc_assert(x) \ do {\ if (nn_slow (!x)) {\ - PNACL_message("Out of memory (%s:%d)\n",\ + PNACL_msg("Out of memory (%s:%d)\n",\ __FILE__, __LINE__);\ nn_err_abort ();\ }\ @@ -76,7 +77,7 @@ #define errno_assert(x) \ do {\ if (nn_slow (!(x))) {\ - PNACL_message("%s [%d] (%s:%d)\n", nn_err_strerror (errno),\ + PNACL_msg("%s [%d] (%s:%d)\n", nn_err_strerror (errno),\ (int) errno, __FILE__, __LINE__);\ nn_err_abort ();\ }\ @@ -86,7 +87,7 @@ #define errnum_assert(cond, err) \ do {\ if (nn_slow (!(cond))) {\ - PNACL_message("%s [%d] (%s:%d)\n", nn_err_strerror (err),(int) (err), __FILE__, __LINE__);\ + PNACL_msg("%s [%d] (%s:%d)\n", nn_err_strerror (err),(int) (err), __FILE__, __LINE__);\ nn_err_abort ();\ }\ } while (0) @@ -118,7 +119,7 @@ /* Assertion-like macros for easier fsm debugging. */ #define nn_fsm_error(message, state, src, type) \ do {\ - PNACL_message("%s: state=%d source=%d action=%d (%s:%d)\n", \ + PNACL_msg("%s: state=%d source=%d action=%d (%s:%d)\n", \ message, state, src, type, __FILE__, __LINE__);\ nn_err_abort ();\ } while (0) diff --git a/crypto777/nanosrc/utils/thread_posix.c b/crypto777/nanosrc/utils/thread_posix.c index 93c81b6cb..df005eee3 100755 --- a/crypto777/nanosrc/utils/thread_posix.c +++ b/crypto777/nanosrc/utils/thread_posix.c @@ -26,11 +26,11 @@ #include #include -static void *nn_thread_main_routine(void *arg) +void *nn_thread_main_routine(void *arg) { struct nn_thread *self; self = (struct nn_thread *)arg; - PNACL_message("nn_thread_main_routine arg.%p self->routine(%p) at %p\n",arg,self->arg,self->routine); + printf("nn_thread_main_routine arg.%p self->routine(%p) at %p\n",arg,self->arg,self->routine); self->routine(self->arg); // Run the thread routine return NULL; } @@ -42,16 +42,22 @@ void nn_thread_term(struct nn_thread *self) errnum_assert(rc == 0,rc); } +void *Nanomsg_threadarg; + #ifdef __PNACL void nn_thread_init(struct nn_thread *self,nn_thread_routine *routine,void *arg) { int32_t rc; // No signals should be processed by this thread. The library doesn't use signals and thus all the signals should be delivered to application threads, not to worker threads. - PNACL_message("nn_thread_init routine.%p arg.%p\n",routine,arg); + printf("nn_thread_init routine.%p arg.%p\n",routine,arg); self->routine = routine; self->arg = arg; +#ifdef FROM_JS + Nanomsg_threadarg = self; +#else rc = pthread_create(&self->handle,NULL,nn_thread_main_routine,(void *)self); errnum_assert (rc == 0, rc); +#endif } #else diff --git a/crypto777/nanosrc/utils/win.h b/crypto777/nanosrc/utils/win.h index dcfe06af6..288713712 100755 --- a/crypto777/nanosrc/utils/win.h +++ b/crypto777/nanosrc/utils/win.h @@ -27,8 +27,8 @@ #define WIN32_LEAN_AND_MEAN #endif -#include #include +#include #include #include #include diff --git a/iguana/coins/basilisk/mnz b/iguana/coins/basilisk/mnz new file mode 100755 index 000000000..d08d34075 --- /dev/null +++ b/iguana/coins/basilisk/mnz @@ -0,0 +1,2 @@ +curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"MNZ.conf\",\"path\":\"${HOME#"/"}/.komodo/MNZ\",\"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\":\"MNZ\",\"name\":\"MNZ\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"53d06fde\",\"p2p\":14336,\"rpc\":14337,\"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\"}" + diff --git a/iguana/coins/chips_7776 b/iguana/coins/chips_7776 new file mode 100755 index 000000000..38f1e5f1c --- /dev/null +++ b/iguana/coins/chips_7776 @@ -0,0 +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,\"pubval\":60,\"p2shval\":85,\"wifval\":188}" diff --git a/iguana/coins/mnz_7776 b/iguana/coins/mnz_7776 new file mode 100755 index 000000000..10d68be4c --- /dev/null +++ b/iguana/coins/mnz_7776 @@ -0,0 +1,2 @@ +curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"MNZ.conf\",\"path\":\"${HOME#"/"}/.komodo/MNZ\",\"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\":\"MNZ\",\"name\":\"MNZ\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"53d06fde\",\"p2p\":14336,\"rpc\":14337,\"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\"}" + diff --git a/iguana/dPoW.h b/iguana/dPoW.h index b773104c8..ba9e5c00e 100755 --- a/iguana/dPoW.h +++ b/iguana/dPoW.h @@ -20,6 +20,7 @@ #define DPOW_CHECKPOINTFREQ 10 #define DPOW_MINSIGS 13 +#define DPOW_MIN_ASSETCHAIN_SIGS 11 //#define DPOW_M(bp) ((bp)->minsigs) // (((bp)->numnotaries >> 1) + 1) #define DPOW_MODIND(bp,offset) (((((bp)->height / DPOW_CHECKPOINTFREQ) % (bp)->numnotaries) + (offset)) % (bp)->numnotaries) #define DPOW_VERSION 0x0781 @@ -132,12 +133,12 @@ struct dpow_info char symbol[16],dest[16]; uint8_t minerkey33[33],minerid; uint64_t lastrecvmask; struct dpow_checkpoint checkpoint,last,destchaintip,srcfifo[DPOW_FIFOSIZE],destfifo[DPOW_FIFOSIZE]; struct dpow_hashheight approved[DPOW_FIFOSIZE],notarized[DPOW_FIFOSIZE]; - bits256 srctx[DPOW_MAXTX],desttx[DPOW_MAXTX]; - uint32_t SRCREALTIME,destupdated,srcconfirms,numdesttx,numsrctx,lastsplit,cancelratify; + bits256 activehash,lastnotarized,srctx[DPOW_MAXTX],desttx[DPOW_MAXTX]; + uint32_t SRCREALTIME,lastsrcupdate,destupdated,srcconfirms,numdesttx,numsrctx,lastsplit,cancelratify; int32_t lastheight,maxblocks,SRCHEIGHT,SHORTFLAG,ratifying; struct pax_transaction *PAX; portable_mutex_t paxmutex,dexmutex; - uint32_t ipbits[64],numipbits; + uint32_t ipbits[128],numipbits; struct dpow_block **blocks; }; uint64_t dpow_notarybestk(uint64_t refmask,struct dpow_block *bp,int8_t *lastkp); diff --git a/iguana/dexscripts.win32/1-client.cmd b/iguana/dexscripts.win32/1-client.cmd new file mode 100644 index 000000000..21bec2717 --- /dev/null +++ b/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= marketmaker.log 2>&1 +marketmaker "{\"gui\":\"nogui\",\"client\":1, \"userhome\":\"%USERHOME%\", \"passphrase\":\"%PASSPHRASE%\"}" + + + + diff --git a/iguana/dexscripts.win32/2-getuserpass.cmd b/iguana/dexscripts.win32/2-getuserpass.cmd new file mode 100644 index 000000000..87e633339 --- /dev/null +++ b/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 \ No newline at end of file diff --git a/iguana/dexscripts.win32/balance.cmd b/iguana/dexscripts.win32/balance.cmd new file mode 100644 index 000000000..551d1234a --- /dev/null +++ b/iguana/dexscripts.win32/balance.cmd @@ -0,0 +1,4 @@ +@echo off +set /p TMPUSERPASS= 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. \ No newline at end of file diff --git a/iguana/dexscripts.win32/images/conemu_jq.png b/iguana/dexscripts.win32/images/conemu_jq.png new file mode 100644 index 000000000..e8eeaf523 Binary files /dev/null and b/iguana/dexscripts.win32/images/conemu_jq.png differ diff --git a/iguana/dexscripts.win32/images/userpass.png b/iguana/dexscripts.win32/images/userpass.png new file mode 100644 index 000000000..9134e8ed5 Binary files /dev/null and b/iguana/dexscripts.win32/images/userpass.png differ diff --git a/iguana/dexscripts.win32/images/userpass_usage.png b/iguana/dexscripts.win32/images/userpass_usage.png new file mode 100644 index 000000000..157251a4b Binary files /dev/null and b/iguana/dexscripts.win32/images/userpass_usage.png differ diff --git a/iguana/dexscripts.win32/inventory.cmd b/iguana/dexscripts.win32/inventory.cmd new file mode 100644 index 000000000..c1e02c0a0 --- /dev/null +++ b/iguana/dexscripts.win32/inventory.cmd @@ -0,0 +1,4 @@ +@echo off +set /p TMPUSERPASS= withdraw.txt +type withdraw.txt diff --git a/iguana/dexscripts.win32/withdraw_10_send.cmd b/iguana/dexscripts.win32/withdraw_10_send.cmd new file mode 100644 index 000000000..44a947787 --- /dev/null +++ b/iguana/dexscripts.win32/withdraw_10_send.cmd @@ -0,0 +1,14 @@ +@echo off +set /p TMPUSERPASS= 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\"}" +) diff --git a/iguana/dexscripts.win32/withdraw_send.cmd b/iguana/dexscripts.win32/withdraw_send.cmd new file mode 100644 index 000000000..a26b9bf56 --- /dev/null +++ b/iguana/dexscripts.win32/withdraw_send.cmd @@ -0,0 +1,14 @@ +@echo off +set /p TMPUSERPASS= 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\"}" +) + diff --git a/iguana/dpow/dpow_fsm.c b/iguana/dpow/dpow_fsm.c index 18afb868b..effcf3914 100755 --- a/iguana/dpow/dpow_fsm.c +++ b/iguana/dpow/dpow_fsm.c @@ -326,7 +326,7 @@ void dpow_statemachinestart(void *ptr) return; } bp->myind = myind; - printf("[%d] statemachinestart %s->%s %s ht.%d minsigs.%d duration.%d start.%u\n",bp->myind,dp->symbol,dp->dest,bits256_str(str,checkpoint.blockhash.hash),checkpoint.blockhash.height,minsigs,duration,checkpoint.timestamp); + printf("[%d] notarize %s->%s %s ht.%d minsigs.%d duration.%d start.%u\n",bp->myind,dp->symbol,dp->dest,bits256_str(str,checkpoint.blockhash.hash),checkpoint.blockhash.height,minsigs,duration,checkpoint.timestamp); if ( bp->isratify != 0 && memcmp(bp->notaries[0].pubkey,bp->ratified_pubkeys[0],33) != 0 ) { for (i=0; i<33; i++) @@ -447,6 +447,11 @@ void dpow_statemachinestart(void *ptr) dpow_send(myinfo,dp,bp,srchash,bp->hashmsg,0,bp->height,(void *)"ping",0); dpow_nanomsg_update(myinfo); } + else + { + dp->lastnotarized = checkpoint.blockhash.hash; + printf("notarized %s %s\n",dp->symbol,bits256_str(str,checkpoint.blockhash.hash)); + } if ( 0 && dp->cancelratify != 0 && bp->isratify != 0 ) { printf("abort pending ratify\n"); diff --git a/iguana/dpow/dpow_network.c b/iguana/dpow/dpow_network.c index 33592f0b8..9899b9cac 100755 --- a/iguana/dpow/dpow_network.c +++ b/iguana/dpow/dpow_network.c @@ -561,7 +561,7 @@ void dex_channelsend(struct supernet_info *myinfo,bits256 srchash,bits256 destha void dpow_randipbits(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *retjson) { - int32_t m; uint32_t ipbits; char *coinstr; + int32_t m; uint32_t ipbits; char *coinstr; cJSON *infojson; if ( is_cJSON_Array(retjson) == 0 ) { if ( (m= myinfo->numdpowipbits) > 0 ) @@ -572,6 +572,11 @@ void dpow_randipbits(struct supernet_info *myinfo,struct iguana_info *coin,cJSON } if ( (coinstr= jstr(retjson,"coin")) == 0 ) jaddstr(retjson,"coin",coin->symbol); + if ( (infojson= dpow_getinfo(myinfo,coin)) != 0 ) + { + jaddnum(retjson,"notaryheight",juint(infojson,"blocks")); + free_json(infojson); + } } } @@ -1318,7 +1323,7 @@ struct dpow_nanomsghdr { bits256 srchash,desthash; struct dpow_nanoutxo ratify,notarize; - uint32_t channel,height,size,datalen,crc32,myipbits,numipbits,ipbits[64]; + uint32_t channel,height,size,datalen,crc32,myipbits,numipbits,ipbits[128]; char symbol[16]; uint8_t senderind,version0,version1,packet[]; } PACKED; @@ -2026,10 +2031,10 @@ void dpow_send(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_blo printf("%d NANOSEND.%d ht.%d channel.%08x (%d) pax.%08x datalen.%d (%d %llx) (%d %llx) recv.%llx\n",i,sentbytes,np->height,np->channel,size,np->notarize.paxwdcrc,datalen,(int8_t)np->notarize.bestk,(long long)np->notarize.bestmask,bp->notaries[bp->myind].bestk,(long long)bp->notaries[bp->myind].bestmask,(long long)bp->recvmask); } -void dpow_ipbitsadd(struct supernet_info *myinfo,struct dpow_info *dp,uint32_t *ipbits,int32_t numipbits,int32_t fromid,uint32_t senderipbits) +void dpow_ipbitsadd(struct supernet_info *myinfo,struct dpow_info *dp,uint32_t *ipbits,int32_t numipbits,int32_t maxipbits,int32_t fromid,uint32_t senderipbits) { int32_t i,j,matched,missing,n; char ipaddr[64]; - if ( numipbits >= 64 ) + if ( numipbits >= maxipbits ) { static int32_t counter; if ( counter++ < 100 ) @@ -2088,7 +2093,7 @@ int32_t dpow_nanomsg_update(struct supernet_info *myinfo) if ( (flags & 1) == 0 && (size= signed_nn_recv(&freeptr,myinfo,myinfo->notaries,myinfo->numnotaries,myinfo->dpowsock,&np)) > 0 ) { num++; - if ( size > 0 ) + if ( size >= sizeof(*np) ) { //fprintf(stderr,"%d ",size); if ( np->version0 == (DPOW_VERSION & 0xff) && np->version1 == ((DPOW_VERSION >> 8) & 0xff) ) @@ -2112,7 +2117,7 @@ int32_t dpow_nanomsg_update(struct supernet_info *myinfo) printf("received nnpacket for (%s)\n",np->symbol); else { - dpow_ipbitsadd(myinfo,dp,np->ipbits,np->numipbits,np->senderind,np->myipbits); + dpow_ipbitsadd(myinfo,dp,np->ipbits,np->numipbits,sizeof(np->ipbits)/sizeof(*np->ipbits),np->senderind,np->myipbits); if ( (bp= dpow_heightfind(myinfo,dp,np->height)) != 0 && bp->state != 0xffffffff && bp->myind >= 0 ) { //char str[65]; printf("%s RECV ht.%d ch.%08x (%d) crc32.%08x:%08x datalen.%d:%d firstz.%d i.%d senderind.%d myind.%d\n",bits256_str(str,np->srchash),np->height,np->channel,size,np->crc32,crc32,np->datalen,(int32_t)(size - sizeof(*np)),firstz,i,np->senderind,bp->myind); diff --git a/iguana/dpow/dpow_prices.c b/iguana/dpow/dpow_prices.c index 5f19199ca..d83da8dd1 100755 --- a/iguana/dpow/dpow_prices.c +++ b/iguana/dpow/dpow_prices.c @@ -1438,7 +1438,7 @@ void PAX_update(struct PAX_data *dp,double *btcusdp,double *kmdbtcp) *kmdbtcp = 0; bitcoinave = 0;//url_json("https://api.bitcoinaverage.com/ticker/USD/"); //bitcoincharts = url_json("http://api.bitcoincharts.com/v1/weighted_prices.json"); - blockchaininfo = 0;//url_json("https://blockchain.info/ticker"); + blockchaininfo = url_json("https://blockchain.info/ticker"); coindesk = 0;//url_json("http://api.coindesk.com/v1/bpi/historical/close.json"); sprintf(url,"https://poloniex.com/public?command=returnChartData¤cyPair=BTC_KMD&start=%ld&end=9999999999&period=86400",(long)(time(NULL)-3600*24)); sprintf(url2,"https://poloniex.com/public?command=returnChartData¤cyPair=BTC_BTCD&start=%ld&end=9999999999&period=86400",(long)(time(NULL)-3600*24)); @@ -1541,7 +1541,7 @@ void PAX_update(struct PAX_data *dp,double *btcusdp,double *kmdbtcp) if ( (item= jobj(blockchaininfo,"USD")) != 0 && item != 0 && (price= jdouble(item,"15m")) > SMALLVAL ) { dpow_price("blockchain.info","BTCUSD",price,price); - //printf("blockchaininfo %f %f\n",btcusd,price); + printf("blockchaininfo %f %f\n",btcusd,price); dxblend(&btcusd,price,0.5); } free_json(blockchaininfo); @@ -1832,13 +1832,16 @@ void PAX_genecbsplines(struct PAX_data *dp) portable_mutex_unlock(&mutex); } +#define BTCFACTOR_TIMESTAMP 1503746319 +#define BTCFACTOR_HEIGHT 466266 + int32_t PAX_idle(struct supernet_info *myinfo)//struct PAX_data *argdp,int32_t idlegap) { - static double lastupdate,lastdayupdate; static int32_t didinit; static char *userhome; int32_t idlegap = 10; + static double lastupdate,lastdayupdate; static uint32_t didinit; static char *userhome; int32_t idlegap = 10; FILE *fp; long filesize; char fname[512]; double splineval; uint32_t pvals[128],timestamp; int32_t i,datenum,seconds,c; struct tai t; struct PAX_data *dp; uint8_t data[512]; if ( Currencymasks[0] == 0 ) return(0); - if ( didinit == 0 ) + if ( time(NULL) > didinit+12*3600 ) { if ( (userhome= OS_filestr(&filesize,"userhome.txt")) == 0 ) userhome = "root"; @@ -1849,15 +1852,15 @@ int32_t PAX_idle(struct supernet_info *myinfo)//struct PAX_data *argdp,int32_t i userhome[strlen(userhome)-1] = 0; } } - myinfo->PAXDATA = calloc(1,sizeof(*dp)); - didinit = 1; + if ( myinfo->PAXDATA == 0 ) + myinfo->PAXDATA = calloc(1,sizeof(*dp)); dp = myinfo->PAXDATA; PAX_genecbsplines(dp); printf("generated splines\n"); - datenum = OS_conv_unixtime(&t,&seconds,(uint32_t)time(NULL)); + didinit = (uint32_t)time(NULL); + datenum = OS_conv_unixtime(&t,&seconds,didinit); expand_datenum(dp->edate,datenum); } - dp = myinfo->PAXDATA; /*if ( 0 && time(NULL) > dp->lastupdate+10 ) { @@ -1904,8 +1907,9 @@ int32_t PAX_idle(struct supernet_info *myinfo)//struct PAX_data *argdp,int32_t i PAX_emitprices(pvals,dp); } timestamp = (uint32_t)time(NULL); - int32_t dispflag = ((rand() % 64) == 0); - if ( dp->kmdbtc == 0 || dispflag != 0 ) + int32_t dispflag = ((rand() % 6) == 0); + //printf("PAX_IDLE.%d %.8f %.8f\n",dispflag,dp->kmdbtc,dp->btcusd); + if ( dp->kmdbtc == 0 || dp->btcusd == 0 || dispflag != 0 ) { PAX_update(dp,&dp->btcusd,&dp->kmdbtc); for (i=0; ikmdbtc * 1000); - pvals[4] = PAX_val32(dp->btcusd * .001); + double btcfactor; + //if ( time(NULL) > BTCFACTOR_TIMESTAMP ) + btcfactor = .00001; + //else btcfactor = .001; + pvals[4] = PAX_val32(dp->btcusd * btcfactor); pvals[5] = PAX_val32(dp->CNYUSD); - if ( dispflag != 0 ) - printf("KMD %.8f BTC %f CNY %f (%f)\n",dp->kmdbtc,dp->btcusd,dp->CNYUSD,1./dp->CNYUSD); sprintf(fname,"/%s/.komodo/komodofeed",userhome); if ( (fp= fopen(fname,"wb")) != 0 ) { @@ -1939,7 +1945,7 @@ int32_t PAX_idle(struct supernet_info *myinfo)//struct PAX_data *argdp,int32_t i { for (i=0; i<6; i++) printf("%u ",pvals[i]); - printf("pvals -> %s\n",fname); + printf("KMD %.8f BTC %f CNY %f (%f) btcusd pval.%u\n",dp->kmdbtc,dp->btcusd,dp->CNYUSD,1./dp->CNYUSD,pvals[4]); } } } diff --git a/iguana/dpow/dpow_rpc.c b/iguana/dpow/dpow_rpc.c index 0e294f4d9..5f695f84a 100755 --- a/iguana/dpow/dpow_rpc.c +++ b/iguana/dpow/dpow_rpc.c @@ -177,7 +177,7 @@ bits256 dpow_getbestblockhash(struct supernet_info *myinfo,struct iguana_info *c memset(blockhash.bytes,0,sizeof(blockhash)); if ( coin->FULLNODE < 0 ) { - if ( coin->lastbesthashtime+20 > time(NULL) && bits256_nonz(coin->lastbesthash) != 0 ) + if ( coin->lastbesthashtime+2 > time(NULL) && bits256_nonz(coin->lastbesthash) != 0 ) return(coin->lastbesthash); if ( (retstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"getbestblockhash","")) != 0 ) { @@ -394,7 +394,7 @@ cJSON *dpow_listunspent(struct supernet_info *myinfo,struct iguana_info *coin,ch char buf[128],*retstr; cJSON *array,*json = 0; if ( coin->FULLNODE < 0 ) { - sprintf(buf,"0, 99999999, [\"%s\"]",coinaddr); + sprintf(buf,"1, 99999999, [\"%s\"]",coinaddr); if ( (retstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"listunspent",buf)) != 0 ) { json = cJSON_Parse(retstr); @@ -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"); @@ -1154,10 +1154,11 @@ void dpow_issuer_voutupdate(struct dpow_info *dp,char *symbol,int32_t isspecial, } } -int32_t dpow_issuer_tx(struct dpow_info *dp,struct iguana_info *coin,int32_t height,int32_t txi,char *txidstr,uint32_t port) +int32_t dpow_issuer_tx(int32_t *isspecialp,struct dpow_info *dp,struct iguana_info *coin,int32_t height,int32_t txi,char *txidstr,uint32_t port) { - char *retstr,params[256],*hexstr; uint8_t script[16384]; cJSON *json,*oldpub,*newpub,*result,*vouts,*item,*sobj; int32_t vout,n,len,isspecial,retval = -1; uint64_t value; bits256 txid; + char *retstr,params[256],*hexstr; uint8_t script[16384]; cJSON *json,*oldpub,*newpub,*result,*vouts,*item,*sobj; int32_t vout,n,len,retval = -1; uint64_t value; bits256 txid; sprintf(params,"[\"%s\", 1]",txidstr); + *isspecialp = 0; if ( (retstr= dpow_issuemethod(coin->chain->userpass,(char *)"getrawtransaction",params,port)) != 0 ) { if ( (json= cJSON_Parse(retstr)) != 0 ) @@ -1170,7 +1171,6 @@ int32_t dpow_issuer_tx(struct dpow_info *dp,struct iguana_info *coin,int32_t hei retval = 0; if ( oldpub == 0 && newpub == 0 && (vouts= jarray(&n,result,(char *)"vout")) != 0 ) { - isspecial = 0; txid = jbits256(result,(char *)"txid"); for (vout=0; vout> 1; if ( vout == 0 && ((memcmp(&hexstr[2],CRYPTO777_PUBSECPSTR,66) == 0 && len == 35) || (memcmp(&hexstr[6],CRYPTO777_RMD160STR,40) == 0 && len == 25)) ) - isspecial = 1; + *isspecialp = 1; else if ( len <= sizeof(script) ) { decode_hex(script,len,hexstr); - dpow_issuer_voutupdate(dp,coin->symbol,isspecial,height,txi,txid,vout,n,value,script,len); + dpow_issuer_voutupdate(dp,coin->symbol,*isspecialp,height,txi,txid,vout,n,value,script,len); } } } @@ -1202,7 +1202,7 @@ int32_t dpow_issuer_tx(struct dpow_info *dp,struct iguana_info *coin,int32_t hei int32_t dpow_issuer_block(struct dpow_info *dp,struct iguana_info *coin,int32_t height,uint16_t port) { - char *retstr,*retstr2,params[128],*txidstr; int32_t i,n,retval = -1; cJSON *json,*tx=0,*result=0,*result2; + char *retstr,*retstr2,params[128],*txidstr; int32_t i,isspecial,n,retval = -1; cJSON *json,*tx=0,*result=0,*result2; sprintf(params,"[%d]",height); if ( (retstr= dpow_issuemethod(coin->chain->userpass,(char *)"getblockhash",params,port)) != 0 ) { @@ -1219,7 +1219,7 @@ int32_t dpow_issuer_block(struct dpow_info *dp,struct iguana_info *coin,int32_t if ( (result2= jobj(json,(char *)"result")) != 0 && (tx= jarray(&n,result2,(char *)"tx")) != 0 ) { for (i=0; i= 0 ) + LP_RTmetrics.pending_swaps[ind]++; + return(ind); +} + +int32_t LP_RTmetrics_pendingswaps(bits256 pubkey) +{ + int32_t ind; + if ( (ind= LP_bits256_find(LP_RTmetrics.pending_pubkeys,LP_RTmetrics.numpendings,pubkey)) >= 0 ) + return(LP_RTmetrics.pending_swaps[ind]); + else return(0); +} + +int32_t LP_RTmetrics_avoidtxid(bits256 txid) +{ + return(LP_bits256_find(LP_RTmetrics.avoidtxids,LP_RTmetrics.numavoidtxids,txid)); +} + +int32_t LP_RTmetrics_whitelisted(bits256 pubkey) +{ + return(LP_bits256_find(LP_RTmetrics.whitelist,LP_RTmetrics.numwhitelist,pubkey)); +} + +int32_t LP_RTmetrics_blacklisted(bits256 pubkey) +{ + return(LP_bits256_find(LP_RTmetrics.blacklist,LP_RTmetrics.numblacklist,pubkey)); +} + +void LP_RTmetrics_swapsinfo(char *refbase,char *refrel,cJSON *swaps,int32_t numswaps) +{ + int32_t i; char *base,*rel,*retstr; cJSON *item,*swapjson; bits256 srcpub,destpub; uint64_t aliceid,basesatoshis,relsatoshis; uint32_t requestid,quoteid; double price; + for (i=0; iistrusted > 0 ) + LP_RTmetrics_whitelistadd(pubp->pubkey); + else if ( pubp->istrusted < 0 ) + LP_RTmetrics_blacklistadd(pubp->pubkey); + } + futuretime = (uint32_t)time(NULL) + 3600*100; + memset(zero.bytes,0,sizeof(zero)); + if ( (retstr= LP_statslog_disp(100,futuretime,futuretime,"",zero)) != 0 ) + { + if ( (statsjson= cJSON_Parse(retstr)) != 0 ) + { + if ( (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); + } + free(retstr); + } + for (i=0; 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]); + } + //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) +{ + int32_t n; double metric,origmetric = (mp->price / bestprice); + metric = origmetric; + if ( mp->numutxos == 0 || relvolume == 0. || mp->maxvol == 0. || mp->balance == 0. ) + { + //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; + else if ( mp->age > 60 ) + metric *= 1.03; + if ( (n= mp->pendingswaps) > 0 ) + while ( n-- > 0 ) + metric *= 1.1; + //if ( metric != origmetric ) + printf("i.%d price %.8f orig %.8f -> %.8f relvol %.8f min %.8f max %.8f bal %.8f age.%d pend.%d\n",mp->ind,mp->price,origmetric,metric,relvolume,mp->minvol,mp->maxvol,mp->balance,mp->age,mp->pendingswaps); + return(metric); +} + +void LP_RTmetric_calc(struct LP_metricinfo *sortbuf,int32_t ind,cJSON *item,double bestprice,double maxprice,double relvolume,double prevdepth) +{ + sortbuf[ind].pubkey = jbits256(item,"pubkey"); + sortbuf[ind].price = jdouble(item,"price"); + sortbuf[ind].maxvol = jdouble(item,"maxvolume"); + sortbuf[ind].minvol = jdouble(item,"minvolume"); + sortbuf[ind].balance = jdouble(item,"depth") - prevdepth; + sortbuf[ind].numutxos = juint(item,"numutxos"); + sortbuf[ind].age = juint(item,"age"); + sortbuf[ind].ind = ind; + sortbuf[ind].pendingswaps = LP_RTmetrics_pendingswaps(sortbuf[ind].pubkey); + 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; + groupi = -1; + bestprice = 0.; + for (num=i=0; i maxprice ) + break; + if ( i == 0 ) + bestprice = price; + else if ( price < bestprice*LP_RTMETRICS_TOPGROUP ) + groupi = i; + num++; + } + if ( groupi > 0 ) + { + sortbuf = calloc(groupi+1,sizeof(*sortbuf)); + prevdepth = 0.; + for (i=0; i<=groupi; i++) + { + item = jitem(rawasks,i); + LP_RTmetric_calc(sortbuf,i,item,bestprice,maxprice,relvolume,prevdepth); + prevdepth = jdouble(item,"depth"); + //printf("%.8f ",sortbuf[i].metric); + } + 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); + item = jitem(rawasks,sortbuf[i].ind); + jaddi(array,jduplicate(item)); + } + for (; i no privkey\n"); - return(zero); -} - -int32_t LP_privkeyadd(bits256 privkey,uint8_t rmd160[20]) -{ - bits256 tmpkey; - tmpkey = LP_privkeyfind(rmd160); - if ( bits256_nonz(tmpkey) != 0 ) - return(-bits256_cmp(privkey,tmpkey)); - LP_privkeys[LP_numprivkeys].privkey = privkey; - memcpy(LP_privkeys[LP_numprivkeys].rmd160,rmd160,20); - //int32_t i; for (i=0; i<20; i++) - // printf("%02x",rmd160[i]); - //char str[65]; printf(" -> add privkey.(%s)\n",bits256_str(str,privkey)); - LP_numprivkeys++; - return(LP_numprivkeys); -} - int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp) { int32_t i; uint64_t x; @@ -1988,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 cltv_rmd160[20],uint8_t anytime_rmd160[20]) +{ + script[n++] = SCRIPT_OP_IF; + n = bitcoin_checklocktimeverify(script,n,unlocktimestamp); + n = bitcoin_standardspend(script,n,cltv_rmd160); + script[n++] = SCRIPT_OP_ELSE; + n = bitcoin_standardspend(script,n,anytime_rmd160); + 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; @@ -2060,7 +2043,7 @@ int32_t bitcoin_addr2rmd160(uint8_t taddr,uint8_t *addrtypep,uint8_t rmd160[20], } for (i=0; itype); } +uint32_t iguana_vinscriptparse(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) +{ + uint32_t hashtype; uint8_t *userdata = 0; + *sigsizep = *pubkeysizep = *p2shsizep = *userdatalenp = 0; + if ( bitcoin_scriptget(taddr,pubtype,p2shtype,&hashtype,sigsizep,pubkeysizep,&userdata,userdatalenp,vp,vinscript,scriptlen,0) < 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; scriptjson = cJSON_CreateObject(); - jaddstr(scriptjson,"asm",asmstr); + if ( asmstr != 0 ) + jaddstr(scriptjson,"asm",asmstr); jaddnum(scriptjson,"numvars",numvars); if ( numvars > 0 ) { @@ -3186,7 +3188,7 @@ int32_t iguana_parsevoutobj(uint8_t *serialized,int32_t maxsize,struct iguana_ms cJSON *iguana_voutjson(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,struct iguana_msgvout *vout,int32_t txi,bits256 txid) { // 035f1321ed17d387e4433b2fa229c53616057964af065f98bfcae2233c5108055e OP_CHECKSIG - char scriptstr[IGUANA_MAXSCRIPTSIZE+1],asmstr[2*IGUANA_MAXSCRIPTSIZE+1]; int32_t i,m,n,scriptlen,asmtype; struct vin_info *vp; + char scriptstr[IGUANA_MAXSCRIPTSIZE+1]; int32_t i,m,n,scriptlen,asmtype; struct vin_info *vp; uint8_t space[8192]; cJSON *addrs,*skey,*json = cJSON_CreateObject(); vp = calloc(1,sizeof(*vp)); jadd64bits(json,"satoshis",vout->value); @@ -3196,12 +3198,12 @@ cJSON *iguana_voutjson(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,struct igu if ( vout->pk_script != 0 && vout->pk_scriptlen*2+1 < sizeof(scriptstr) ) { memset(vp,0,sizeof(*vp)); - if ( (asmtype= iguana_calcrmd160(taddr,pubtype,p2shtype,asmstr,vp,vout->pk_script,vout->pk_scriptlen,txid,txi,0xffffffff)) >= 0 ) + if ( (asmtype= iguana_calcrmd160(taddr,pubtype,p2shtype,0,vp,vout->pk_script,vout->pk_scriptlen,txid,txi,0xffffffff)) >= 0 ) { skey = cJSON_CreateObject(); - scriptlen = iguana_scriptgen(taddr,pubtype,p2shtype,&m,&n,vp->coinaddr,space,asmstr,vp->rmd160,asmtype,vp,txi); - if ( asmstr[0] != 0 ) - jaddstr(skey,"asm",asmstr); + scriptlen = iguana_scriptgen(taddr,pubtype,p2shtype,&m,&n,vp->coinaddr,space,0,vp->rmd160,asmtype,vp,txi); + //if ( asmstr[0] != 0 ) + // jaddstr(skey,"asm",asmstr); addrs = cJSON_CreateArray(); if ( vp->N == 1 ) { @@ -3229,6 +3231,7 @@ cJSON *iguana_voutjson(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,struct igu jadd(json,"scriptPubKey",skey); } } + free(vp); return(json); } @@ -3276,9 +3279,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 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); -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) +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,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; @@ -3287,7 +3290,7 @@ 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_ALL ) + if ( (hashtype & ~SIGHASH_FORKID) != SIGHASH_ALL ) { printf("currently only SIGHASH_ALL supported, not %d\n",hashtype); return(sigtxid); @@ -3312,7 +3315,7 @@ bits256 bitcoin_sigtxid(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t i 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); + len = iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,1,0,serialized,maxlen,&dest,&txid,vpnstr,0,0,0,suppress_pubkeys,zcash); //for (i=0; ivpub_old),&msg->vpub_old); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->vpub_new),&msg->vpub_new); + + len += iguana_rwbignum(rwflag,&serialized[len],sizeof(msg->anchor),msg->anchor.bytes); + len += iguana_rwbignum(rwflag,&serialized[len],sizeof(msg->nullifiers[0]),msg->nullifiers[0].bytes); + len += iguana_rwbignum(rwflag,&serialized[len],sizeof(msg->nullifiers[1]),msg->nullifiers[1].bytes); + len += iguana_rwbignum(rwflag,&serialized[len],sizeof(msg->commitments[0]),msg->commitments[0].bytes); + len += iguana_rwbignum(rwflag,&serialized[len],sizeof(msg->commitments[1]),msg->commitments[1].bytes); + len += iguana_rwbignum(rwflag,&serialized[len],sizeof(msg->ephemeralkey),msg->ephemeralkey.bytes); + if ( rwflag == 1 ) + memcpy(&serialized[len],msg->ciphertexts,sizeof(msg->ciphertexts)); + else memcpy(msg->ciphertexts,&serialized[len],sizeof(msg->ciphertexts)); + len += sizeof(msg->ciphertexts); + len += iguana_rwbignum(rwflag,&serialized[len],sizeof(msg->randomseed),msg->randomseed.bytes); + len += iguana_rwbignum(rwflag,&serialized[len],sizeof(msg->vmacs[0]),msg->vmacs[0].bytes); + len += iguana_rwbignum(rwflag,&serialized[len],sizeof(msg->vmacs[1]),msg->vmacs[1].bytes); + if ( rwflag == 1 ) + memcpy(&serialized[len],msg->zkproof,sizeof(msg->zkproof)); + else memcpy(msg->zkproof,&serialized[len],sizeof(msg->zkproof)); + len += sizeof(msg->zkproof); + 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) { - 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]; cJSON *vinarray=0,*voutarray=0; bits256 sigtxid; + len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->version),&msg->version); if ( json != 0 ) { @@ -3354,6 +3384,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 ) { @@ -3371,7 +3417,7 @@ int32_t iguana_rwmsgtx(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t is } for (i=0; itx_in; i++) { - //printf("vin.%d starts offset.%d\n",i,len); + //printf("vin.%d starts offset.%d numvins.%d\n",i,len,msg->tx_in); if ( vins != 0 && jitem(vins,i) != 0 ) iguana_vinobjset(&msg->vins[i],jitem(vins,i),spendscript,sizeof(spendscript)); if ( (n= iguana_vinparse(rwflag,&serialized[len],&msg->vins[i])) < 0 ) @@ -3409,7 +3455,7 @@ int32_t iguana_rwmsgtx(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t is } for (i=0; itx_out; i++) { - //printf("rwflag.%d vout.%d starts %d\n",rwflag,i,len); + //printf("rwflag.%d vout.%d starts %d numvouts.%d\n",rwflag,i,len,msg->tx_out); if ( (n= iguana_voutparse(rwflag,&serialized[len],&msg->vouts[i])) < 0 ) return(-1); len += n; @@ -3421,28 +3467,65 @@ 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)); } - 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 ( strcmp(coin->symbol,"VPN") == 0 ) + if ( segwitflag != 0 ) { - uint16_t ddosflag = 0; - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ddosflag),&ddosflag); - for (i=0; serialized[len]!=0&&lenlock_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 { - if ( rwflag == 0 ) - serialized[len] = vpnstr[i]; - else vpnstr[i] = serialized[len]; + for (i=0; itx_in; i++) + { + len += iguana_rwvarint32(rwflag,&serialized[len],&segitems); + //printf("vini.%d (%d:",i,segitems); + for (j=0; j= 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)); } - if ( rwflag == 0 ) - serialized[len] = 0; - else vpnstr[i] = 0; - len++; - if ( json != 0 ) + } + 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 ) + { + uint32_t numjoinsplits; struct iguana_msgjoinsplit joinsplit; uint8_t joinsplitpubkey[33],joinsplitsig[64]; + len += iguana_rwvarint32(rwflag,&serialized[len],&numjoinsplits); + if ( numjoinsplits > 0 ) { - jaddnum(json,"ddosflag",ddosflag); - jaddstr(json,"vpnstr",vpnstr); + for (i=0; itx_in; i++) @@ -3450,8 +3533,12 @@ 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); + sighash = SIGHASH_ALL; + if ( zcash == LP_IS_BITCOINCASH ) + sighash |= SIGHASH_FORKID; + sigtxid = bitcoin_sigtxid(taddr,pubtype,p2shtype,isPoS,height,sigser,maxsize*2,msg,i,msg->vins[i].spendscript,msg->vins[i].spendlen,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)); @@ -3470,7 +3557,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); @@ -3548,13 +3636,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) +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) { 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)) > 0 ) + 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 ) { txbytes = malloc(n*2+1); init_hexbytes_noT(txbytes,serialized,n); @@ -3582,7 +3670,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) +cJSON *bitcoin_data2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash) { int32_t n; char vpnstr[64]; struct iguana_msgtx M; cJSON *txobj; if ( serialized == 0 ) @@ -3593,7 +3681,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)) <= 0 ) + if ( (n= iguana_rwmsgtx(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); @@ -3604,14 +3692,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; itaddr,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 = 0;//serialized; + free(serialized); + tx->fpos = fpos; + tx->len = 0;//tx->len; + tx->SPV = tx->height = height; + //printf("tx.%s numvins.%d numvouts.%d\n",bits256_str(str,txid),numvins,numvouts); + for (i=0; ioutpoints[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; inumvouts ) + { + 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> 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>= 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,SPV = 0; + if ( height <= 0 ) + return(0); + if ( (tx= LP_transactionfind(coin,txid)) == 0 && strcmp(coinaddr,coin->smartaddr) == 0 ) + { + if ( (retjson= electrum_transaction(coin->symbol,ep,&retjson,txid,0)) != 0 ) + free_json(retjson); + } + if ( tx != 0 ) + { + tx->height = 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 ( 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; 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; ielectrum,coin->smartaddr,retjson,1); + free_json(retjson); + } + free(arraystr); + } + } + return(balance); +} + + + diff --git a/iguana/exchanges/LP_coins.c b/iguana/exchanges/LP_coins.c index a5fd82434..7f43a005a 100644 --- a/iguana/exchanges/LP_coins.c +++ b/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; isymbol); if ( showwif != 0 ) { - bitcoin_priv2wif(coin->wiftaddr,wifstr,LP_mypriv25519,coin->wiftype); + bitcoin_priv2wif(coin->wiftaddr,wifstr,G.LP_privkey,coin->wiftype); bitcoin_wif2priv(coin->wiftaddr,&tmptype,&checkkey,wifstr); - if ( bits256_cmp(LP_mypriv25519,checkkey) == 0 ) + if ( bits256_cmp(G.LP_privkey,checkkey) == 0 ) jaddstr(item,"wif",wifstr); else jaddstr(item,"wif","error creating wif"); } + jadd(item,"installed",coin->userpass[0] == 0 ? jfalse() : jtrue()); + if ( coin->userpass[0] != 0 ) + { + jaddnum(item,"height",LP_getheight(coin)); + 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))); + } + else + { + jaddnum(item,"height",-1); + jaddnum(item,"balance",0); + } if ( coin->inactive != 0 ) + { jaddstr(item,"status","inactive"); + } else jaddstr(item,"status","active"); if ( coin->isPoS != 0 ) jaddstr(item,"type","PoS"); + if ( (ep= coin->electrum) != 0 ) + { + sprintf(ipaddr,"%s:%u",ep->ipaddr,ep->port); + jaddstr(item,"electrum",ipaddr); + } jaddstr(item,"smartaddress",coin->smartaddr); jaddstr(item,"rpc",coin->serverport); 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)); return(item); } +struct iguana_info *LP_conflicts_find(struct iguana_info *refcoin) +{ + struct iguana_info *coin=0,*tmp; + if ( refcoin != 0 ) + { + 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); +} + cJSON *LP_coinsjson(int32_t showwif) { struct iguana_info *coin,*tmp; cJSON *array = cJSON_CreateArray(); @@ -209,62 +262,78 @@ 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); } struct iguana_info *LP_coinadd(struct iguana_info *cdata) { struct iguana_info *coin = calloc(1,sizeof(*coin)); - //printf("%s: (%s) (%s)\n",symbol,cdata.serverport,cdata.userpass); *coin = *cdata; portable_mutex_init(&coin->txmutex); + portable_mutex_init(&coin->addrmutex); portable_mutex_lock(&LP_coinmutex); HASH_ADD_KEYPTR(hh,LP_coins,coin->symbol,strlen(coin->symbol),coin); portable_mutex_unlock(&LP_coinmutex); return(coin); } -int32_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *assetname,int32_t isPoS,uint16_t port,uint8_t pubtype,uint8_t p2shtype,uint8_t wiftype,uint64_t txfee,double estimatedrate,int32_t longestchain,uint8_t wiftaddr,uint8_t taddr,uint16_t busport,char *confpath) +uint16_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *assetname,int32_t isPoS,uint16_t port,uint8_t pubtype,uint8_t p2shtype,uint8_t wiftype,uint64_t txfee,double estimatedrate,int32_t longestchain,uint8_t wiftaddr,uint8_t taddr,uint16_t busport,char *confpath) { + static void *ctx; char *name2; memset(coin,0,sizeof(*coin)); safecopy(coin->symbol,symbol,sizeof(coin->symbol)); - sprintf(coin->serverport,"127.0.0.1:%u",port); + coin->updaterate = (uint32_t)time(NULL); coin->isPoS = isPoS; coin->taddr = taddr; coin->wiftaddr = wiftaddr; coin->longestchain = longestchain; - coin->txfee = txfee; + if ( (coin->txfee= txfee) > 0 && txfee < LP_MIN_TXFEE ) + coin->txfee = LP_MIN_TXFEE; coin->pubtype = pubtype; coin->p2shtype = p2shtype; coin->wiftype = wiftype; coin->inactive = (uint32_t)time(NULL); coin->bussock = LP_coinbus(busport); + if ( ctx == 0 ) + ctx = bitcoin_ctx(); + coin->ctx = ctx; + if ( assetname != 0 && strcmp(name,assetname) == 0 ) + { + //printf("%s is assetchain\n",symbol); + coin->isassetchain = 1; + } if ( strcmp(symbol,"KMD") == 0 || (assetname != 0 && assetname[0] != 0) ) name2 = 0; else name2 = name; @@ -273,7 +342,18 @@ int32_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *asset coin->noimportprivkey_flag = 1; printf("truncate importprivkey for %s\n",symbol); } - return(LP_userpass(coin->userpass,symbol,assetname,name,name2,confpath)); +#ifndef FROM_JS + port = LP_userpass(coin->userpass,symbol,assetname,name,name2,confpath,port); +#endif + sprintf(coin->serverport,"127.0.0.1:%u",port); + if ( strcmp(symbol,"KMD") == 0 || coin->isassetchain != 0 || taddr != 0 ) + coin->zcash = LP_IS_ZCASHPROTOCOL; + else if ( strcmp(symbol,"BCH") == 0 ) + { + coin->zcash = LP_IS_BITCOINCASH; + //printf("set coin.%s <- LP_IS_BITCOINCASH %d\n",symbol,coin->zcash); + } + return(port); } int32_t LP_isdisabled(char *base,char *rel) @@ -289,6 +369,8 @@ int32_t LP_isdisabled(char *base,char *rel) struct iguana_info *LP_coinfind(char *symbol) { struct iguana_info *coin,cdata; int32_t isinactive,isPoS,longestchain = 1; uint16_t port,busport; uint64_t txfee; double estimatedrate; uint8_t pubtype,p2shtype,wiftype; char *name,*assetname; + if ( symbol == 0 || symbol[0] == 0 ) + return(0); if ( (coin= LP_coinsearch(symbol)) != 0 ) return(coin); if ( (port= LP_rpcport(symbol)) == 0 ) @@ -314,13 +396,16 @@ struct iguana_info *LP_coinfind(char *symbol) else if ( strcmp(symbol,"KMD") == 0 ) name = "komodo"; else return(0); - isinactive = LP_coininit(&cdata,symbol,name,assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,0,0,busport,0) < 0; + port = LP_coininit(&cdata,symbol,name,assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,0,0,busport,0); + if ( port == 0 ) + isinactive = 1; + else isinactive = 0; if ( (coin= LP_coinadd(&cdata)) != 0 ) { coin->inactive = isinactive * (uint32_t)time(NULL); - 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); @@ -374,7 +459,7 @@ struct iguana_info *LP_coincreate(cJSON *item) } } else coin->inactive = 0; } - if ( coin != 0 && coin->inactive != 0 ) + if ( 0 && coin != 0 && coin->inactive != 0 ) printf("LPnode.%d %s inactive.%u %p vs %p\n",IAMLP,coin->symbol,coin->inactive,assetname,name); return(0); } diff --git a/iguana/exchanges/LP_commands.c b/iguana/exchanges/LP_commands.c index f50c73ab5..d2f72406d 100644 --- a/iguana/exchanges/LP_commands.c +++ b/iguana/exchanges/LP_commands.c @@ -25,18 +25,21 @@ char *LP_numutxos() { jaddstr(retjson,"ipaddr",LP_mypeer->ipaddr); jaddnum(retjson,"port",LP_mypeer->port); - jaddnum(retjson,"numutxos",LP_mypeer->numutxos); + //jaddnum(retjson,"numutxos",LP_mypeer->numutxos); jaddnum(retjson,"numpeers",LP_mypeer->numpeers); - jaddnum(retjson,"session",LP_sessionid); + jaddnum(retjson,"session",G.LP_sessionid); } else jaddstr(retjson,"error","client node"); return(jprint(retjson,1)); } 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,othernumutxos,flag = 0; struct LP_peerinfo *peer; cJSON *retjson,*reqjson = 0; struct iguana_info *ptr; -//printf("stats_JSON(%s)\n",jprint(argjson,0)); - if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 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 ( method != 0 && (strcmp(method,"addr_unspents") == 0 || strcmp(method,"uitem") == 0 || strcmp(method,"postutxos") == 0) ) + return(0); +//printf("stats_JSON %s\n",method); + /*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 ) { @@ -49,103 +52,142 @@ 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= jstr(argjson,"method")) == 0 ) + }*/ + 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 ) + 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 ) - { - static char *laststr; - char *newstr; bits256 pubkey = jbits256(argjson,"pubkey"); - if ( bits256_nonz(pubkey) == 0 || bits256_cmp(pubkey,LP_mypub25519) == 0 ) - { - newstr = jprint(argjson,0); - if ( laststr == 0 || strcmp(laststr,newstr) != 0 ) - { - printf("got message.(%s) from %s:%u\n",newstr,ipaddr!=0?ipaddr:"",argport); - if ( laststr != 0 ) - free(laststr); - laststr = newstr; - LP_gotmessage(argjson); - retstr = clonestr(laststr); - } - } else retstr = clonestr("{\"error\":\"duplicate message\"}"); + 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"); + if ( bits256_nonz(pubkey) == 0 || bits256_cmp(pubkey,G.LP_mypub25519) == 0 ) + { + newstr = jprint(argjson,0); + if ( laststr == 0 || strcmp(laststr,newstr) != 0 ) + { + printf("got message.(%s) from %s:%u\n",newstr,ipaddr!=0?ipaddr:"",argport); + if ( laststr != 0 ) + free(laststr); + laststr = newstr; + LP_gotmessage(argjson); + 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, firsttime=0, lasttime=-1, timescale=60) -> [timestamp, avebid, aveask, highbid, lowask]\n\ + 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, price, margin, type)\n\ +autoprice(base, rel, fixed, minprice, margin, refbase, refrel, factor, offset)*\n\ goal(coin=*, val=)\n\ myprice(base, rel)\n\ enable(coin)\n\ disable(coin)\n\ -inventory(coin)\n\ +notarizations(coin)\n\ +parselog()\n\ +statsdisp(starttime=0, endtime=0, gui="", pubkey="")\n\ +getrawtransaction(coin, txid)\n\ +inventory(coin, reset=0, [passphrase=])\n\ bestfit(rel, relvolume)\n\ -ordermatch(base, txfee=0, rel, desttxfee=0, price, relvolume=0, txid, vout, feetxid, feevout, duration=3600)\n\ -trade(price, timeout=10, duration=3600, )\n\ -autotrade(base, rel, price, relvolume, timeout=10, duration=3600)\n\ +lastnonce()\n\ +buy(base, rel, price, relvolume, timeout=10, duration=3600, nonce, destpubkey="")\n\ +sell(base, rel, price, basevolume, timeout=10, duration=3600, nonce, destpubkey="")\n\ +withdraw(coin, outputs[])\n\ +sendrawtransaction(coin, signedtx)\n\ swapstatus()\n\ +swapstatus(coin, limit=10)\n\ +swapstatus(base, rel, limit=10)\n\ swapstatus(requestid, quoteid)\n\ +recentswaps(limit=3)\n\ public API:\n \ getcoins()\n\ getcoin(coin)\n\ portfolio()\n\ getpeers()\n\ -getutxos()\n\ -getutxos(coin, lastn)\n\ +passphrase(passphrase, gui)\n\ +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\ orderbook(base, rel, duration=3600)\n\ getprices(base, rel)\n\ -sendmessage(base=coin, rel="", pubkey=zero, )\n\ -getmessages(firsti=0, num=100)\n\ -clearmessages(firsti=0, num=100)\n\ +//sendmessage(base=coin, rel="", pubkey=zero, )\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, )\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\ +bot_resume(botid)\n\ \"}")); + //sell(base, rel, price, basevolume, timeout=10, duration=3600)\n\ - base = jstr(argjson,"base"); - rel = jstr(argjson,"rel"); - if ( USERPASS[0] != 0 && strcmp(remoteaddr,"127.0.0.1") == 0 && port != 0 ) + 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 ( USERPASS_COUNTER == 0 ) + if ( G.USERPASS_COUNTER == 0 ) { - USERPASS_COUNTER = 1; + G.USERPASS_COUNTER = 1; retjson = cJSON_CreateObject(); - jaddstr(retjson,"userpass",USERPASS); - jaddbits256(retjson,"mypubkey",LP_mypub25519); + jaddstr(retjson,"userpass",G.USERPASS); + jaddbits256(retjson,"mypubkey",G.LP_mypub25519); jadd(retjson,"coins",LP_coinsjson(LP_showwif)); return(jprint(retjson,1)); } - if ( (userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,USERPASS) != 0 ) - return(clonestr("{\"error\":\"authentication error\"}")); + if ( strcmp(method,"passphrase") != 0 && ((userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,G.USERPASS) != 0) ) + return(clonestr("{\"error\":\"authentication error you need to make sure userpass is set\"}")); jdelete(argjson,"userpass"); - if ( strcmp(method,"sendmessage") == 0 ) + if ( strcmp(method,"passphrase") == 0 ) + { + G.USERPASS_COUNTER = 1; + if ( LP_passphrase_init(jstr(argjson,"passphrase"),jstr(argjson,"gui")) < 0 ) + return(clonestr("{\"error\":\"couldnt change passphrase\"}")); + { + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jaddstr(retjson,"userpass",G.USERPASS); + jaddbits256(retjson,"mypubkey",G.LP_mypub25519); + return(jprint(retjson,1)); + } + } + /*else if ( strcmp(method,"sendmessage") == 0 ) { if ( jobj(argjson,"method2") == 0 ) { - printf("broadcast message\n"); - LP_broadcast_message(LP_mypubsock,base!=0?base:jstr(argjson,"coin"),rel,jbits256(argjson,"pubkey"),jprint(argjson,0)); + LP_broadcast_message(LP_mypubsock,base!=0?base:coin,rel,jbits256(argjson,"pubkey"),jprint(argjson,0)); } return(clonestr("{\"result\":\"success\"}")); } @@ -159,38 +201,112 @@ dividends(coin, height, )\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); + return(jprint(retjson,1)); + } else return(clonestr("{\"error\":\"cant find coin\"}")); } else if ( strcmp(method,"portfolio") == 0 ) { return(LP_portfolio()); } - if ( base != 0 && rel != 0 ) + 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"))); + } + else if ( strcmp(method,"secretaddresses") == 0 ) + { + uint8_t taddr,pubtype; + pubtype = (jobj(argjson,"pubtype") == 0) ? 60 : juint(argjson,"pubtype"); + taddr = (jobj(argjson,"taddr") == 0) ? 0 : juint(argjson,"taddr"); + return(LP_secretaddresses(ctx,jstr(argjson,"prefix"),jstr(argjson,"passphrase"),juint(argjson,"num"),taddr,pubtype)); + } + else if ( strcmp(method,"swapstatus") == 0 ) + { + uint32_t requestid,quoteid; + if ( (requestid= juint(argjson,"requestid")) != 0 && (quoteid= juint(argjson,"quoteid")) != 0 ) + return(basilisk_swapentry(requestid,quoteid)); + else if ( coin[0] != 0 ) + return(basilisk_swapentries(coin,0,jint(argjson,"limit"))); + else if ( base[0] != 0 && rel[0] != 0 ) + return(basilisk_swapentries(base,rel,jint(argjson,"limit"))); + else return(basilisk_swaplist(0,0)); + } + else if ( (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(base,rel,argjson) < 0 ) + return(clonestr("{\"error\":\"couldnt set autoprice\"}")); + else return(clonestr("{\"result\":\"success\"}")); + } if ( IAMLP == 0 && LP_isdisabled(base,rel) != 0 ) return(clonestr("{\"error\":\"at least one of coins disabled\"}")); price = jdouble(argjson,"price"); if ( strcmp(method,"setprice") == 0 ) { - if ( price > SMALLVAL ) - { - if ( LP_mypriceset(&changed,base,rel,price) < 0 ) - 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 return(clonestr("{\"error\":\"no price\"}")); - } - else if ( strcmp(method,"autoprice") == 0 ) - { - if ( LP_autoprice(base,rel,price,jdouble(argjson,"margin"),jstr(argjson,"type")) < 0 ) - return(clonestr("{\"error\":\"couldnt set autoprice\"}")); - else return(clonestr("{\"result\":\"success\"}")); + if ( LP_mypriceset(&changed,base,rel,price) < 0 ) + return(clonestr("{\"error\":\"couldnt set price\"}")); + //else if ( LP_mypriceset(&changed,rel,base,1./price) < 0 ) + // return(clonestr("{\"error\":\"couldnt set price\"}")); + else return(LP_pricepings(ctx,myipaddr,LP_mypubsock,base,rel,price * LP_profitratio)); } else if ( strcmp(method,"pricearray") == 0 ) { - return(jprint(LP_pricearray(base,rel,juint(argjson,"firsttime"),juint(argjson,"lasttime"),jint(argjson,"timescale")),1)); + uint32_t firsttime; + if ( base[0] != 0 && rel[0] != 0 ) + { + if ( (firsttime= juint(argjson,"firsttime")) < time(NULL)-30*24*3600 ) + firsttime = (uint32_t)(time(NULL)-30*24*3600); + return(jprint(LP_pricearray(base,rel,firsttime,juint(argjson,"lasttime"),jint(argjson,"timescale")),1)); + } else return(clonestr("{\"error\":\"pricearray needs base and rel\"}")); } + /*else if ( 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 ) @@ -203,49 +319,147 @@ dividends(coin, height, )\n\ return(jprint(retjson,1)); } else return(clonestr("{\"error\":\"no price set\"}")); } - else if ( strcmp(method,"ordermatch") == 0 ) + else if ( strcmp(method,"buy") == 0 ) { + //* if ( price > SMALLVAL ) - return(LP_ordermatch(base,j64bits(argjson,"txfee"),price,jdouble(argjson,"relvolume"),rel,jbits256(argjson,"txid"),jint(argjson,"vout"),jbits256(argjson,"feetxid"),jint(argjson,"feevout"),j64bits(argjson,"desttxfee"),jint(argjson,"duration"))); - else return(clonestr("{\"error\":\"no price set\"}")); - } - else if ( strcmp(method,"trade") == 0 ) - { - struct LP_quoteinfo Q; - if ( price > SMALLVAL || jobj(argjson,"quote") != 0 ) { - LP_quoteparse(&Q,jobj(argjson,"quote")); - return(LP_trade(ctx,myipaddr,pubsock,&Q,price,jint(argjson,"timeout"),jint(argjson,"duration"))); - } else return(clonestr("{\"error\":\"no price set or no quote object\"}")); + 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,"autotrade") == 0 ) + else if ( strcmp(method,"sell") == 0 ) { + //* if ( price > SMALLVAL ) { - return(LP_autotrade(ctx,myipaddr,pubsock,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration"))); + 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 ) { + //* if ( (ptr= LP_coinsearch(coin)) != 0 ) - ptr->inactive = 0; - return(jprint(LP_coinsjson(0),1)); + { + if ( ptr->userpass[0] == 0 ) + { + cJSON *retjson = cJSON_CreateObject(); + jaddstr(retjson,"error","couldnt find coin locally installed"); + jaddstr(retjson,"coin",coin); + return(jprint(retjson,1)); + } + if ( LP_conflicts_find(ptr) == 0 ) + { + ptr->inactive = 0; + cJSON *array; + if ( ptr->smartaddr[0] != 0 ) + LP_unspents_load(coin,ptr->smartaddr); + if ( LP_getheight(ptr) <= 0 ) + { + ptr->inactive = (uint32_t)time(NULL); + return(clonestr("{\"error\":\"coin cant be activated till synced\"}")); + } else LP_unspents_load(coin,ptr->smartaddr); + array = cJSON_CreateArray(); + jaddi(array,LP_coinjson(ptr,0)); + return(jprint(array,1)); + } else return(clonestr("{\"error\":\"coin port conflicts with existing coin\"}")); + } else return(clonestr("{\"error\":\"couldnt find coin\"}")); } else if ( strcmp(method,"disable") == 0 ) { + //* if ( (ptr= LP_coinsearch(coin)) != 0 ) + { ptr->inactive = (uint32_t)time(NULL); - return(jprint(LP_coinsjson(0),1)); + cJSON *array = cJSON_CreateArray(); + jaddi(array,LP_coinjson(ptr,0)); + return(jprint(array,1)); + } else return(clonestr("{\"error\":\"couldnt find coin\"}")); + } + else if ( strcmp(method,"listunspent") == 0 ) + { + if ( (ptr= LP_coinsearch(coin)) != 0 ) + { + char *coinaddr; + 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); + LP_privkey_init(-1,ptr,G.LP_privkey,G.LP_mypub25519); + //LP_smartutxos_push(ptr); + if ( ptr->electrum != 0 ) + return(LP_unspents_filestr(coin,ptr->smartaddr)); + else return(jprint(LP_address_utxos(ptr,coinaddr,1),1)); + } + else + { + return(clonestr("{\"error\":\"not my address\"}")); + } + } + return(jprint(LP_address_utxos(ptr,coinaddr,1),1)); + } else return(clonestr("{\"error\":\"no address specified\"}")); + } else return(clonestr("{\"error\":\"cant find coind\"}")); + } + else if ( strcmp(method,"balance") == 0 ) + { + 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 ) + { + ptr->inactive = 0; + return(jprint(LP_electrumserver(ptr,jstr(argjson,"ipaddr"),juint(argjson,"port")),1)); + } else return(clonestr("{\"error\":\"cant find coind\"}")); + } + else if ( strcmp(method,"sendrawtransaction") == 0 ) + { + return(LP_sendrawtransaction(coin,jstr(argjson,"signedtx"))); + } + else if ( strcmp(method,"getrawtransaction") == 0 ) + { + return(jprint(LP_gettx(coin,jbits256(argjson,"txid")),1)); + } + else if ( strcmp(method,"withdraw") == 0 ) + { + if ( (ptr= LP_coinsearch(coin)) != 0 ) + { + if ( jobj(argjson,"outputs") == 0 ) + return(clonestr("{\"error\":\"withdraw needs to have outputs\"}")); + else return(LP_withdraw(ptr,argjson)); + } + return(clonestr("{\"error\":\"cant find coind\"}")); + } + else if ( strcmp(method,"setconfirms") == 0 ) + { + int32_t n; + n = jint(argjson,"numconfirms"); + if ( n < 0 ) + return(clonestr("{\"error\":\"illegal numconfirms\"}")); + if ( (ptr= LP_coinsearch(coin)) != 0 ) + { + ptr->userconfirms = n; + if ( (n= jint(argjson,"maxconfirms")) > 0 ) + ptr->maxconfirms = n; + if ( ptr->maxconfirms > 0 && ptr->userconfirms > ptr->maxconfirms ) + ptr->userconfirms = ptr->maxconfirms; + return(clonestr("{\"result\":\"success\"}")); + } else return(clonestr("{\"error\":\"cant find coind\"}")); } else if ( strcmp(method,"snapshot") == 0 ) { @@ -259,6 +473,12 @@ dividends(coin, height, )\n\ return(LP_dividends(ptr,juint(argjson,"height"),argjson)); else return(clonestr("{\"error\":\"cant find coind\"}")); } + else if ( strcmp(method,"snapshot_balance") == 0 ) + { + if ( (ptr= LP_coinsearch(coin)) != 0 ) + return(LP_snapshot_balance(ptr,juint(argjson,"height"),argjson)); + else return(clonestr("{\"error\":\"cant find coind\"}")); + } if ( LP_isdisabled(coin,0) != 0 ) return(clonestr("{\"error\":\"coin is disabled\"}")); if ( strcmp(method,"inventory") == 0 ) @@ -266,16 +486,23 @@ dividends(coin, height, )\n\ struct iguana_info *ptr; if ( (ptr= LP_coinfind(coin)) != 0 ) { - //privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,ptr,"",USERPASS_WIFSTR); - //LP_utxopurge(0); - if ( bits256_nonz(LP_mypriv25519) != 0 ) - LP_privkey_init(-1,ptr,LP_mypriv25519,LP_mypub25519); + 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"); retjson = cJSON_CreateObject(); jaddstr(retjson,"result","success"); jaddstr(retjson,"coin",coin); jaddnum(retjson,"timestamp",time(NULL)); - jadd(retjson,"alice",LP_inventory(coin,0)); - jadd(retjson,"bob",LP_inventory(coin,1)); + jadd(retjson,"alice",LP_inventory(coin)); + //jadd(retjson,"bob",LP_inventory(coin,1)); + LP_smartutxos_push(ptr); return(jprint(retjson,1)); } } @@ -286,18 +513,20 @@ dividends(coin, height, )\n\ } else if ( strcmp(method,"goal") == 0 ) return(LP_portfolio_goal("*",100.)); - else if ( strcmp(method,"swapstatus") == 0 ) + else if ( strcmp(method,"lastnonce") == 0 ) { - uint32_t requestid,quoteid; - if ( (requestid= juint(argjson,"requestid")) != 0 && (quoteid= juint(argjson,"quoteid")) != 0 ) - return(basilisk_swapentry(requestid,quoteid)); - else return(basilisk_swaplist()); + cJSON *retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jaddnum(retjson,"lastnonce",LP_lastnonce); + return(jprint(retjson,1)); } else if ( strcmp(method,"myprices") == 0 ) return(LP_myprices()); else if ( strcmp(method,"trust") == 0 ) return(LP_pubkey_trustset(jbits256(argjson,"pubkey"),jint(argjson,"trust"))); - } + else if ( strcmp(method,"trusted") == 0 ) + return(LP_pubkey_trusted()); + } // end of protected localhost commands if ( IAMLP == 0 ) { if ( (reqjson= LP_dereference(argjson,"broadcast")) != 0 ) @@ -311,88 +540,92 @@ dividends(coin, height, )\n\ argjson = reqjson; } } - if ( IAMLP == 0 && LP_isdisabled(base,rel) != 0 ) - return(clonestr("{\"result\":\"at least one of coins disabled\"}")); - else if ( IAMLP == 0 && LP_isdisabled(jstr(argjson,"coin"),0) != 0 ) - retstr = clonestr("{\"result\":\"coin is disabled\"}"); - else if ( strcmp(method,"reserved") == 0 ) - retstr = LP_quotereceived(argjson); - else if ( strcmp(method,"connected") == 0 ) - retstr = LP_connectedalice(argjson); - else if ( strcmp(method,"checktxid") == 0 ) - retstr = LP_spentcheck(argjson); - else if ( strcmp(method,"getcoins") == 0 ) - return(jprint(LP_coinsjson(0),1)); - else if ( strcmp(method,"numutxos") == 0 ) - return(LP_numutxos()); - else if ( strcmp(method,"postprice") == 0 ) - retstr = LP_postedprice(argjson); - else if ( strcmp(method,"encrypted") == 0 ) - retstr = clonestr("{\"result\":\"success\"}"); - 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,"registerall") == 0 ) - return(clonestr("{\"error\":\"you are running an obsolete version, update\"}")); - else if ( strcmp(method,"forward") == 0 ) - return(clonestr("{\"error\":\"you are running an obsolete version, update\"}")); - else if ( strcmp(method,"keepalive") == 0 ) - return(clonestr("{\"error\":\"you are running an obsolete version, update\"}")); + // received response + 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,"notify") == 0 ) + return(LP_notify_recv(argjson)); else if ( strcmp(method,"getpeers") == 0 ) - return(LP_peers()); - else if ( strcmp(method,"getutxos") == 0 ) - return(LP_utxos(1,LP_mypeer,jstr(argjson,"coin"),jint(argjson,"lastn"))); - else if ( strcmp(method,"utxo") == 0 ) + retstr = clonestr("{\"error\":\"deprecated\"}"); + /*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 + + else if ( strcmp(method,"tradestatus") == 0 ) { - if ( LP_utxoaddjson(1,LP_mypubsock,argjson) != 0 ) - retstr = clonestr("{\"result\":\"success\",\"utxo\":\"received\"}"); - else retstr = clonestr("{\"result\":\"couldnt add utxo\"}"); + LP_tradecommand_log(argjson); + printf("GOT TRADESTATUS! %s\n",jprint(argjson,0)); + retstr = clonestr("{\"result\":\"success\"}"); } - else + else if ( strcmp(method,"wantnotify") == 0 ) { - if ( IAMLP != 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+60 ) + { + lastnotify = (uint32_t)time(NULL); + //printf("wantnotify for me!\n"); + LP_notify_pubkeys(ctx,LP_mypubsock); + } + retstr = clonestr("{\"result\":\"success\"}"); + } + else if ( strcmp(method,"addr_unspents") == 0 ) + { + //printf("GOT ADDR_UNSPENTS %s %s\n",jstr(argjson,"coin"),jstr(argjson,"address")); + if ( (ptr= LP_coinsearch(coin)) != 0 ) { - if ( strcmp(method,"register") == 0 ) - return(clonestr("{\"error\":\"you are running an obsolete version, update\"}")); - else if ( strcmp(method,"lookup") == 0 ) - return(clonestr("{\"error\":\"you are running an obsolete version, update\"}")); - if ( strcmp(method,"broadcast") == 0 ) + char *coinaddr; + if ( (coinaddr= jstr(argjson,"address")) != 0 ) { - bits256 zero; char *cipherstr; int32_t cipherlen; uint8_t cipher[LP_ENCRYPTED_MAXSIZE]; - if ( (reqjson= LP_dereference(argjson,"broadcast")) != 0 ) + if ( coinaddr[0] != 0 ) { - if ( (cipherstr= jstr(reqjson,"cipher")) != 0 ) + LP_address(ptr,coinaddr); + if ( strcmp(coinaddr,ptr->smartaddr) == 0 && bits256_nonz(G.LP_privkey) != 0 ) { - cipherlen = (int32_t)strlen(cipherstr) >> 1; - if ( cipherlen <= sizeof(cipher) ) - { - decode_hex(cipher,cipherlen,cipherstr); - LP_queuesend(calc_crc32(0,&cipher[2],cipherlen-2),LP_mypubsock,base,rel,cipher,cipherlen); - } else retstr = clonestr("{\"error\":\"cipher too big\"}"); - } - else - { - memset(zero.bytes,0,sizeof(zero)); - LP_broadcast_message(LP_mypubsock,base!=0?base:jstr(argjson,"coin"),rel,zero,jprint(reqjson,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); } - retstr = clonestr("{\"result\":\"success\"}"); - } else retstr = clonestr("{\"error\":\"couldnt dereference sendmessage\"}"); - } - else if ( strcmp(method,"psock") == 0 ) - { - if ( myipaddr == 0 || myipaddr[0] == 0 || strcmp(myipaddr,"127.0.0.1") == 0 ) - { - if ( LP_mypeer != 0 ) - myipaddr = LP_mypeer->ipaddr; - else printf("LP_psock dont have actual ipaddr?\n"); } - if ( jint(argjson,"ispaired") != 0 ) - return(LP_psock(myipaddr,jint(argjson,"ispaired"))); - else return(clonestr("{\"error\":\"you are running an obsolete version, update\"}")); } - else if ( strcmp(method,"notify") == 0 ) - retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}"); + } + retstr = clonestr("{\"result\":\"success\"}"); + } + else if ( strcmp(method,"encrypted") == 0 ) + retstr = clonestr("{\"result\":\"success\"}"); + else // psock requests/response + { + if ( IAMLP != 0 ) + { + if ( strcmp(method,"psock") == 0 ) + { + if ( myipaddr == 0 || myipaddr[0] == 0 || strcmp(myipaddr,"127.0.0.1") == 0 ) + { + if ( LP_mypeer != 0 ) + myipaddr = LP_mypeer->ipaddr; + else printf("LP_psock dont have actual ipaddr?\n"); + } + if ( jint(argjson,"ispaired") != 0 ) + return(LP_psock(myipaddr,jint(argjson,"ispaired"))); + else return(clonestr("{\"error\":\"you are running an obsolete version, update\"}")); + } } else { diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index e630c13ea..3bea50380 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -21,34 +21,70 @@ #ifndef LP_INCLUDE_H #define LP_INCLUDE_H +#define LP_MAJOR_VERSION "0" +#define LP_MINOR_VERSION "1" +#define LP_BUILD_NUMBER "15256" +#define LP_BARTERDEX_VERSION 1 +#define LP_MAGICBITS 8 + +#ifdef FROM_JS +#include +#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" +// Edit src/core/sock.c and add here #include for INT_MAX support +// emmake make +// cp .libs/libnanomsg.a ~/SuperNET/OSlibs/js +#endif //#define LP_STRICTPEERS + +#define LP_MAXVINS 64 +#define LP_HTTP_TIMEOUT 3 // 1 is too small due to edge cases of time(NULL) +#define LP_AUTOTRADE_TIMEOUT 30 +#define LP_RESERVETIME (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_MIN_PEERS 8 +#define LP_MAX_PEERS 32 + +#define LP_MAXDESIRED_UTXOS (IAMLP != 0 ? 128 : 64) +#define LP_MINDESIRED_UTXOS (IAMLP != 0 ? 32 : 16) +#define LP_DUSTCOMBINE_THRESHOLD 1000000 + +// RTmetrics +#define LP_RTMETRICS_TOPGROUP 1.01 +#define LP_MAXPENDING_SWAPS 13 + #define LP_COMMAND_SENDSOCK NN_PUSH #define LP_COMMAND_RECVSOCK NN_PULL -#define LP_ENCRYPTED_MAXSIZE (4096 + 2 + crypto_box_NONCEBYTES + crypto_box_ZEROBYTES) +#define DPOW_MIN_ASSETCHAIN_SIGS 11 +#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 #define MIN_PSOCK_PORT 10000 -#define LP_MEMPOOL_TIMEINCR 10 #define LP_GETINFO_INCR 30 -#define LP_ORDERBOOK_DURATION 3600 +#define LP_ORDERBOOK_DURATION 180 -#define LP_HTTP_TIMEOUT 2 // 1 is too small due to edge cases of time(NULL) #define LP_MAXPEER_ERRORS 3 #define LP_MINPEER_GOOD 20 #define LP_PEERGOOD_ERRORDECAY 0.9 #define LP_SWAPSTEP_TIMEOUT 30 -#define LP_AUTOTRADE_TIMEOUT 60 #define LP_MIN_TXFEE 10000 -#define LP_MINVOL 10 -#define LP_MINCLIENTVOL 20 +#define LP_MINVOL 20 +#define LP_MINCLIENTVOL 100 #define LP_MINSIZE_TXFEEMULT 10 -#define LP_REQUIRED_TXFEE 0.95 +#define LP_REQUIRED_TXFEE 0.8 #define LP_DEXFEE(destsatoshis) ((destsatoshis) / INSTANTDEX_INSURANCEDIV) #define LP_DEPOSITSATOSHIS(satoshis) ((satoshis) + (satoshis >> 3)) @@ -61,21 +97,29 @@ #define JUMBLR_RMD160 "5177f8b427e5f47342a4b8ab5dac770815d4389e" #define TIERNOLAN_RMD160 "daedddd8dbe7a2439841ced40ba9c3d375f98146" #define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu" -#define INSTANTDEX_BTCD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf" +#define INSTANTDEX_KMD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf" //#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 +#define BASILISK_DEFAULT_MAXCONFIRMS 6 #define DEX_SLEEP 3 #define BASILISK_KEYSIZE ((int32_t)(2*sizeof(bits256)+sizeof(uint32_t)*2)) -extern char GLOBAL_DBDIR[],USERPASS[],USERPASS_WIFSTR[]; -extern int32_t IAMLP,USERPASS_COUNTER; +#define LP_IS_ZCASHPROTOCOL 1 +#define LP_IS_BITCOINCASH 2 + +#define SIGHASH_FORKID 0x40 +#define ZKSNARK_PROOF_SIZE 296 +#define ZCASH_SOLUTION_ELEMENTS 1344 + +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; }; @@ -92,13 +136,22 @@ struct iguana_msgtx uint8_t *serialized; }; +struct iguana_msgjoinsplit +{ + uint64_t vpub_old,vpub_new; + bits256 anchor,nullifiers[2],commitments[2],ephemeralkey; + bits256 randomseed,vmacs[2]; + uint8_t zkproof[ZKSNARK_PROOF_SIZE]; + uint8_t ciphertexts[2][601]; +}; + struct vin_signer { bits256 privkey; char coinaddr[64]; uint8_t siglen,sig[80],rmd160[20],pubkey[66]; }; 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]; }; @@ -113,9 +166,9 @@ 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]; @@ -124,20 +177,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; @@ -147,11 +199,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; - uint64_t alicesatoshis,bobsatoshis,bobinsurance,aliceinsurance,Atxfee,Btxfee; + int32_t bobconfirms,aliceconfirms,iambob,reclaimed,bobspent,alicespent,pad,aliceistrusted,bobistrusted,otheristrusted,otherstrust,alicemaxconfirms,bobmaxconfirms; + 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]; @@ -166,38 +218,69 @@ 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[40]; }; +#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_transaction +struct LP_outpoint { - UT_hash_handle hh; - bits256 txid; int32_t height,numvouts,numvins; uint32_t timestamp; - struct LP_outpoint outpoints[]; + bits256 spendtxid; + uint64_t value,interest; + int32_t spendvini,spendheight; + char coinaddr[64]; }; -struct LP_address +struct LP_transaction { UT_hash_handle hh; - int64_t balance; - char coinaddr[40]; + bits256 txid; + long fpos; + int32_t height,numvouts,numvins,len,SPV; + uint8_t *serialized; + struct LP_outpoint outpoints[]; }; struct iguana_info { UT_hash_handle hh; - portable_mutex_t txmutex; struct LP_transaction *transactions; struct LP_address *addresses; + portable_mutex_t txmutex,addrmutex; struct LP_transaction *transactions; struct LP_address *addresses; uint64_t txfee; - int32_t longestchain,firstrefht,firstscanht,lastscanht,bussock; uint16_t busport; - uint32_t counter,inactive,lastmempool,lastgetinfo; - uint8_t pubtype,p2shtype,isPoS,wiftype,wiftaddr,taddr,noimportprivkey_flag; - char symbol[16],smartaddr[64],userpass[1024],serverport[128]; + int32_t numutxos,longestchain,firstrefht,firstscanht,lastscanht,bussock,height; uint16_t busport; + uint32_t loadedcache,electrumlist,lastunspent,importedprivkey,lastpushtime,lastutxosync,addr_listunspent_requested,lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,obooktime; + uint8_t pubtype,p2shtype,isPoS,wiftype,wiftaddr,taddr,noimportprivkey_flag,userconfirms,isassetchain,maxconfirms; + char symbol[128],smartaddr[64],userpass[1024],serverport[128]; // portfolio - double price_kmd,force,perc,goal,goalperc,relvolume; + 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]; + uint8_t pubkey33[33],zcash; + int32_t privkeydepth; + bits256 cachedtxid; uint8_t *cachedtxiddata; int32_t cachedtxidlen; + bits256 cachedmerkle; int32_t cachedmerkleheight; }; -struct _LP_utxoinfo { bits256 txid; uint64_t value; int32_t vout; }; +struct _LP_utxoinfo { bits256 txid; uint64_t value; int32_t vout,height; }; struct LP_utxostats { uint32_t sessionid,lasttime,errors,swappending,spentflag,lastspentcheck,bestflag; }; @@ -205,7 +288,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 { @@ -214,19 +297,38 @@ struct LP_utxoinfo struct _LP_utxoinfo payment,deposit,fee; struct LP_utxostats T; struct LP_utxoswap S; - //struct LP_utxonetwork N; 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],spendscript[256],gui[16]; + char coin[65],coinaddr[64],gui[16];//spendscript[256]; +}; + +struct LP_address_utxo +{ + struct LP_address_utxo *next,*prev; + struct _LP_utxoinfo U; + int32_t SPV,spendheight; + //uint32_t timestamp; +}; + +struct LP_address +{ + UT_hash_handle hh; + struct LP_address_utxo *utxos; + bits256 pubkey; + int64_t balance,total; + uint32_t timestamp,n,unspenttime; + int32_t unspentheight; + char coinaddr[40]; + uint8_t pubsecp[33],pad; }; struct LP_peerinfo { UT_hash_handle hh; uint64_t ip_port; - uint32_t ipbits,errortime,errors,numpeers,numutxos,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]; }; @@ -235,19 +337,21 @@ struct LP_quoteinfo { struct basilisk_request R; bits256 srchash,desthash,txid,txid2,desttxid,feetxid,privkey; - uint64_t satoshis,txfee,destsatoshis,desttxfee; - uint32_t timestamp,quotetime; int32_t vout,vout2,destvout,feevout,pair; - char srccoin[16],coinaddr[64],destcoin[16],destaddr[64]; + uint64_t satoshis,txfee,destsatoshis,desttxfee,aliceid; + 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; @@ -255,11 +359,50 @@ struct basilisk_swap bits256 privkeys[INSTANTDEX_DECKSIZE]; struct basilisk_swapmessage *messages; int32_t nummessages,sentflag; char Bdeposit[64],Bpayment[64]; - uint64_t otherdeck[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2]; - uint8_t persistent_pubkey33[33],changermd160[20],pad[15],verifybuf[65536]; + 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; +}; + +#define LP_MAXPRICEINFOS 256 +struct LP_pubkeyinfo +{ + UT_hash_handle hh; + bits256 pubkey; + struct LP_pubkey_quote *quotes; + //float matrix[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS]; + //uint32_t timestamps[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS]; + uint32_t timestamp,numerrors,lasttime; + int32_t istrusted; + uint8_t rmd160[20],sig[65],pubsecp[33],siglen; +}; + +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[]; +}; + +int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *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); +void LP_swap_coinaddr(struct iguana_info *coin,char *coinaddr,uint64_t *valuep,uint8_t *data,int32_t datalen,int32_t vout); 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); @@ -273,17 +416,71 @@ int32_t LP_forward(void *ctx,char *myipaddr,int32_t pubsock,bits256 pubkey,char int32_t LP_ismine(struct LP_utxoinfo *utxo); int32_t LP_isavailable(struct LP_utxoinfo *utxo); struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port); +uint64_t LP_value_extract(cJSON *obj,int32_t addinterest); +int32_t LP_swap_getcoinaddr(char *symbol,char *coinaddr,bits256 txid,int32_t vout); char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen); -void LP_availableset(struct LP_utxoinfo *utxo); +int64_t LP_komodo_interest(bits256 txid,int64_t value); +void LP_availableset(bits256 txid,int32_t vout); int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2); int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsock,int32_t pullsock); +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); +//void LP_utxo_clientpublish(struct LP_utxoinfo *utxo); int32_t LP_coinbus(uint16_t coin_busport); +int32_t LP_nanomsg_recvs(void *ctx); +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(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); -uint64_t LP_txfeecalc(char *symbol,uint64_t txfee); - +int32_t LP_merkleproof(struct iguana_info *coin,char *coinaddr,struct electrum_info *ep,bits256 txid,int32_t height); +int32_t _LP_utxos_remove(bits256 txid,int32_t vout); +int32_t LP_utxos_remove(bits256 txid,int32_t vout); +struct LP_transaction *LP_transactionadd(struct iguana_info *coin,bits256 txid,int32_t height,int32_t numvouts,int32_t numvins); +void LP_tradebot_finished(uint32_t tradeid,uint32_t requestid,uint32_t quoteid); +uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee,int32_t txlen); +struct LP_address *_LP_address(struct iguana_info *coin,char *coinaddr); +struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr); +struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr); +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); +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); +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(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); +char *issue_LP_psock(char *destip,uint16_t destport,int32_t ispaired); +char *LP_unspents_filestr(char *symbol,char *addr); +cJSON *bitcoin_data2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash); +//int32_t LP_butxo_findeither(bits256 txid,int32_t vout); +cJSON *LP_listunspent(char *symbol,char *coinaddr); +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); + +void LP_listunspent_query(char *symbol,char *coinaddr); +int32_t bitcoin_priv2wif(uint8_t wiftaddr,char *wifstr,bits256 privkey,uint8_t addrtype); #endif diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index e3bf7308e..f1b89a40b 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -13,49 +13,130 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - // // LP_nativeDEX.c // marketmaker // -// new features: -// bittrex balancing -// detect port conflicts on enable -// stats -// PoW, JS -// verify actual pricing -// autoutxo, if < 10*txfee and > 10 utxo: combine smallest utxo into dexfee; autosplit if imbalanced - -// unduplicated bugs: -// swap cancel should cleanly cancel +// BCH signing: FORKID_BCC = 0, FORKID_BTG = 79, // Atomic number AU +// alice waiting for bestprice +// MNZ getcoin strangeness +// improve critical section detection when parallel trades +// reduce mem: dont redundant store pubkey utxo info +// previously, it used to show amount, kmd equiv, perc +// dPoW security -> 4: KMD notarized, 5: BTC notarized, after next notary elections +// bigendian architectures need to use little endian for sighash calcs #include + +long LP_cjson_allocated,LP_cjson_total,LP_cjson_count; + +struct LP_millistats +{ + double lastmilli,millisum,threshold; + uint32_t count; + char name[64]; +} LP_psockloop_stats,LP_reserved_msgs_stats,utxosQ_loop_stats,command_rpcloop_stats,queue_loop_stats,prices_loop_stats,LP_coinsloop_stats,LP_coinsloopBTC_stats,LP_coinsloopKMD_stats,LP_pubkeysloop_stats,LP_privkeysloop_stats,LP_swapsloop_stats,LP_gcloop_stats; +extern int32_t IAMLP; + +void LP_millistats_update(struct LP_millistats *mp) +{ + double elapsed,millis; + if ( mp == 0 ) + { + if ( IAMLP != 0 ) + { + mp = &LP_psockloop_stats, printf("%32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,OS_milliseconds() - mp->lastmilli,mp->threshold,mp->millisum/(mp->count > 0 ? mp->count: 1),mp->count); + } + mp = &LP_reserved_msgs_stats, printf("%32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,OS_milliseconds() - mp->lastmilli,mp->threshold,mp->millisum/(mp->count > 0 ? mp->count: 1),mp->count); + mp = &utxosQ_loop_stats, printf("%32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,OS_milliseconds() - mp->lastmilli,mp->threshold,mp->millisum/(mp->count > 0 ? mp->count: 1),mp->count); + mp = &command_rpcloop_stats, printf("%32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,OS_milliseconds() - mp->lastmilli,mp->threshold,mp->millisum/(mp->count > 0 ? mp->count: 1),mp->count); + mp = &queue_loop_stats, printf("%32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,OS_milliseconds() - mp->lastmilli,mp->threshold,mp->millisum/(mp->count > 0 ? mp->count: 1),mp->count); + mp = &prices_loop_stats, printf("%32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,OS_milliseconds() - mp->lastmilli,mp->threshold,mp->millisum/(mp->count > 0 ? mp->count: 1),mp->count); + mp = &LP_coinsloop_stats, printf("%32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,OS_milliseconds() - mp->lastmilli,mp->threshold,mp->millisum/(mp->count > 0 ? mp->count: 1),mp->count); + mp = &LP_coinsloopBTC_stats, printf("%32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,OS_milliseconds() - mp->lastmilli,mp->threshold,mp->millisum/(mp->count > 0 ? mp->count: 1),mp->count); + mp = &LP_coinsloopKMD_stats, printf("%32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,OS_milliseconds() - mp->lastmilli,mp->threshold,mp->millisum/(mp->count > 0 ? mp->count: 1),mp->count); + mp = &LP_pubkeysloop_stats, printf("%32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,OS_milliseconds() - mp->lastmilli,mp->threshold,mp->millisum/(mp->count > 0 ? mp->count: 1),mp->count); + mp = &LP_privkeysloop_stats, printf("%32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,OS_milliseconds() - mp->lastmilli,mp->threshold,mp->millisum/(mp->count > 0 ? mp->count: 1),mp->count); + mp = &LP_swapsloop_stats, printf("%32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,OS_milliseconds() - mp->lastmilli,mp->threshold,mp->millisum/(mp->count > 0 ? mp->count: 1),mp->count); + mp = &LP_gcloop_stats, printf("%32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,OS_milliseconds() - mp->lastmilli,mp->threshold,mp->millisum/(mp->count > 0 ? mp->count: 1),mp->count); + } + else + { + if ( mp->lastmilli == 0. ) + mp->lastmilli = OS_milliseconds(); + else + { + mp->count++; + millis = OS_milliseconds(); + elapsed = (millis - mp->lastmilli); + mp->millisum += elapsed; + if ( mp->threshold != 0. && elapsed > mp->threshold ) + { + //if ( IAMLP == 0 ) + printf("%32s elapsed %10.2f millis > threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,elapsed,mp->threshold,mp->millisum/mp->count,mp->count); + } + mp->lastmilli = millis; + } + } +} + #include "LP_include.h" -portable_mutex_t LP_peermutex,LP_UTXOmutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex,LP_forwardmutex,LP_pubkeymutex,LP_networkmutex,LP_psockmutex,LP_coinmutex,LP_messagemutex,LP_portfoliomutex; +portable_mutex_t LP_peermutex,LP_UTXOmutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex,LP_forwardmutex,LP_pubkeymutex,LP_networkmutex,LP_psockmutex,LP_coinmutex,LP_messagemutex,LP_portfoliomutex,LP_electrummutex,LP_butxomutex,LP_reservedmutex,LP_nanorecvsmutex,LP_tradebotsmutex,LP_gcmutex,LP_inusemutex,LP_cJSONmutex; int32_t LP_canbind; - -struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2]; +char *Broadcaststr,*Reserved_msgs[2][1000]; +int32_t num_Reserved_msgs[2],max_Reserved_msgs[2]; struct LP_peerinfo *LP_peerinfos,*LP_mypeer; struct LP_forwardinfo *LP_forwardinfos; struct iguana_info *LP_coins; -#include "LP_network.c" +struct LP_pubkeyinfo *LP_pubkeyinfos; +struct rpcrequest_info *LP_garbage_collector; +struct LP_address_utxo *LP_garbage_collector2; -char *activecoins[] = { "BTC", "KMD" }; -char GLOBAL_DBDIR[] = { "DB" }; -char USERPASS[65],USERPASS_WIFSTR[64],LP_myipaddr[64],LP_publicaddr[64],USERHOME[512] = { "/root" }; -char LP_gui[16] = { "cli" }; - -char *default_LPnodes[] = { "5.9.253.195", "5.9.253.196", "5.9.253.197", "5.9.253.198", "5.9.253.199", "5.9.253.200", "5.9.253.201", "5.9.253.202", "5.9.253.203", };//"5.9.253.204" }; // //uint32_t LP_deadman_switch; uint16_t LP_fixed_pairport,LP_publicport; +uint32_t LP_lastnonce,LP_counter,LP_swap_endcritical,LP_swap_critical; int32_t LP_mybussock = -1; int32_t LP_mypubsock = -1; int32_t LP_mypullsock = -1; -int32_t LP_pendingswaps,LP_showwif,USERPASS_COUNTER,IAMLP = 0; -uint32_t LP_sessionid; +int32_t LP_numfinished,LP_showwif,IAMLP = 0; double LP_profitratio = 1.; -bits256 LP_mypub25519,LP_mypriv25519; + +struct LP_privkey { bits256 privkey; uint8_t rmd160[20]; }; + +struct LP_globals +{ + struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2]; + bits256 LP_mypub25519,LP_privkey,LP_mypriv25519; + uint64_t LP_skipstatus[10000]; + uint8_t LP_myrmd160[20],LP_pubsecp[33]; + uint32_t LP_sessionid,counter; + int32_t LP_IAMLP,LP_pendingswaps,USERPASS_COUNTER,LP_numprivkeys,initializing,waiting,LP_numskips; + char USERPASS[65],USERPASS_WIFSTR[64],LP_myrmd160str[41],gui[16]; + struct LP_privkey LP_privkeys[100]; +} G; + +uint32_t LP_rand() +{ + uint32_t retval; + retval = rand(); + retval = (retval << 7) ^ (retval >> 17) ^ rand(); + retval = (retval << 13) ^ (retval >> 13) ^ rand(); + retval = (retval << 17) ^ (retval >> 7) ^ rand(); + return(retval); +} + +#include "LP_network.c" + +char *activecoins[] = { "BTC", "KMD" }; +char GLOBAL_DBDIR[] = { "DB" }; +char LP_myipaddr[64],LP_publicaddr[64],USERHOME[512] = { "/root" }; +char LP_gui[16] = { "cli" }; + +char *default_LPnodes[] = { "5.9.253.195", "5.9.253.196", "5.9.253.197", "5.9.253.198", "5.9.253.199", "5.9.253.200", "5.9.253.201", "5.9.253.202", "5.9.253.203", + //"24.54.206.138", "173.212.225.176", "136.243.45.140", "107.72.162.127", "72.50.16.86", "51.15.202.191", "173.228.198.88", + "51.15.203.171", "51.15.86.136", "51.15.94.249", "51.15.80.18", "51.15.91.40", "51.15.54.2", "51.15.86.31", "51.15.82.29", "51.15.89.155", +};//"5.9.253.204" }; // // stubs @@ -79,19 +160,26 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_ return(0); } +#include "LP_socket.c" #include "LP_secp.c" #include "LP_bitcoin.c" #include "LP_coins.c" #include "LP_rpc.c" +#include "LP_cache.c" +#include "LP_RTmetrics.c" +#include "LP_utxo.c" #include "LP_prices.c" #include "LP_scan.c" #include "LP_transaction.c" +#include "LP_stats.c" #include "LP_remember.c" #include "LP_swap.c" #include "LP_peers.c" #include "LP_utxos.c" #include "LP_forwarding.c" +#include "LP_signatures.c" #include "LP_ordermatch.c" +#include "LP_tradebots.c" #include "LP_portfolio.c" #include "LP_messages.c" #include "LP_commands.c" @@ -109,7 +197,7 @@ char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson //if ( pubsock >= 0 ) //strncmp("{\"error\":",retstr,strlen("{\"error\":")) != 0 && //LP_send(pubsock,retstr,(int32_t)strlen(retstr)+1,0); } - } + } //else printf("finished tradecommand (%s)\n",jprint(argjson,0)); return(retstr); } @@ -122,14 +210,14 @@ char *LP_decrypt(uint8_t *ptr,int32_t *recvlenp) cipherlen = recvlen - (2 + crypto_box_NONCEBYTES); if ( cipherlen > 0 && cipherlen <= sizeof(decoded) ) { - if ( (jsonstr= (char *)_SuperNET_decipher(nonce,cipher,decoded,cipherlen,GENESIS_PUBKEY,LP_mypriv25519)) != 0 ) + if ( (jsonstr= (char *)_SuperNET_decipher(nonce,cipher,decoded,cipherlen,GENESIS_PUBKEY,G.LP_mypriv25519)) != 0 ) { recvlen = (cipherlen - crypto_box_ZEROBYTES); if ( strlen(jsonstr)+1 != recvlen ) { printf("unexpected len %d vs recvlen.%d\n",(int32_t)strlen(jsonstr)+1,recvlen); jsonstr = 0; - } else printf("decrypted (%s)\n",jsonstr); + } //else printf("decrypted (%s)\n",jsonstr); } } else printf("cipher.%d too big for %d\n",cipherlen,(int32_t)sizeof(decoded)); *recvlenp = recvlen; @@ -140,16 +228,17 @@ char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock, { static uint32_t dup,uniq; int32_t i,len,cipherlen,datalen=0,duplicate=0,encrypted=0; char *method,*method2,*tmp,*cipherstr,*retstr=0,*jsonstr=0; cJSON *argjson; uint32_t crc32; + //double millis = OS_milliseconds(); crc32 = calc_crc32(0,&ptr[2],recvlen-2); if ( (crc32 & 0xff) == ptr[0] && ((crc32>>8) & 0xff) == ptr[1] ) encrypted = 1; - portable_mutex_lock(&LP_commandmutex); i = LP_crc32find(&duplicate,-1,crc32); if ( duplicate != 0 ) dup++; else uniq++; - if ( (rand() % 1000) == 0 ) - printf("%s dup.%d (%u / %u) %.1f%% encrypted.%d recv.%u [%02x %02x] vs %02x %02x U.%d\n",typestr,duplicate,dup,dup+uniq,(double)100*dup/(dup+uniq),encrypted,crc32,ptr[0],ptr[1],crc32&0xff,(crc32>>8)&0xff,LP_mypeer != 0 ? LP_mypeer->numutxos : -1); + portable_mutex_lock(&LP_commandmutex); + if ( (LP_rand() % 10000) == 0 ) + printf("%s dup.%d (%u / %u) %.1f%% encrypted.%d recv.%u [%02x %02x] vs %02x %02x\n",typestr,duplicate,dup,dup+uniq,(double)100*dup/(dup+uniq),encrypted,crc32,ptr[0],ptr[1],crc32&0xff,(crc32>>8)&0xff); if ( duplicate == 0 ) { if ( i >= 0 ) @@ -193,321 +282,444 @@ char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock, } else { - printf("packet not for this node %u\n",crc32); + //printf("packet not for this node %u\n",crc32); } } else printf("error (%s) method is %s\n",jsonstr,method); } if ( jsonstr != 0 && argjson != 0 ) { len = (int32_t)strlen(jsonstr) + 1; - if ( (retstr= LP_command_process(ctx,myipaddr,pubsock,argjson,&((uint8_t *)ptr)[len],recvlen - len)) != 0 ) + if ( (method= jstr(argjson,"method")) != 0 && strcmp(method,"broadcast") == 0 ) + { + bits256 zero; cJSON *reqjson; char *cipherstr; int32_t cipherlen; uint8_t cipher[LP_ENCRYPTED_MAXSIZE]; + if ( (reqjson= LP_dereference(argjson,"broadcast")) != 0 ) + { + Broadcaststr = jprint(reqjson,0); + if ( (cipherstr= jstr(reqjson,"cipher")) != 0 ) + { + cipherlen = (int32_t)strlen(cipherstr) >> 1; + if ( cipherlen <= sizeof(cipher) ) + { + decode_hex(cipher,cipherlen,cipherstr); + LP_queuesend(calc_crc32(0,&cipher[2],cipherlen-2),LP_mypubsock,"","",cipher,cipherlen); + } else retstr = clonestr("{\"error\":\"cipher too big\"}"); + } + else + { + memset(zero.bytes,0,sizeof(zero)); + /*if ( (method= jstr(reqjson,"method")) != 0 && (strcmp(method,"request") == 0 || strcmp(method,"requested") == 0 || strcmp(method,"connect") == 0 || strcmp(method,"connected") == 0) ) + printf("broadcast.(%s)\n",Broadcaststr);*/ + LP_reserved_msg(0,"","",zero,jprint(reqjson,0)); + } + retstr = clonestr("{\"result\":\"success\"}"); + free_json(reqjson); + } else retstr = clonestr("{\"error\":\"couldnt dereference sendmessage\"}"); + } + else { + if ( (retstr= LP_command_process(ctx,myipaddr,pubsock,argjson,&((uint8_t *)ptr)[len],recvlen - len)) != 0 ) + { + } } - free_json(argjson); } + if ( argjson != 0 ) + free_json(argjson); } } //else printf("DUPLICATE.(%s)\n",(char *)ptr); portable_mutex_unlock(&LP_commandmutex); if ( jsonstr != 0 && (void *)jsonstr != (void *)ptr && encrypted == 0 ) free(jsonstr); - if ( ptr != 0 ) - nn_freemsg(ptr), ptr = 0; return(retstr); } -void LP_utxo_spentcheck(int32_t pubsock,struct LP_utxoinfo *utxo) +int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int32_t sock,char *remoteaddr,int32_t maxdepth) { - struct _LP_utxoinfo u; struct iguana_info *coin; char str[65]; uint32_t now = (uint32_t)time(NULL); - if ( IAMLP != 0 && (coin= LP_coinfind(utxo->coin)) != 0 && coin->inactive != 0 ) - return; - //printf("%s lag.%d\n",bits256_str(str,utxo->txid),now-utxo->lastspentcheck); - if ( utxo->T.spentflag == 0 && now > utxo->T.lastspentcheck+60 ) - { - u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; - utxo->T.lastspentcheck = now; - if ( LP_txvalue(0,utxo->coin,utxo->payment.txid,utxo->payment.vout) == 0 ) - { - printf("txid.%s %s/v%d %.8f has been spent\n",utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout,dstr(utxo->payment.value)); - LP_spentnotify(utxo,0); - } - else if ( LP_txvalue(0,utxo->coin,u.txid,u.vout) == 0 ) - { - printf("txid2.%s %s/v%d %.8f has been spent\n",utxo->coin,bits256_str(str,u.txid),u.vout,dstr(u.value)); - LP_spentnotify(utxo,1); - } - } -} - -void LP_myutxo_updates(void *ctx,int32_t pubsock,char *passphrase) -{ - //LP_utxopurge(0); not good to disrupt existing pointers - LP_privkey_updates(ctx,pubsock,passphrase,0); -} - -int32_t LP_peer_utxosquery(struct LP_peerinfo *mypeer,uint16_t myport,int32_t pubsock,struct LP_peerinfo *peer,uint32_t now,int32_t interval,int32_t maxentries) -{ - int32_t lastn,n = -1; - if ( peer->lastutxos < now-interval ) - { - //lastn = peer->numutxos - mypeer->numutxos + LP_PROPAGATION_SLACK; - //if ( lastn < LP_PROPAGATION_SLACK * 2 ) - lastn = LP_PROPAGATION_SLACK * 2; - if ( mypeer == 0 || strcmp(peer->ipaddr,mypeer->ipaddr) != 0 ) - { - peer->lastutxos = now; - //printf("query utxos from %s\n",peer->ipaddr); - n = LP_utxosquery(mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,maxentries); - } - } //else printf("LP_peer_utxosquery skip.(%s) %u\n",peer->ipaddr,peer->lastutxos); - return(n); -} - -int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int32_t sock) -{ - int32_t recvlen=1,nonz = 0; void *ptr; char *retstr; struct nn_pollfd pfd; + int32_t recvlen=1,nonz = 0; cJSON *argjson; void *ptr; char methodstr[64],*retstr,*str; struct nn_pollfd pfd; if ( sock >= 0 ) { - while ( nonz < 1000 && recvlen > 0 ) + while ( nonz < maxdepth && recvlen > 0 ) { + nonz++; memset(&pfd,0,sizeof(pfd)); pfd.fd = sock; pfd.events = NN_POLLIN; if ( nn_poll(&pfd,1,1) != 1 ) break; + ptr = 0; + //buf = malloc(1000000); + //if ( (recvlen= nn_recv(sock,buf,1000000,0)) > 0 ) if ( (recvlen= nn_recv(sock,&ptr,NN_MSG,0)) > 0 ) { - nonz++; - if ( (retstr= LP_process_message(ctx,typestr,myipaddr,pubsock,ptr,recvlen,sock)) != 0 ) - free(retstr); + //ptr = buf; + methodstr[0] = 0; + //printf("%s.(%s)\n",typestr,(char *)ptr); + if ( 0 ) + { + cJSON *recvjson; char *mstr;//,*cstr; + if ( (recvjson= cJSON_Parse((char *)ptr)) != 0 ) + { + if ( (mstr= jstr(recvjson,"method")) != 0 )//&& strcmp(mstr,"uitem") == 0 && (cstr= jstr(recvjson,"coin")) != 0 && strcmp(cstr,"REVS") == 0 ) + { + //printf("%s RECV.(%s)\n",typestr,(char *)ptr); + } + safecopy(methodstr,jstr(recvjson,"method"),sizeof(methodstr)); + free_json(recvjson); + } + } + int32_t validreq = 0; + if ( strlen((char *)ptr)+sizeof(bits256) <= recvlen ) + { + if ( LP_magic_check(ptr,recvlen,remoteaddr) <= 0 ) + { + //printf("magic check error\n"); + } else validreq = 1; + recvlen -= sizeof(bits256); + } + if ( validreq != 0 ) + { + if ( (retstr= LP_process_message(ctx,typestr,myipaddr,pubsock,ptr,recvlen,sock)) != 0 ) + free(retstr); + if ( Broadcaststr != 0 ) + { + //printf("self broadcast.(%s)\n",Broadcaststr); + str = Broadcaststr; + Broadcaststr = 0; + if ( (argjson= cJSON_Parse(str)) != 0 ) + { + portable_mutex_lock(&LP_commandmutex); + if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,0,0) <= 0 ) + { + if ( (retstr= stats_JSON(ctx,myipaddr,pubsock,argjson,remoteaddr,0)) != 0 ) + free(retstr); + } + portable_mutex_unlock(&LP_commandmutex); + free_json(argjson); + } + free(str); + } + } + } + if ( ptr != 0 ) + { + nn_freemsg(ptr), ptr = 0; + //free(buf); } } } return(nonz); } -void command_rpcloop(void *myipaddr) +int32_t LP_nanomsg_recvs(void *ctx) { - int32_t nonz = 0; char *origipaddr; struct LP_peerinfo *peer,*tmp; void *ctx; //struct iguana_info *coin,*ctmp; - ctx = bitcoin_ctx(); - if ( (origipaddr= myipaddr) == 0 ) + int32_t nonz = 0; char *origipaddr; struct LP_peerinfo *peer,*tmp; + if ( (origipaddr= LP_myipaddr) == 0 ) origipaddr = "127.0.0.1"; - while ( 1 ) + //portable_mutex_lock(&LP_nanorecvsmutex); + HASH_ITER(hh,LP_peerinfos,peer,tmp) { - nonz = 0; - HASH_ITER(hh,LP_peerinfos,peer,tmp) + if ( peer->errors >= LP_MAXPEER_ERRORS ) { - if ( peer->errors >= LP_MAXPEER_ERRORS ) + if ( (LP_rand() % 10000) == 0 ) + peer->errors--; + else { - if ( (rand() % 10000) == 0 ) - peer->errors--; - else continue; + //printf("skip %s\n",peer->ipaddr); + continue; } - //printf("check %s pubsock.%d\n",peer->ipaddr,peer->subsock); - nonz += LP_sock_check("PULL",ctx,origipaddr,LP_mypubsock,peer->subsock); } - /*HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht - { - if ( coin->inactive != 0 ) - continue; - if ( coin->bussock >= 0 ) - nonz += LP_sock_check(coin->symbol,ctx,origipaddr,-1,coin->bussock,LP_profitratio - 1.); - }*/ - if ( LP_mypullsock >= 0 ) - nonz += LP_sock_check("SUB",ctx,origipaddr,-1,LP_mypullsock); + //printf("check %s pubsock.%d\n",peer->ipaddr,peer->subsock); + nonz += LP_sock_check("PULL",ctx,origipaddr,LP_mypubsock,peer->subsock,peer->ipaddr,1); + } + /*HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht + { + if ( coin->inactive != 0 ) + continue; + if ( coin->bussock >= 0 ) + nonz += LP_sock_check(coin->symbol,ctx,origipaddr,-1,coin->bussock,LP_profitratio - 1.); + }*/ + if ( LP_mypullsock >= 0 ) + { + nonz += LP_sock_check("SUB",ctx,origipaddr,-1,LP_mypullsock,"127.0.0.1",1); + } + //portable_mutex_unlock(&LP_nanorecvsmutex); + return(nonz); +} + +void command_rpcloop(void *myipaddr) +{ + int32_t nonz = 0; void *ctx; + ctx = bitcoin_ctx(); + strcpy(command_rpcloop_stats.name,"command_rpcloop"); + command_rpcloop_stats.threshold = 1000.; + while ( 1 ) + { + LP_millistats_update(&command_rpcloop_stats); + nonz = LP_nanomsg_recvs(ctx); //if ( LP_mybussock >= 0 ) // nonz += LP_sock_check("BUS",ctx,origipaddr,-1,LP_mybussock); if ( nonz == 0 ) - usleep(10000); + { + if ( IAMLP != 0 ) + usleep(10000); + else usleep(50000); + } + else if ( IAMLP == 0 ) + usleep(1000); } } -int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int32_t pubsock,char *pushaddr,uint16_t myport,char *passphrase) +void utxosQ_loop(void *myipaddr) { - static uint32_t counter,numpeers,lastresync; //lastforward - struct LP_utxoinfo *utxo,*utmp; cJSON *retjson; struct iguana_info *coin,*ctmp; char *retstr,*origipaddr; struct LP_peerinfo *peer,*tmp,*mostpeer; uint32_t id,now; int32_t mostutxos,nonz = 0,n=0,num,lastn=-1; - now = (uint32_t)time(NULL); - if ( (origipaddr= myipaddr) == 0 ) - origipaddr = "127.0.0.1"; - if ( mypeer == 0 ) - myipaddr = "127.0.0.1"; - //if ( LP_canbind == 0 ) printf("counter.%d canbind.%d peers\n",counter,LP_canbind); - numpeers = LP_numpeers(); - mostutxos = 0; - mostpeer = 0; - HASH_ITER(hh,LP_peerinfos,peer,tmp) + strcpy(utxosQ_loop_stats.name,"utxosQ_loop"); + utxosQ_loop_stats.threshold = 5000.; + while ( 1 ) { - if ( peer->errors >= LP_MAXPEER_ERRORS ) + LP_millistats_update(&utxosQ_loop_stats); + if ( LP_utxosQ_process() == 0 ) + usleep(50000); + } +} + +void LP_coinsloop(void *_coins) +{ + struct LP_address *ap=0,*atmp; struct LP_transaction *tx; cJSON *retjson; struct LP_address_utxo *up,*tmp; struct iguana_info *coin,*ctmp; char str[65]; struct electrum_info *ep,*backupep=0; bits256 zero; int32_t oldht,j,nonz; char *coins = _coins; + if ( strcmp("BTC",coins) == 0 ) + { + strcpy(LP_coinsloopBTC_stats.name,"BTC coin loop"); + LP_coinsloopBTC_stats.threshold = 20000.; + } + else if ( strcmp("KMD",coins) == 0 ) + { + strcpy(LP_coinsloopKMD_stats.name,"KMD coin loop"); + LP_coinsloopKMD_stats.threshold = 10000.; + } + else + { + strcpy(LP_coinsloop_stats.name,"other coins loop"); + LP_coinsloop_stats.threshold = 5000.; + } + while ( 1 ) + { + if ( strcmp("BTC",coins) == 0 ) + LP_millistats_update(&LP_coinsloopBTC_stats); + else if ( strcmp("KMD",coins) == 0 ) + LP_millistats_update(&LP_coinsloopKMD_stats); + else LP_millistats_update(&LP_coinsloop_stats); + nonz = 0; + HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht { - if ( (rand() % 10000) == 0 ) + if ( coins != 0 ) { - peer->errors--; - peer->diduquery = 0; + if ( coins[0] != 0 ) + { + if ( strcmp(coins,coin->symbol) != 0 ) + continue; + } + else // avoid hardcode special case LP_coinsloop + { + if ( strcmp("BTC",coin->symbol) == 0 || strcmp("KMD",coin->symbol) == 0 ) + continue; + } } - if ( IAMLP == 0 ) + if ( coin->smartaddr[0] == 0 ) + printf("%s has no smartaddress??\n",coin->symbol); + memset(&zero,0,sizeof(zero)); + if ( coin->inactive != 0 ) continue; - } - if ( now > peer->lastpeers+60 && peer->numpeers > 0 && (peer->numpeers != numpeers || (rand() % 10000) == 0) ) - { - //if ( IAMLP != 0 ) - // printf("numpeers.%d updatepeer.%s lag.%d\n",numpeers,peer->ipaddr,now-peer->lastpeers); - peer->lastpeers = now; - //if ( IAMLP != 0 && peer->numpeers != numpeers ) - // printf("%s num.%d vs %d\n",peer->ipaddr,peer->numpeers,numpeers); - if ( strcmp(peer->ipaddr,myipaddr) != 0 ) - LP_peersquery(mypeer,pubsock,peer->ipaddr,peer->port,myipaddr,myport); - if ( IAMLP != 0 && LP_mypeer != 0 && strcmp(peer->ipaddr,myipaddr) != 0 ) + if ( coin->longestchain == 1 ) // special init value + coin->longestchain = LP_getheight(coin); + if ( (ep= coin->electrum) != 0 ) { - if ( (retstr= issue_LP_numutxos(peer->ipaddr,peer->port,LP_mypeer->ipaddr,LP_mypeer->port,LP_mypeer->numpeers,LP_mypeer->numutxos)) != 0 ) + if ( (backupep= ep->prev) == 0 ) + backupep = ep; + if ( (ap= LP_addressfind(coin,coin->smartaddr)) != 0 ) { - //printf("%d <- (%s)\n",peer->numutxos,retstr); - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( (num= jint(retjson,"numutxos")) > peer->numutxos ) - peer->numutxos = num; - if ( (num= jint(retjson,"numpeers")) > peer->numpeers ) - peer->numpeers = num; - if ( (id= juint(retjson,"session")) != 0 ) - peer->sessionid = id; + if ( (retjson= electrum_address_listunspent(coin->symbol,ep,&retjson,ap->coinaddr,1)) != 0 ) free_json(retjson); + } + HASH_ITER(hh,coin->addresses,ap,atmp) + { + //printf("call unspent %s\n",ap->coinaddr); + if ( (retjson= electrum_address_listunspent(coin->symbol,ep,&retjson,ap->coinaddr,1)) != 0 ) + free_json(retjson); + } + if ( (ap= LP_addressfind(coin,coin->smartaddr)) != 0 ) + { + DL_FOREACH_SAFE(ap->utxos,up,tmp) + { + if ( up->U.height > 0 && up->spendheight < 0 ) + { + if ( up->SPV == 0 ) + { + nonz++; + up->SPV = LP_merkleproof(coin,coin->smartaddr,backupep,up->U.txid,up->U.height); + if ( up->SPV > 0 ) + { + if ( (tx= LP_transactionfind(coin,up->U.txid)) != 0 && tx->SPV == 0 ) + { + tx->SPV = up->SPV; + //printf("%s %s: SPV.%d\n",coin->symbol,bits256_str(str,up->U.txid),up->SPV); + } + } + } + else if ( up->SPV == -1 ) + { + nonz++; + printf("SPV failure for %s %s\n",coin->symbol,bits256_str(str,up->U.txid)); + oldht = up->U.height; + LP_txheight_check(coin,ap->coinaddr,up); + if ( oldht != up->U.height ) + up->SPV = LP_merkleproof(coin,coin->smartaddr,backupep,up->U.txid,up->U.height); + if ( up->SPV <= 0 ) + up->SPV = -2; + else printf("%s %s: corrected SPV.%d\n",coin->symbol,bits256_str(str,up->U.txid),up->SPV); + } + } + } + } + while ( ep != 0 ) + { + if ( time(NULL) > ep->keepalive+LP_ELECTRUM_KEEPALIVE ) + { + //printf("%s electrum.%p needs a keepalive: lag.%d\n",ep->symbol,ep,(int32_t)(time(NULL) - ep->keepalive)); + if ( (retjson= electrum_address_listunspent(coin->symbol,ep,&retjson,coin->smartaddr,1)) != 0 ) + free_json(retjson); } - free(retstr); - retstr = 0; + ep = ep->prev; } + continue; } - } - if ( peer->diduquery == 0 ) - { - if ( lastn != n || n < 20 ) + if ( coin->firstrefht == 0 ) + continue; + else if ( coin->firstscanht == 0 ) + coin->lastscanht = coin->firstscanht = coin->firstrefht; + else if ( coin->firstrefht < coin->firstscanht ) { - lastn = n; - n = LP_peer_utxosquery(mypeer,myport,pubsock,peer,now,60,100); + printf("detected %s firstrefht.%d < firstscanht.%d\n",coin->symbol,coin->firstrefht,coin->firstscanht); + coin->lastscanht = coin->firstscanht = coin->firstrefht; } - LP_peer_pricesquery(peer->ipaddr,peer->port); - peer->diduquery = now; - } - if ( peer->numutxos > mostutxos ) - { - mostutxos = peer->numutxos; - mostpeer = peer; - } - } - //printf("numutxos vs mine.%d\n",LP_mypeer != 0 ? LP_mypeer->numutxos : -1); - if ( LP_mypeer != 0 && LP_mypeer->numutxos < mostutxos && mostpeer != 0 && time(NULL) > lastresync+180 ) - { - printf("myutxos.%d most.%d %s\n",LP_mypeer->numutxos,mostutxos,mostpeer->ipaddr); - LP_peer_utxosquery(LP_mypeer,myport,pubsock,mostpeer,now,60,(mostutxos-LP_mypeer->numutxos) * 2); - lastresync = (uint32_t)time(NULL); - //LP_peer_pricesquery(mostpeer->ipaddr,mostpeer->port); - } - if ( (counter % 6000) == 10 ) - { - LP_myutxo_updates(ctx,pubsock,passphrase); - HASH_ITER(hh,LP_utxoinfos[0],utxo,utmp) - { - LP_utxo_spentcheck(pubsock,utxo); - } - HASH_ITER(hh,LP_utxoinfos[1],utxo,utmp) - { - LP_utxo_spentcheck(pubsock,utxo); - if ( LP_isunspent(utxo) > 0 && utxo->T.lasttime == 0 && LP_ismine(utxo) > 0 ) + if ( coin->lastscanht == coin->longestchain+1 ) { - char str[65]; printf("publish mybob %s\n",bits256_str(str,utxo->payment.txid)); - LP_utxo_clientpublish(utxo); + //printf("%s lastscanht.%d is longest.%d + 1\n",coin->symbol,coin->lastscanht,coin->longestchain); + continue; + } + else if ( coin->lastscanht > coin->longestchain+1 ) + { + printf("detected chain rewind lastscanht.%d vs longestchain.%d, first.%d ref.%d\n",coin->lastscanht,coin->longestchain,coin->firstscanht,coin->firstrefht); + LP_undospends(coin,coin->longestchain-1); + //LP_mempoolscan(coin->symbol,zero); + coin->lastscanht = coin->longestchain - 1; + if ( coin->firstscanht < coin->lastscanht ) + coin->lastscanht = coin->firstscanht; + continue; + } + nonz++; + if ( 0 && coin->lastscanht < coin->longestchain-3 ) + printf("[%s]: %s ref.%d scan.%d to %d, longest.%d\n",coins,coin->symbol,coin->firstrefht,coin->firstscanht,coin->lastscanht,coin->longestchain); + for (j=0; j<100; j++) + { + if ( LP_blockinit(coin,coin->lastscanht) < 0 ) + { + static uint32_t counter; + if ( counter++ < 3 ) + printf("blockinit.%s %d error\n",coin->symbol,coin->lastscanht); + break; + } + coin->lastscanht++; + if ( coin->lastscanht == coin->longestchain+1 ) + break; } } + if ( coins == 0 ) + return; + if ( nonz == 0 ) + usleep(100000); } +} + +int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int32_t pubsock,char *pushaddr,uint16_t myport) +{ + static uint32_t counter; + struct iguana_info *coin,*ctmp; char *origipaddr; uint32_t now; int32_t height,nonz = 0; + if ( (origipaddr= myipaddr) == 0 ) + origipaddr = "127.0.0.1"; + if ( mypeer == 0 ) + myipaddr = "127.0.0.1"; HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht { - cJSON *obj; int32_t height; bits256 zero; - //printf("%s ref.%d scan.%d to %d, longest.%d\n",coin->symbol,coin->firstrefht,coin->firstscanht,coin->lastscanht,coin->longestchain); - if ( coin->inactive != 0 ) - continue; - memset(zero.bytes,0,sizeof(zero)); - if ( time(NULL) > coin->lastgetinfo+LP_GETINFO_INCR ) + now = (uint32_t)time(NULL); + if ( (coin->addr_listunspent_requested != 0 && now > coin->lastpushtime+LP_ORDERBOOK_DURATION*.5) || now > coin->lastpushtime+LP_ORDERBOOK_DURATION*5 ) { - if ( (obj= LP_getinfo(coin->symbol)) != 0 ) - { - if ( (height= jint(obj,"blocks")) > coin->longestchain ) - { - coin->longestchain = height; - if ( coin->firstrefht != 0 ) - printf(">>>>>>>>>> set %s longestchain %d (ref.%d [%d, %d])\n",coin->symbol,height,coin->firstrefht,coin->firstscanht,coin->lastscanht); - } else LP_mempoolscan(coin->symbol,zero); - free_json(obj); - } else printf("error getting info.%s\n",coin->symbol); - coin->lastgetinfo = (uint32_t)time(NULL); + //printf("PUSH addr_listunspent_requested %u\n",coin->addr_listunspent_requested); + coin->lastpushtime = (uint32_t)now; + LP_smartutxos_push(coin); + coin->addr_listunspent_requested = 0; } - if ( coin->firstrefht == 0 ) - continue; - else if ( coin->firstscanht == 0 ) - coin->lastscanht = coin->firstscanht = coin->firstrefht; - else if ( coin->firstrefht < coin->firstscanht ) + if ( coin->electrum == 0 && coin->inactive == 0 && now > coin->lastgetinfo+LP_GETINFO_INCR ) { - printf("detected %s firstrefht.%d < firstscanht.%d\n",coin->symbol,coin->firstrefht,coin->firstscanht); - coin->lastscanht = coin->firstscanht = coin->firstrefht; - } - if ( coin->lastscanht == coin->longestchain+1 ) - continue; - else if ( coin->lastscanht > coin->longestchain+1 ) - { - printf("detected chain rewind lastscanht.%d vs longestchain.%d, first.%d ref.%d\n",coin->lastscanht,coin->longestchain,coin->firstscanht,coin->firstrefht); - LP_undospends(coin,coin->longestchain-1); - LP_mempoolscan(coin->symbol,zero); - coin->lastscanht = coin->longestchain - 1; - if ( coin->firstscanht < coin->lastscanht ) - coin->lastscanht = coin->firstscanht; - continue; - } - //printf("%s ref.%d scan.%d to %d, longest.%d\n",coin->symbol,coin->firstrefht,coin->firstscanht,coin->lastscanht,coin->longestchain); - if ( LP_blockinit(coin,coin->lastscanht) < 0 ) - { - printf("blockinit.%s %d error\n",coin->symbol,coin->lastscanht); - continue; - } - coin->lastscanht++; - break; - } - if ( (counter % 6000) == 60 ) - { - if ( (retstr= basilisk_swapentry(0,0)) != 0 ) - { - //printf("SWAPS.(%s)\n",retstr); - free(retstr); + nonz++; + if ( (height= LP_getheight(coin)) > coin->longestchain ) + { + coin->longestchain = height; + if ( 0 && coin->firstrefht != 0 ) + printf(">>>>>>>>>> set %s longestchain %d (ref.%d [%d, %d])\n",coin->symbol,height,coin->firstrefht,coin->firstscanht,coin->lastscanht); + } //else LP_mempoolscan(coin->symbol,zero); + coin->lastgetinfo = (uint32_t)now; } } counter++; return(nonz); } -void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins,char *passphrase) +void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins) { - int32_t i,n; cJSON *item; + int32_t i,n; cJSON *item; char *symbol; struct iguana_info *coin; for (i=0; iinactive = (uint32_t)time(NULL); + else LP_unspents_load(coin->symbol,coin->smartaddr); + if ( coin->txfee == 0 && strcmp(coin->symbol,"BTC") != 0 ) + coin->txfee = LP_MIN_TXFEE; + } } if ( (n= cJSON_GetArraySize(coins)) > 0 ) { for (i=0; iinactive = (uint32_t)time(NULL); + else LP_unspents_load(coin->symbol,coin->smartaddr); + if ( coin->txfee == 0 && strcmp(coin->symbol,"BTC") != 0 ) + coin->txfee = LP_MIN_TXFEE; + } + } } } - fprintf(stderr,"privkey updates\n"); - LP_privkey_updates(ctx,pubsock,passphrase,1); + printf("privkey updates\n"); } -void LP_initpeers(int32_t pubsock,struct LP_peerinfo *mypeer,char *myipaddr,uint16_t myport,char *seednode) +void LP_initpeers(int32_t pubsock,struct LP_peerinfo *mypeer,char *myipaddr,uint16_t myport,char *seednode,uint16_t pushport,uint16_t subport) { int32_t i,j; uint32_t r; if ( IAMLP != 0 ) { - LP_mypeer = mypeer = LP_addpeer(mypeer,pubsock,myipaddr,myport,0,0,0,0,LP_sessionid); + LP_mypeer = mypeer = LP_addpeer(mypeer,pubsock,myipaddr,myport,pushport,subport,1,G.LP_sessionid); if ( myipaddr == 0 || mypeer == 0 ) { printf("couldnt get myipaddr or null mypeer.%p\n",mypeer); @@ -517,11 +729,9 @@ void LP_initpeers(int32_t pubsock,struct LP_peerinfo *mypeer,char *myipaddr,uint { for (i=0; i 25 ) - // continue; - LP_peersquery(mypeer,pubsock,default_LPnodes[i],myport,mypeer->ipaddr,myport); + LP_addpeer(mypeer,pubsock,default_LPnodes[i],myport,pushport,subport,0,G.LP_sessionid); } - } else LP_peersquery(mypeer,pubsock,seednode,myport,mypeer->ipaddr,myport); + } else LP_addpeer(mypeer,pubsock,seednode,myport,pushport,subport,0,G.LP_sessionid); } else { @@ -532,19 +742,160 @@ void LP_initpeers(int32_t pubsock,struct LP_peerinfo *mypeer,char *myipaddr,uint } if ( seednode == 0 || seednode[0] == 0 ) { + //LP_addpeer(mypeer,pubsock,"51.15.86.136",myport,pushport,subport,0,G.LP_sessionid); OS_randombytes((void *)&r,sizeof(r)); + //r = 0; for (j=0; jelectrum != 0 && time(NULL) > coin->lastunspent+30 ) + { + //printf("call electrum listunspent.%s\n",coin->symbol); + if ( (retjson= electrum_address_listunspent(coin->symbol,coin->electrum,&retjson,coin->smartaddr,2)) != 0 ) + free_json(retjson); + coin->lastunspent = (uint32_t)time(NULL); + } + } + if ( time(NULL) > lasttime+LP_ORDERBOOK_DURATION*0.5 ) + { +//printf("LP_pubkeysloop %u\n",(uint32_t)time(NULL)); + LP_notify_pubkeys(ctx,LP_mypubsock); + lasttime = (uint32_t)time(NULL); + } + sleep(3); + } +} + +void LP_privkeysloop(void *ctx) +{ + strcpy(LP_privkeysloop_stats.name,"LP_privkeysloop"); + LP_privkeysloop_stats.threshold = (LP_ORDERBOOK_DURATION * .8 * 1000) + 10000; + sleep(20); + while ( 1 ) + { + LP_millistats_update(&LP_privkeysloop_stats); + LP_counter += 1000; +//printf("LP_privkeysloop %u\n",LP_counter); + LP_privkey_updates(ctx,LP_mypubsock,0); + sleep(LP_ORDERBOOK_DURATION * .777); + } +} + +void LP_swapsloop(void *ignore) +{ + char *retstr; + strcpy(LP_swapsloop_stats.name,"LP_swapsloop"); + LP_swapsloop_stats.threshold = 605000.; + sleep(50); + while ( 1 ) + { + LP_millistats_update(&LP_swapsloop_stats); + LP_counter += 10000; +//printf("LP_swapsloop %u\n",LP_counter); + if ( (retstr= basilisk_swapentry(0,0)) != 0 ) + free(retstr); + sleep(600); + } +} + +void LP_reserved_msgs(void *ignore) +{ + bits256 zero; int32_t flag,nonz; struct nn_pollfd pfd; + memset(zero.bytes,0,sizeof(zero)); + strcpy(LP_reserved_msgs_stats.name,"LP_reserved_msgs"); + LP_reserved_msgs_stats.threshold = 150.; + while ( 1 ) + { + nonz = 0; + LP_millistats_update(&LP_reserved_msgs_stats); + if ( num_Reserved_msgs[0] > 0 || num_Reserved_msgs[1] > 0 ) + { + nonz++; + flag = 0; + if ( LP_mypubsock >= 0 ) + { + memset(&pfd,0,sizeof(pfd)); + pfd.fd = LP_mypubsock; + pfd.events = NN_POLLOUT; + if ( nn_poll(&pfd,1,1) == 1 ) + flag = 1; + } else flag = 1; + if ( flag == 1 ) + { + portable_mutex_lock(&LP_reservedmutex); + if ( num_Reserved_msgs[1] > 0 ) + { + num_Reserved_msgs[1]--; +//printf("PRIORITY BROADCAST.(%s)\n",Reserved_msgs[1][num_Reserved_msgs[1]]); + LP_broadcast_message(LP_mypubsock,"","",zero,Reserved_msgs[1][num_Reserved_msgs[1]]); + Reserved_msgs[1][num_Reserved_msgs[1]] = 0; + } + else if ( num_Reserved_msgs[0] > 0 ) + { + num_Reserved_msgs[0]--; +//printf("BROADCAST.(%s)\n",Reserved_msgs[0][num_Reserved_msgs[0]]); + LP_broadcast_message(LP_mypubsock,"","",zero,Reserved_msgs[0][num_Reserved_msgs[0]]); + Reserved_msgs[0][num_Reserved_msgs[0]] = 0; + } + portable_mutex_unlock(&LP_reservedmutex); } - } else LP_peersquery(mypeer,pubsock,seednode,myport,"127.0.0.1",myport); + } + if ( ignore == 0 ) + break; + if ( nonz != 0 ) + usleep(1000); + else usleep(5000); } } +int32_t LP_reserved_msg(int32_t priority,char *base,char *rel,bits256 pubkey,char *msg) +{ + int32_t n = 0; + portable_mutex_lock(&LP_reservedmutex); + if ( num_Reserved_msgs[priority] < sizeof(Reserved_msgs[priority])/sizeof(*Reserved_msgs[priority]) ) + { + Reserved_msgs[priority][num_Reserved_msgs[priority]++] = msg; + n = num_Reserved_msgs[priority]; + } else LP_broadcast_message(LP_mypubsock,base,rel,pubkey,msg); + if ( num_Reserved_msgs[priority] > max_Reserved_msgs[priority] ) + { + max_Reserved_msgs[priority] = num_Reserved_msgs[priority]; + if ( (max_Reserved_msgs[priority] % 100) == 0 ) + printf("New priority.%d max_Reserved_msgs.%d\n",priority,max_Reserved_msgs[priority]); + } + portable_mutex_unlock(&LP_reservedmutex); + return(n); +} + void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybusport,char *passphrase,int32_t amclient,char *userhome,cJSON *argjson) { - char *myipaddr=0; long filesize,n; int32_t timeout,pubsock=-1; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128],bindaddr[128]; void *ctx = bitcoin_ctx(); + char *myipaddr=0,version[64]; long filesize,n; int32_t valid,timeout,pubsock=-1; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128],bindaddr[128],*coins_str=0; cJSON *coinsjson=0; void *ctx = bitcoin_ctx(); + sprintf(version,"Marketmaker %s.%s %s rsize.%ld",LP_MAJOR_VERSION,LP_MINOR_VERSION,LP_BUILD_NUMBER,sizeof(struct basilisk_request)); + printf("%s %u\n",version,calc_crc32(0,version,(int32_t)strlen(version))); + if ( LP_MAXPRICEINFOS > 256 ) + { + printf("LP_MAXPRICEINFOS %d wont fit in a uint8_t, need to increase the width of the baseind and relind for struct LP_pubkey_quote\n",LP_MAXPRICEINFOS); + exit(-1); + } LP_showwif = juint(argjson,"wif"); if ( passphrase == 0 || passphrase[0] == 0 ) { @@ -560,6 +911,7 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu } #endif OS_randombytes((void *)&n,sizeof(n)); + srand((uint32_t)n); if ( jobj(argjson,"gui") != 0 ) safecopy(LP_gui,jstr(argjson,"gui"),sizeof(LP_gui)); if ( jobj(argjson,"canbind") == 0 ) @@ -594,17 +946,28 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu portable_mutex_init(&LP_swaplistmutex); portable_mutex_init(&LP_cachemutex); portable_mutex_init(&LP_networkmutex); + portable_mutex_init(&LP_gcmutex); portable_mutex_init(&LP_forwardmutex); + portable_mutex_init(&LP_inusemutex); portable_mutex_init(&LP_psockmutex); portable_mutex_init(&LP_coinmutex); portable_mutex_init(&LP_pubkeymutex); + portable_mutex_init(&LP_electrummutex); portable_mutex_init(&LP_messagemutex); portable_mutex_init(&LP_portfoliomutex); - LP_sessionid = (uint32_t)time(NULL); - printf("getting myipaddr sessionid.%u\n",LP_sessionid); - if ( system("curl -s4 checkip.amazonaws.com > /tmp/myipaddr") == 0 ) + portable_mutex_init(&LP_butxomutex); + portable_mutex_init(&LP_reservedmutex); + portable_mutex_init(&LP_nanorecvsmutex); + portable_mutex_init(&LP_tradebotsmutex); + portable_mutex_init(&LP_cJSONmutex); + myipaddr = clonestr("127.0.0.1"); +#ifndef _WIN32 +#ifndef FROM_JS + if ( system("curl -s4 checkip.amazonaws.com > myipaddr") == 0 ) { - if ( (myipaddr= OS_filestr(&filesize,"/tmp/myipaddr")) != 0 && myipaddr[0] != 0 ) + char ipfname[64]; + strcpy(ipfname,"myipaddr"); + if ( (myipaddr= OS_filestr(&filesize,ipfname)) != 0 && myipaddr[0] != 0 ) { n = strlen(myipaddr); if ( myipaddr[n-1] == '\n' ) @@ -612,16 +975,27 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu strcpy(LP_myipaddr,myipaddr); } else printf("error getting myipaddr\n"); } else printf("error issuing curl\n"); +#else + IAMLP = 0; +#endif +#endif if ( IAMLP != 0 ) { pubsock = -1; nanomsg_transportname(0,subaddr,myipaddr,mypubport); nanomsg_transportname(1,bindaddr,myipaddr,mypubport); + //nanomsg_transportname2(1,bindaddr2,myipaddr,mypubport); + valid = 0; if ( (pubsock= nn_socket(AF_SP,NN_PUB)) >= 0 ) { + valid = 0; if ( nn_bind(pubsock,bindaddr) >= 0 ) + valid++; + //if ( nn_bind(pubsock,bindaddr2) >= 0 ) + // valid++; + if ( valid > 0 ) { - timeout = 10; + timeout = 1; nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); } else @@ -631,11 +1005,12 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu nn_close(pubsock), pubsock = -1; } } else printf("error getting pubsock %d\n",pubsock); - printf(">>>>>>>>> myipaddr.%s (%s) pullsock.%d\n",myipaddr,subaddr,pubsock); + printf(">>>>>>>>> myipaddr.(%s) (%s) pullsock.%d valid.%d\n",bindaddr,subaddr,pubsock,valid); LP_mypubsock = pubsock; } printf("got %s, initpeers\n",myipaddr); - LP_initpeers(pubsock,mypeer,myipaddr,myport,jstr(argjson,"seednode")); + LP_initpeers(pubsock,mypeer,myipaddr,myport,jstr(argjson,"seednode"),mypullport,mypubport); + RPC_port = myport; printf("get public socket\n"); LP_mypullsock = LP_initpublicaddr(ctx,&mypullport,pushaddr,myipaddr,mypullport,0); strcpy(LP_publicaddr,pushaddr); @@ -643,42 +1018,283 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu LP_mybussock = LP_coinbus(mybusport); //LP_deadman_switch = (uint32_t)time(NULL); printf("canbind.%d my command address is (%s) pullsock.%d pullport.%u\n",LP_canbind,pushaddr,LP_mypullsock,mypullport); - printf("initcoins\n"); - LP_initcoins(ctx,pubsock,jobj(argjson,"coins"),passphrase); - if ( IAMLP != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_psockloop,(void *)&myipaddr) != 0 ) + if ( (coinsjson= jobj(argjson,"coins")) == 0 ) + { + if ( (coins_str= OS_filestr(&filesize,"coins.json")) != 0 || (coins_str= OS_filestr(&filesize,"exchanges/coins.json")) != 0 ) + { + unstringify(coins_str); + printf("UNSTRINGIFIED.(%s)\n",coins_str); + coinsjson = cJSON_Parse(coins_str); + free(coins_str); + // yes I know this coinsjson is not freed, not sure about if it is referenced + } + } + if ( coinsjson == 0 ) + { + printf("no coins object or coins.json file, must abort\n"); + exit(-1); + } + LP_initcoins(ctx,pubsock,coinsjson); + + G.waiting = 1; + LP_passphrase_init(passphrase,jstr(argjson,"gui")); +#ifndef FROM_JS + if ( IAMLP != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_psockloop,(void *)myipaddr) != 0 ) { printf("error launching LP_psockloop for (%s)\n",myipaddr); exit(-1); } + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_reserved_msgs,(void *)myipaddr) != 0 ) + { + printf("error launching LP_reserved_msgs for (%s)\n",myipaddr); + exit(-1); + } + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)utxosQ_loop,(void *)myipaddr) != 0 ) + { + printf("error launching utxosQ_loop for (%s)\n",myipaddr); + exit(-1); + } if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)stats_rpcloop,(void *)&myport) != 0 ) { printf("error launching stats rpcloop for port.%u\n",myport); exit(-1); } - if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)command_rpcloop,(void *)&myipaddr) != 0 ) + uint16_t myport2 = myport-1; + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)stats_rpcloop,(void *)&myport2) != 0 ) { printf("error launching stats rpcloop for port.%u\n",myport); exit(-1); } - if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)queue_loop,(void *)&myipaddr) != 0 ) + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)command_rpcloop,(void *)myipaddr) != 0 ) { - printf("error launching stats rpcloop for port.%u\n",myport); + printf("error launching command_rpcloop for port.%u\n",myport); exit(-1); } - if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)prices_loop,(void *)&myipaddr) != 0 ) + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)queue_loop,(void *)myipaddr) != 0 ) { - printf("error launching stats rpcloop for port.%u\n",myport); + printf("error launching queue_loop for port.%u\n",myport); + exit(-1); + } + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)gc_loop,(void *)myipaddr) != 0 ) + { + printf("error launching gc_loop for port.%u\n",myport); exit(-1); } - //if ( (retstr= basilisk_swapentry(0,0)) != 0 ) - // free(retstr); + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)prices_loop,ctx) != 0 ) + { + printf("error launching prices_loop for port.%u\n",myport); + exit(-1); + } + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_coinsloop,(void *)"") != 0 ) + { + printf("error launching LP_coinsloop for port.%u\n",myport); + exit(-1); + } + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_coinsloop,(void *)"BTC") != 0 ) + { + printf("error launching BTC LP_coinsloop for port.%u\n",myport); + exit(-1); + } + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_coinsloop,(void *)"KMD") != 0 ) + { + printf("error launching KMD LP_coinsloop for port.%u\n",myport); + exit(-1); + } + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_pubkeysloop,(void *)myipaddr) != 0 ) + { + printf("error launching LP_pubkeysloop for ctx.%p\n",ctx); + exit(-1); + } + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_privkeysloop,(void *)myipaddr) != 0 ) + { + printf("error launching LP_privkeysloop for ctx.%p\n",ctx); + exit(-1); + } + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_swapsloop,(void *)myipaddr) != 0 ) + { + printf("error launching LP_swapsloop for port.%u\n",myport); + exit(-1); + } + int32_t nonz; while ( 1 ) { - //fprintf(stderr,"."); - if ( LP_mainloop_iter(ctx,myipaddr,mypeer,pubsock,pushaddr,myport,passphrase) == 0 ) - usleep(1000000 / MAINLOOP_PERSEC); + nonz = 0; + G.waiting = 1; + while ( G.initializing != 0 ) + { + //fprintf(stderr,"."); + sleep(3); + } + if ( LP_mainloop_iter(ctx,myipaddr,mypeer,pubsock,pushaddr,myport) != 0 ) + nonz++; + if ( nonz == 0 ) + usleep(1000); + else if ( IAMLP == 0 ) + usleep(1000); } +#endif } +#ifdef FROM_JS +extern void *Nanomsg_threadarg; +void *nn_thread_main_routine(void *arg); + +void emscripten_usleep(int32_t x) +{ +} + +char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params,int32_t timeout) +{ + static uint32_t counter; char fname[512],*retstr; long fsize; + if ( strncmp("http://",url,strlen("http://")) != 0 ) + return(clonestr("{\"error\":\"only http allowed\"}")); + sprintf(fname,"bitcoind_RPC/request.%d",counter % 10); + counter++; + //printf("issue.(%s)\n",url); + emscripten_wget(url,fname); + retstr = OS_filestr(&fsize,fname); + //printf("bitcoind_RPC(%s) -> fname.(%s) %s\n",url,fname,retstr); + return(retstr); +} + +char *barterDEX(char *argstr) +{ + static void *ctx; + cJSON *argjson; char *retstr; + if ( ctx == 0 ) + ctx = bitcoin_ctx(); + printf("barterDEX.(%s)\n",argstr); + if ( (argjson= cJSON_Parse(argstr)) != 0 ) + { + retstr = LP_command_process(ctx,LP_myipaddr,LP_mypubsock,argjson,(uint8_t *)argstr,(int32_t)strlen(argstr)); + free_json(argjson); + } else retstr = clonestr("{\"error\":\"couldnt parse request\"}"); + return(retstr); +} + +void LP_fromjs_iter() +{ + static void *ctx; char *retstr; + if ( G.initializing != 0 ) + { + printf("LP_fromjs_iter during G.initializing, skip\n"); + return; + } + if ( ctx == 0 ) + ctx = bitcoin_ctx(); + if ( 0 && (LP_counter % 100) == 0 ) + printf("LP_fromjs_iter got called LP_counter.%d userpass.(%s) ctx.%p\n",LP_counter,G.USERPASS,ctx); + //if ( Nanomsg_threadarg != 0 ) + // nn_thread_main_routine(Nanomsg_threadarg); + //LP_pubkeys_query(); + //LP_utxosQ_process(); + //LP_nanomsg_recvs(ctx); + LP_mainloop_iter(ctx,LP_myipaddr,0,LP_mypubsock,LP_publicaddr,LP_RPCPORT); + //queue_loop(0); + if ( 0 && (LP_counter % 10) == 0 ) // 10 seconds + { + LP_coinsloop(0); + if ( (LP_counter % 100) == 0 ) // 100 seconds + { + LP_notify_pubkeys(ctx,LP_mypubsock); + LP_privkey_updates(ctx,LP_mypubsock,0); + if ( (retstr= basilisk_swapentry(0,0)) != 0 ) + free(retstr); + } + } + LP_counter++; +} + +#endif + +#undef calloc +#undef free +#undef realloc +#undef clonestr + +struct LP_memory_list +{ + struct LP_memory_list *next,*prev; + uint32_t timestamp,len; + void *ptr; +} *LP_memory_list; +int32_t zeroval() { return(0); } + +void *LP_alloc(uint64_t len) +{ +//return(calloc(1,len)); + LP_cjson_allocated += len; + LP_cjson_total += len; + LP_cjson_count++; + struct LP_memory_list *mp; + mp = calloc(1,sizeof(*mp) + len); + mp->ptr = calloc(1,len); + //printf(">>>>>>>>>>> LP_alloc mp.%p ptr.%p len.%llu %llu\n",mp,mp->ptr,(long long)len,(long long)LP_cjson_allocated); + mp->timestamp = (uint32_t)time(NULL); + mp->len = (uint32_t)len; + portable_mutex_lock(&LP_cJSONmutex); + DL_APPEND(LP_memory_list,mp); + portable_mutex_unlock(&LP_cJSONmutex); + return(mp->ptr); +} + +void LP_free(void *ptr) +{ + static uint32_t lasttime,unknown; static int64_t lasttotal; +//free(ptr); return; + uint32_t now; char str[65]; int32_t n,lagging; uint64_t total = 0; struct LP_memory_list *mp,*tmp; + if ( (now= (uint32_t)time(NULL)) > lasttime+1 ) + { + n = lagging = 0; + DL_FOREACH_SAFE(LP_memory_list,mp,tmp) + { + total += mp->len; + n++; + if ( 0 && now > mp->timestamp+120 ) + { + lagging++; + if ( now > mp->timestamp+240 ) + { + portable_mutex_lock(&LP_cJSONmutex); + DL_DELETE(LP_memory_list,mp); + portable_mutex_unlock(&LP_cJSONmutex); + free(mp->ptr); + free(mp); + } + } + } + printf("[%lld] total %d allocated total %llu/%llu [%llu %llu] %.1f ave %s unknown.%u lagging.%d\n",(long long)(total-lasttotal),n,(long long)total,(long long)LP_cjson_allocated,(long long)LP_cjson_total,(long long)LP_cjson_count,(double)LP_cjson_total/LP_cjson_count,mbstr(str,total),unknown,lagging); + lasttime = (uint32_t)time(NULL); + lasttotal = total; + } + DL_FOREACH_SAFE(LP_memory_list,mp,tmp) + { + if ( mp->ptr == ptr ) + break; + mp = 0; + } + if ( mp != 0 ) + { + LP_cjson_allocated -= mp->len; + portable_mutex_lock(&LP_cJSONmutex); + DL_DELETE(LP_memory_list,mp); + portable_mutex_unlock(&LP_cJSONmutex); + //printf(">>>>>>>>>>> LP_free ptr.%p mp.%p len.%u %llu\n",ptr,mp,mp->len,(long long)LP_cjson_allocated); + free(mp->ptr); + free(mp); + } else unknown++; // free from source file with #define redirect for alloc that wasnt +} + +/*char *LP_clonestr(char *str) +{ + char *retstr = LP_alloc(strlen(str)+1); + strcpy(retstr,str); + return(retstr); +} + +void *LP_realloc(void *ptr,uint64_t len) +{ + return(realloc(ptr,len)); +}*/ diff --git a/iguana/exchanges/LP_network.c b/iguana/exchanges/LP_network.c index aadc2f485..d1b147bc8 100644 --- a/iguana/exchanges/LP_network.c +++ b/iguana/exchanges/LP_network.c @@ -28,9 +28,83 @@ struct psock uint16_t Numpsocks,Psockport = MIN_PSOCK_PORT; +#ifdef FROM_JS + +int32_t nn_socket(int domain, int protocol) +{ + return(0); +} + +int32_t nn_close(int s) +{ + return(0); +} + +int32_t nn_setsockopt(int s, int level, int option, const void *optval,size_t optvallen) +{ + return(0); +} + +int32_t nn_getsockopt(int s, int level, int option, void *optval,size_t *optvallen) +{ + return(0); +} + +int32_t nn_bind(int s, const char *addr) +{ + return(-1); +} + +int32_t nn_connect(int s, const char *addr) +{ + if ( strncmp("ws://",addr,strlen("ws://")) != 0 ) + return(-1); + return(0); +} + +int32_t nn_shutdown(int s, int how) +{ + return(0); +} + +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); +} + +int32_t nn_recv(int s, void *buf, size_t len, int flags) +{ + return(0); +} + +int32_t nn_errno(void) +{ + return(-11); +} + +const char *nn_strerror(int errnum) +{ + return("nanomsg error"); +} + +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,"tcp://%s:%u",bindflag == 0 ? ipaddr : "*",port); // ws is worse + sprintf(str,"tcp://%s:%u",bindflag == 0 ? ipaddr : "*",port); + return(str); +} + +/*char *nanomsg_transportname2(int32_t bindflag,char *str,char *ipaddr,uint16_t port) +{ + sprintf(str,"ws://%s:%u",bindflag == 0 ? ipaddr : "*",port+10); return(str); } @@ -46,11 +120,11 @@ int32_t _LP_send(int32_t sock,void *msg,int32_t sendlen,int32_t freeflag) } if ( (sentbytes= nn_send(sock,msg,sendlen,0)) != sendlen ) printf("LP_send sent %d instead of %d\n",sentbytes,sendlen); - //else printf("SENT.(%s)\n",msg); + else printf("SENT.(%s)\n",(char *)msg); if ( freeflag != 0 ) free(msg); return(sentbytes); -} +}*/ int32_t LP_sockcheck(int32_t sock) { @@ -66,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; @@ -74,20 +148,72 @@ int32_t LP_Qenqueued,LP_Qerrors,LP_Qfound; void _LP_sendqueueadd(uint32_t crc32,int32_t sock,uint8_t *msg,int32_t msglen,int32_t peerind) { struct LP_queue *ptr; - ptr = calloc(1,sizeof(*ptr) + msglen); + ptr = calloc(1,sizeof(*ptr) + msglen + sizeof(bits256)); ptr->crc32 = crc32; ptr->sock = sock; ptr->peerind = peerind; - ptr->msglen = msglen; - memcpy(ptr->msg,msg,msglen); + ptr->msglen = (int32_t)(msglen + sizeof(bits256)); + memcpy(ptr->msg,msg,msglen); // sizeof(bits256) at the end all zeroes DL_APPEND(LP_Q,ptr); LP_Qenqueued++; //printf("Q.%p: peerind.%d msglen.%d\n",ptr,peerind,msglen); } +uint32_t _LP_magic_check(bits256 hash,bits256 magic) +{ + bits256 pubkey,shared; + pubkey = curve25519(magic,curve25519_basepoint9()); + shared = curve25519(hash,pubkey); + return(shared.uints[1] & ((1 << LP_MAGICBITS)-1)); +} + +bits256 LP_calc_magic(uint8_t *msg,int32_t len) +{ + static uint32_t maxn,counter,nsum; static double sum; + bits256 magic,hash; int32_t n = 0; double millis; + vcalc_sha256(0,hash.bytes,msg,len); + millis = OS_milliseconds(); + while ( 1 ) + { + magic = rand256(1); + if ( _LP_magic_check(hash,magic) == LP_BARTERDEX_VERSION ) + break; + n++; + } + sum += (OS_milliseconds() - millis); + nsum += n; + counter++; + if ( n > maxn || (LP_rand() % 10000) == 0 ) + { + if ( n > maxn ) + { + 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); + } + return(magic); +} + +int32_t LP_magic_check(uint8_t *msg,int32_t recvlen,char *remoteaddr) +{ + bits256 magic,hash; uint32_t val; + recvlen -= sizeof(bits256); + if ( recvlen > 0 ) + { + vcalc_sha256(0,hash.bytes,msg,recvlen); + memcpy(magic.bytes,&msg[recvlen],sizeof(magic)); + val = _LP_magic_check(hash,magic); + if ( val != LP_BARTERDEX_VERSION ) + printf("magicval = %x from %s\n",val,remoteaddr); + return(val == LP_BARTERDEX_VERSION); + } + return(-1); +} + int32_t LP_crc32find(int32_t *duplicatep,int32_t ind,uint32_t crc32) { - static uint32_t crcs[8192]; static unsigned long dup,total; + static uint32_t crcs[4096]; static unsigned long dup,total; int32_t i; *duplicatep = 0; if ( ind < 0 ) @@ -111,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 @@ -139,49 +265,96 @@ int32_t LP_peerindsock(int32_t *peerindp) return(-1); } -void queue_loop(void *ignore) +void gc_loop(void *arg) +{ + uint32_t now; struct LP_address_utxo *up,*utmp; struct rpcrequest_info *req,*rtmp; int32_t flag = 0; + strcpy(LP_gcloop_stats.name,"gc_loop"); + LP_gcloop_stats.threshold = 11000.; + while ( 1 ) + { + flag = 0; + LP_millistats_update(&LP_gcloop_stats); + portable_mutex_lock(&LP_gcmutex); + DL_FOREACH_SAFE(LP_garbage_collector,req,rtmp) + { + DL_DELETE(LP_garbage_collector,req); + //printf("garbage collect ipbits.%x\n",req->ipbits); + free(req); + flag++; + } + now = (uint32_t)time(NULL); + DL_FOREACH_SAFE(LP_garbage_collector2,up,utmp) + { + if ( now > (uint32_t)up->spendheight+120 ) + { + DL_DELETE(LP_garbage_collector2,up); + //char str[65]; printf("garbage collect %s/v%d lag.%d\n",bits256_str(str,up->U.txid),up->U.vout,now-up->spendheight); + free(up); + } + flag++; + } + portable_mutex_unlock(&LP_gcmutex); + if ( 0 && flag != 0 ) + printf("gc_loop.%d\n",flag); + sleep(10); + } +} + +void queue_loop(void *arg) { struct LP_queue *ptr,*tmp; int32_t sentbytes,nonz,flag,duplicate,n=0; + strcpy(queue_loop_stats.name,"queue_loop"); + queue_loop_stats.threshold = 1000.; while ( 1 ) { - nonz = 0; + LP_millistats_update(&queue_loop_stats); //printf("LP_Q.%p next.%p prev.%p\n",LP_Q,LP_Q!=0?LP_Q->next:0,LP_Q!=0?LP_Q->prev:0); - n = 0; + n = nonz = flag = 0; DL_FOREACH_SAFE(LP_Q,ptr,tmp) { n++; flag = 0; if ( ptr->sock >= 0 ) { - if ( LP_sockcheck(ptr->sock) > 0 ) + if ( ptr->notready == 0 || (LP_rand() % ptr->notready) == 0 ) { - if ( (sentbytes= nn_send(ptr->sock,ptr->msg,ptr->msglen,0)) != ptr->msglen ) - printf("%d LP_send sent %d instead of %d\n",n,sentbytes,ptr->msglen); - // else printf("%d %p qsent %u msglen.%d peerind.%d\n",n,ptr,ptr->crc32,ptr->msglen,ptr->peerind); - ptr->sock = -1; - if ( ptr->peerind > 0 ) - ptr->starttime = (uint32_t)time(NULL); - else flag = 1; + if ( LP_sockcheck(ptr->sock) > 0 ) + { + bits256 magic; + magic = LP_calc_magic(ptr->msg,(int32_t)(ptr->msglen - sizeof(bits256))); + memcpy(&ptr->msg[ptr->msglen - sizeof(bits256)],&magic,sizeof(magic)); + if ( (sentbytes= nn_send(ptr->sock,ptr->msg,ptr->msglen,0)) != ptr->msglen ) + printf("%d LP_send sent %d instead of %d\n",n,sentbytes,ptr->msglen); + else flag++; + ptr->sock = -1; + if ( ptr->peerind > 0 ) + ptr->starttime = (uint32_t)time(NULL); + } + else + { + if ( ptr->notready++ > 1000 ) + flag = 1; + } } } - else if ( time(NULL) > ptr->starttime+13 ) + else if ( 0 && time(NULL) > ptr->starttime+13 ) { LP_crc32find(&duplicate,-1,ptr->crc32); if ( duplicate > 0 ) { LP_Qfound++; - if ( (LP_Qfound % 10) == 0 ) + if ( (LP_Qfound % 100) == 0 ) printf("found.%u Q.%d err.%d match.%d\n",ptr->crc32,LP_Qenqueued,LP_Qerrors,LP_Qfound); - flag = 1; + flag++; } - else + else if ( 0 ) // too much beyond duplicate filter when network is busy { printf("couldnt find.%u peerind.%d Q.%d err.%d match.%d\n",ptr->crc32,ptr->peerind,LP_Qenqueued,LP_Qerrors,LP_Qfound); ptr->peerind++; 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; + flag++; LP_Qerrors++; } } @@ -194,66 +367,47 @@ void queue_loop(void *ignore) portable_mutex_unlock(&LP_networkmutex); free(ptr); ptr = 0; + break; } } - //if ( n != 0 ) - // printf("LP_Q.[%d]\n",n); + if ( arg == 0 ) + break; if ( nonz == 0 ) - usleep(500000); + { + if ( IAMLP == 0 ) + usleep(50000); + else usleep(10000); + } } } void _LP_queuesend(uint32_t crc32,int32_t sock0,int32_t sock1,uint8_t *msg,int32_t msglen,int32_t needack) { - int32_t sentbytes,peerind = 0; - if ( sock0 >= 0 || sock1 >= 0 ) - { - if ( sock0 >= 0 && LP_sockcheck(sock0) > 0 ) - { - if ( (sentbytes= nn_send(sock0,msg,msglen,0)) != msglen ) - printf("_LP_queuesend0 sent %d instead of %d\n",sentbytes,msglen); - else - { - //printf("Q sent %u\n",crc32); - sock0 = -1; - } - } - if ( sock1 >= 0 && LP_sockcheck(sock1) > 0 ) - { - if ( (sentbytes= nn_send(sock1,msg,msglen,0)) != msglen ) - printf("_LP_queuesend1 sent %d instead of %d\n",sentbytes,msglen); - else sock1 = -1; - } - if ( sock0 < 0 && sock1 < 0 ) - return; - } - else + int32_t maxind,peerind = 0; //sentbytes, + if ( sock0 < 0 && sock1 < 0 ) { - peerind = 1; + if ( (maxind= LP_numpeers()) > 0 ) + peerind = (LP_rand() % maxind) + 1; + else peerind = 1; sock0 = LP_peerindsock(&peerind); + if ( (maxind= LP_numpeers()) > 0 ) + peerind = (LP_rand() % maxind) + 1; + else peerind = 1; + sock1 = LP_peerindsock(&peerind); } - portable_mutex_lock(&LP_networkmutex); if ( sock0 >= 0 ) _LP_sendqueueadd(crc32,sock0,msg,msglen,needack * peerind); if ( sock1 >= 0 ) _LP_sendqueueadd(crc32,sock1,msg,msglen,needack); - portable_mutex_unlock(&LP_networkmutex); } void LP_queuesend(uint32_t crc32,int32_t pubsock,char *base,char *rel,uint8_t *msg,int32_t msglen) { - //struct iguana_info *coin; int32_t flag=0,socks[2]; + portable_mutex_lock(&LP_networkmutex); if ( pubsock >= 0 ) - { - //socks[0] = socks[1] = -1; - //if ( rel != 0 && rel[0] != 0 && (coin= LP_coinfind(rel)) != 0 && coin->bussock >= 0 ) - // socks[flag++] = coin->bussock; - //if ( base != 0 && base[0] != 0 && (coin= LP_coinfind(base)) != 0 && coin->bussock >= 0 ) - // socks[flag++] = coin->bussock; - //if ( flag == 0 && pubsock >= 0 ) - _LP_queuesend(crc32,pubsock,-1,msg,msglen,0); - //else _LP_queuesend(socks[0],socks[1],msg,msglen,0); - } else _LP_queuesend(crc32,-1,-1,msg,msglen,1); + _LP_queuesend(crc32,pubsock,-1,msg,msglen,0); + else _LP_queuesend(crc32,-1,-1,msg,msglen,1); + portable_mutex_unlock(&LP_networkmutex); } // first 2 bytes == (crc32 & 0xffff) if encrypted, then nonce is next crypto_box_NONCEBYTES @@ -266,11 +420,19 @@ 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 ) + jaddnum(argjson,"timestamp",(uint32_t)time(NULL)); + // add signature here msg = (void *)jprint(argjson,0); msglen = (int32_t)strlen((char *)msg) + 1; LP_queuesend(crc32,-1,base,rel,msg,msglen); @@ -311,11 +473,14 @@ void LP_broadcast_message(int32_t pubsock,char *base,char *rel,bits256 destpub25 jdelete(argjson,"method2"); jaddstr(argjson,"method2",method); jaddstr(argjson,"method",method); - //printf("CRC32.%u (%s)\n",crc32,(char *)msg); + //if ( strncmp(method,"connect",7) == 0 || strcmp(method,"reserved") == 0 ) + // printf("CRC32.%u (%s)\n",crc32,msgstr); LP_broadcast_finish(pubsock,base,rel,msg,argjson,0); + //if ( strncmp(method,"connect",7) == 0 || strcmp(method,"reserved") == 0 ) + // printf("finished %u\n",crc32); } // else printf("no valid method in (%s)\n",msgstr); free_json(argjson); - } else printf("couldnt parse (%s)\n",msgstr); + } else printf("couldnt parse %p (%s)\n",msgstr,msgstr); } else { @@ -360,8 +525,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 ) { @@ -406,12 +574,19 @@ 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); + 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++; @@ -438,12 +613,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; } } } @@ -611,10 +786,11 @@ 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); @@ -636,6 +812,8 @@ uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired) 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 ( publicaddr[0] != 0 && connectaddr[0] != 0 ) publicport = juint(retjson,"publicport"); free_json(retjson); @@ -653,6 +831,7 @@ int32_t LP_initpublicaddr(void *ctx,uint16_t *mypullportp,char *publicaddr,char { int32_t nntype,pullsock,timeout; char bindaddr[128],connectaddr[128]; *mypullportp = mypullport; + //connectaddr2[0] = 0; if ( ispaired == 0 ) { if ( LP_canbind != 0 ) @@ -663,6 +842,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); } else { @@ -690,7 +870,13 @@ int32_t LP_initpublicaddr(void *ctx,uint16_t *mypullportp,char *publicaddr,char { printf("bind to %s error for %s: %s\n",connectaddr,publicaddr,nn_strerror(nn_errno())); exit(-1); - } else printf("nntype.%d NN_PAIR.%d connect to %s connectsock.%d\n",nntype,NN_PAIR,connectaddr,pullsock); + } + else + { + //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); + } } else { @@ -699,6 +885,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); } timeout = 1; nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); diff --git a/iguana/exchanges/LP_ordermatch.c b/iguana/exchanges/LP_ordermatch.c index e32930cda..bc73ee840 100644 --- a/iguana/exchanges/LP_ordermatch.c +++ b/iguana/exchanges/LP_ordermatch.c @@ -18,26 +18,71 @@ // LP_ordermatch.c // marketmaker // +struct LP_quoteinfo LP_Alicequery,LP_Alicereserved; +double LP_Alicemaxprice; +bits256 LP_Alicedestpubkey; +uint32_t Alice_expiration; +struct { uint64_t aliceid; double bestprice; uint32_t starttime,counter; } Bob_competition[512]; -uint64_t LP_txfeecalc(char *symbol,uint64_t txfee) +double LP_bob_competition(int32_t *counterp,uint64_t aliceid,double price,int32_t counter) { - struct iguana_info *coin; - if ( strcmp(symbol,"BTC") == 0 ) + int32_t i,firsti = -1; uint32_t now = (uint32_t)time(NULL); + *counterp = 0; + for (i=0; i Bob_competition[i].starttime+LP_AUTOTRADE_TIMEOUT ) + { + //printf("aliceid.%llu expired\n",(long long)aliceid); + Bob_competition[i].bestprice = 0.; + Bob_competition[i].starttime = now; + Bob_competition[i].counter = 0; + } + if ( price != 0. && (Bob_competition[i].bestprice == 0. || price < Bob_competition[i].bestprice) ) + { + Bob_competition[i].bestprice = price; + //printf("Bob competition aliceid.%llu <- bestprice %.8f\n",(long long)aliceid,price); + } + Bob_competition[i].counter += counter; + *counterp = Bob_competition[i].counter; + return(Bob_competition[i].bestprice); + } + else if ( Bob_competition[i].aliceid == 0 ) + firsti = i; } - else if ( (coin= LP_coinfind(symbol)) != 0 ) - txfee = coin->txfee; - if ( txfee < LP_MIN_TXFEE ) - txfee = LP_MIN_TXFEE; - return(txfee); + if ( firsti < 0 ) + firsti = (LP_rand() % (sizeof(Bob_competition)/sizeof(*Bob_competition))); + Bob_competition[firsti].starttime = (uint32_t)time(NULL); + Bob_competition[firsti].counter = counter; + Bob_competition[firsti].aliceid = aliceid; + Bob_competition[firsti].bestprice = price; + *counterp = counter; + //printf("Bob competition aliceid.%llu %.8f\n",(long long)aliceid,price); + return(price); } -void LP_txfees(uint64_t *txfeep,uint64_t *desttxfeep,char *base,char *rel) +uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee,int32_t txlen) { - *txfeep = LP_txfeecalc(base,0); - *desttxfeep = LP_txfeecalc(rel,0); + if ( coin != 0 ) + { + if ( strcmp(coin->symbol,"BTC") == 0 ) + { + if ( txlen == 0 ) + txlen = LP_AVETXSIZE; + coin->rate = LP_getestimatedrate(coin); + if ( (txfee= SATOSHIDEN * coin->rate * txlen) <= LP_MIN_TXFEE ) + { + coin->rate = -1.; + coin->rate = _LP_getestimatedrate(coin); + if ( (txfee= SATOSHIDEN * coin->rate * txlen) <= LP_MIN_TXFEE ) + txfee = LP_MIN_TXFEE; + } + } else txfee = coin->txfee; + if ( txfee < LP_MIN_TXFEE ) + txfee = LP_MIN_TXFEE; + } + return(txfee); } double LP_qprice_calc(int64_t *destsatoshisp,int64_t *satoshisp,double price,uint64_t b_satoshis,uint64_t txfee,uint64_t a_value,uint64_t maxdestsatoshis,uint64_t desttxfee) @@ -57,198 +102,15 @@ double LP_qprice_calc(int64_t *destsatoshisp,int64_t *satoshisp,double price,uin else return(0.); } -struct basilisk_request *LP_requestinit(struct basilisk_request *rp,bits256 srchash,bits256 desthash,char *src,uint64_t srcsatoshis,char *dest,uint64_t destsatoshis,uint32_t timestamp,uint32_t quotetime,int32_t DEXselector) -{ - struct basilisk_request R; - memset(rp,0,sizeof(*rp)); - rp->srchash = srchash; - rp->srcamount = srcsatoshis; - rp->timestamp = timestamp; - rp->DEXselector = DEXselector; - safecopy(rp->src,src,sizeof(rp->src)); - safecopy(rp->dest,dest,sizeof(rp->dest)); - R = *rp; - rp->requestid = basilisk_requestid(rp); - rp->quotetime = quotetime; - 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)); - return(rp); -} - -cJSON *LP_quotejson(struct LP_quoteinfo *qp) -{ - double price; cJSON *retjson = cJSON_CreateObject(); - jaddstr(retjson,"base",qp->srccoin); - jaddstr(retjson,"rel",qp->destcoin); - if ( qp->coinaddr[0] != 0 ) - jaddstr(retjson,"address",qp->coinaddr); - if ( qp->timestamp != 0 ) - jaddnum(retjson,"timestamp",qp->timestamp); - if ( bits256_nonz(qp->txid) != 0 ) - { - jaddbits256(retjson,"txid",qp->txid); - jaddnum(retjson,"vout",qp->vout); - } - if ( bits256_nonz(qp->srchash) != 0 ) - jaddbits256(retjson,"srchash",qp->srchash); - if ( qp->txfee != 0 ) - jadd64bits(retjson,"txfee",qp->txfee); - if ( qp->quotetime != 0 ) - jaddnum(retjson,"quotetime",qp->quotetime); - if ( qp->satoshis != 0 ) - jadd64bits(retjson,"satoshis",qp->satoshis); - if ( bits256_nonz(qp->desthash) != 0 ) - jaddbits256(retjson,"desthash",qp->desthash); - if ( bits256_nonz(qp->txid2) != 0 ) - { - jaddbits256(retjson,"txid2",qp->txid2); - jaddnum(retjson,"vout2",qp->vout2); - } - if ( bits256_nonz(qp->desttxid) != 0 ) - { - if ( qp->destaddr[0] != 0 ) - jaddstr(retjson,"destaddr",qp->destaddr); - jaddbits256(retjson,"desttxid",qp->desttxid); - jaddnum(retjson,"destvout",qp->destvout); - } - if ( bits256_nonz(qp->feetxid) != 0 ) - { - jaddbits256(retjson,"feetxid",qp->feetxid); - jaddnum(retjson,"feevout",qp->feevout); - } - if ( qp->desttxfee != 0 ) - jadd64bits(retjson,"desttxfee",qp->desttxfee); - if ( qp->destsatoshis != 0 ) - { - jadd64bits(retjson,"destsatoshis",qp->destsatoshis); - if ( qp->satoshis != 0 ) - { - price = (double)qp->destsatoshis / qp->satoshis; - jaddnum(retjson,"price",price); - } - } - return(retjson); -} - -int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson) -{ - 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->timestamp = juint(argjson,"timestamp"); - qp->quotetime = juint(argjson,"quotetime"); - qp->txid = jbits256(argjson,"txid"); - qp->txid2 = jbits256(argjson,"txid2"); - qp->vout = jint(argjson,"vout"); - qp->vout2 = jint(argjson,"vout2"); - qp->feevout = jint(argjson,"feevout"); - qp->srchash = jbits256(argjson,"srchash"); - qp->desttxid = jbits256(argjson,"desttxid"); - qp->feetxid = jbits256(argjson,"feetxid"); - qp->destvout = jint(argjson,"destvout"); - qp->desthash = jbits256(argjson,"desthash"); - qp->satoshis = j64bits(argjson,"satoshis"); - qp->destsatoshis = j64bits(argjson,"destsatoshis"); - qp->txfee = j64bits(argjson,"txfee"); - qp->desttxfee = j64bits(argjson,"desttxfee"); - return(0); -} - -int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char *destcoin,double price,uint64_t satoshis,uint64_t destsatoshis) -{ - memset(qp,0,sizeof(*qp)); - if ( qp->timestamp == 0 ) - qp->timestamp = (uint32_t)time(NULL); - safecopy(qp->destcoin,destcoin,sizeof(qp->destcoin)); - LP_txfees(&qp->txfee,&qp->desttxfee,utxo->coin,qp->destcoin); - qp->satoshis = satoshis;//(destsatoshis / price) + 0.49; - qp->destsatoshis = destsatoshis; - if ( utxo->iambob == 0 || qp->txfee >= qp->satoshis || qp->txfee >= utxo->deposit.value || utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis) ) - { - printf("quoteinit error.(%d %d %d %d) %.8f vs %.8f\n",utxo->iambob == 0,qp->txfee >= qp->satoshis,qp->txfee >= utxo->deposit.value,utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis),dstr(utxo->deposit.value),dstr(LP_DEPOSITSATOSHIS(qp->satoshis))); - return(-1); - } - qp->txid = utxo->payment.txid; - qp->vout = utxo->payment.vout; - qp->txid2 = utxo->deposit.txid; - qp->vout2 = utxo->deposit.vout; - if ( qp->desttxfee >= qp->destsatoshis ) - { - printf("quoteinit desttxfee %.8f < %.8f destsatoshis\n",dstr(qp->desttxfee),dstr(qp->destsatoshis)); - return(-2); - } - safecopy(qp->srccoin,utxo->coin,sizeof(qp->srccoin)); - safecopy(qp->coinaddr,utxo->coinaddr,sizeof(qp->coinaddr)); - qp->srchash = utxo->pubkey; - return(0); -} - -int32_t LP_quotedestinfo(struct LP_quoteinfo *qp,bits256 desttxid,int32_t destvout,bits256 feetxid,int32_t feevout,bits256 desthash,char *destaddr) -{ - qp->desttxid = desttxid; - qp->destvout = destvout; - qp->desthash = desthash; - qp->feetxid = feetxid; - qp->feevout = feevout; - safecopy(qp->destaddr,destaddr,sizeof(qp->destaddr)); - return(0); -} - -char *LP_quotereceived(cJSON *argjson) -{ - struct LP_cacheinfo *ptr; double price; struct LP_quoteinfo Q; - LP_quoteparse(&Q,argjson); - price = (double)Q.destsatoshis / Q.satoshis; - if ( (ptr= LP_cacheadd(Q.srccoin,Q.destcoin,Q.txid,Q.vout,price,&Q)) != 0 ) - { - ptr->Q = Q; - printf(">>>>>>>>>> received quote %s/%s %.8f\n",Q.srccoin,Q.destcoin,price); - return(clonestr("{\"result\":\"updated\"}")); - } else return(clonestr("{\"error\":\"nullptr\"}")); -} - -char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *rel,double price) -{ - bits256 zero; char *msg; cJSON *reqjson = cJSON_CreateObject(); - memset(zero.bytes,0,sizeof(zero)); - jaddbits256(reqjson,"pubkey",LP_mypub25519); - jaddstr(reqjson,"base",base); - jaddstr(reqjson,"rel",rel); - jaddnum(reqjson,"price",price); - jaddstr(reqjson,"method","postprice"); - msg = jprint(reqjson,1); - LP_broadcast_message(pubsock,base,rel,zero,msg); - return(clonestr("{\"result\":\"success\"}")); -} - -char *LP_postedprice(cJSON *argjson) -{ - bits256 pubkey; double price; char *base,*rel; - //printf("PRICE POSTED.(%s)\n",jprint(argjson,0)); - if ( (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 && (price= jdouble(argjson,"price")) > SMALLVAL ) - { - pubkey = jbits256(argjson,"pubkey"); - if ( bits256_nonz(pubkey) != 0 ) - { - LP_pricefeedupdate(pubkey,base,rel,price); - return(clonestr("{\"result\":\"success\"}")); - } - } - return(clonestr("{\"error\":\"missing fields in posted price\"}")); -} - -int32_t LP_quote_checkmempool(struct LP_quoteinfo *qp) +int32_t LP_quote_checkmempool(struct LP_quoteinfo *qp,struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo) { int32_t selector,spendvini; bits256 spendtxid; - if ( (selector= LP_mempool_vinscan(&spendtxid,&spendvini,qp->srccoin,qp->txid,qp->vout,qp->txid2,qp->vout2)) >= 0 ) + if ( butxo != 0 && (selector= LP_mempool_vinscan(&spendtxid,&spendvini,qp->srccoin,qp->coinaddr,qp->txid,qp->vout,qp->txid2,qp->vout2)) >= 0 ) { char str[65]; printf("LP_tradecommand selector.%d in mempool %s vini.%d",selector,bits256_str(str,spendtxid),spendvini); return(-1); } - if ( (selector= LP_mempool_vinscan(&spendtxid,&spendvini,qp->destcoin,qp->desttxid,qp->destvout,qp->feetxid,qp->feevout)) >= 0 ) + if ( autxo != 0 && (selector= LP_mempool_vinscan(&spendtxid,&spendvini,qp->destcoin,qp->destaddr,qp->desttxid,qp->destvout,qp->feetxid,qp->feevout)) >= 0 ) { char str[65]; printf("LP_tradecommand dest selector.%d in mempool %s vini.%d",selector,bits256_str(str,spendtxid),spendvini); return(-1); @@ -256,57 +118,114 @@ int32_t LP_quote_checkmempool(struct LP_quoteinfo *qp) return(0); } -double LP_quote_validate(struct LP_utxoinfo **autxop,struct LP_utxoinfo **butxop,struct LP_quoteinfo *qp,int32_t iambob) +double LP_quote_validate(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,struct LP_quoteinfo *qp,int32_t iambob) { - double qprice; uint64_t txfee,desttxfee,srcvalue,srcvalue2,destvalue,destvalue2; - *autxop = *butxop = 0; - if ( LP_iseligible(&srcvalue,&srcvalue2,1,qp->srccoin,qp->txid,qp->vout,qp->satoshis,qp->txid2,qp->vout2) == 0 ) + double qprice=0.; char str[65]; cJSON *txout; uint64_t txfee,desttxfee,srcvalue=0,srcvalue2=0,destvalue=0,destvalue2=0; + //printf(">>>>>>> quote satoshis.(%.8f %.8f) %s %.8f -> %s %.8f\n",dstr(qp->satoshis),dstr(qp->destsatoshis),qp->srccoin,dstr(qp->satoshis),qp->destcoin,dstr(qp->destsatoshis)); + if ( butxo != 0 ) { - printf("bob not eligible\n"); - return(-2); + if ( LP_iseligible(&srcvalue,&srcvalue2,1,qp->srccoin,qp->txid,qp->vout,qp->satoshis,qp->txid2,qp->vout2) == 0 ) + { + //printf("bob not eligible %s (%.8f %.8f)\n",jprint(LP_quotejson(qp),1),dstr(srcvalue),dstr(srcvalue2)); + return(-2); + } + if ( (txout= LP_gettxout(qp->srccoin,qp->coinaddr,qp->txid,qp->vout)) != 0 ) + free_json(txout); + else + { + printf("%s %s payment %s/v%d is spent\n",qp->srccoin,qp->coinaddr,bits256_str(str,qp->txid),qp->vout); + return(-21); + } + if ( (txout= LP_gettxout(qp->srccoin,qp->coinaddr,qp->txid2,qp->vout2)) != 0 ) + free_json(txout); + else + { + printf("%s %s deposit %s/v%d is spent\n",qp->srccoin,qp->coinaddr,bits256_str(str,qp->txid2),qp->vout2); + return(-22); + } + if ( bits256_cmp(butxo->deposit.txid,qp->txid2) != 0 || butxo->deposit.vout != qp->vout2 ) + { + char str[65],str2[65]; printf("%s != %s v%d != %d\n",bits256_str(str,butxo->deposit.txid),bits256_str(str2,qp->txid2),butxo->deposit.vout,qp->vout2); + return(-6); + } + if ( strcmp(butxo->coinaddr,qp->coinaddr) != 0 ) + { + printf("(%s) != (%s)\n",butxo->coinaddr,qp->coinaddr); + return(-7); + } } - if ( LP_iseligible(&destvalue,&destvalue2,0,qp->destcoin,qp->desttxid,qp->destvout,qp->destsatoshis,qp->feetxid,qp->feevout) == 0 ) + if ( autxo != 0 ) { - char str[65]; printf("alice not eligible (%.8f %.8f) %s/v%d\n",dstr(destvalue),dstr(destvalue2),bits256_str(str,qp->feetxid),qp->feevout); - return(-3); + if ( LP_iseligible(&destvalue,&destvalue2,0,qp->destcoin,qp->desttxid,qp->destvout,qp->destsatoshis,qp->feetxid,qp->feevout) == 0 ) + { + //alice not eligible 0.36893923 -> dest 0.55020000 1.49130251 (0.61732249 0.00104324) 14b8b74808d2d34a70e5eddd1cad47d855858f8b23cac802576d4d37b5f8af8f/v1 abec6e76169bcb738235ca67fab02cc55390f39e422aa71f1badf8747c290cc4/v1 + //char str[65],str2[65]; printf("alice not eligible %.8f -> dest %.8f %.8f (%.8f %.8f) %s/v%d %s/v%d\n",dstr(qp->satoshis),dstr(qp->destsatoshis),(double)qp->destsatoshis/qp->satoshis,dstr(destvalue),dstr(destvalue2),bits256_str(str,qp->desttxid),qp->destvout,bits256_str(str2,qp->feetxid),qp->feevout); + return(-3); + } + if ( (txout= LP_gettxout(qp->destcoin,qp->destaddr,qp->desttxid,qp->destvout)) != 0 ) + free_json(txout); + else + { + printf("%s %s Apayment %s/v%d is spent\n",qp->destcoin,qp->destaddr,bits256_str(str,qp->desttxid),qp->destvout); + return(-23); + } + if ( (txout= LP_gettxout(qp->destcoin,qp->destaddr,qp->feetxid,qp->feevout)) != 0 ) + free_json(txout); + else + { + printf("%s %s dexfee %s/v%d is spent\n",qp->destcoin,qp->destaddr,bits256_str(str,qp->feetxid),qp->feevout); + return(-24); + } } - if ( LP_quote_checkmempool(qp) < 0 ) + if ( LP_quote_checkmempool(qp,autxo,butxo) < 0 ) return(-4); - if ( (*butxop= LP_utxofind(1,qp->txid,qp->vout)) == 0 ) - return(-5); - if ( bits256_cmp((*butxop)->deposit.txid,qp->txid2) != 0 || (*butxop)->deposit.vout != qp->vout2 ) - return(-6); - if ( strcmp((*butxop)->coinaddr,qp->coinaddr) != 0 ) - return(-7); - if ( iambob == 0 ) - { - if ( (*autxop= LP_utxofind(0,qp->desttxid,qp->destvout)) == 0 ) - return(-8); - if ( bits256_cmp((*autxop)->fee.txid,qp->feetxid) != 0 || (*autxop)->fee.vout != qp->feevout ) + //if ( iambob != 0 && (*butxop= LP_utxofind(1,qp->txid,qp->vout)) == 0 ) + // return(-5); + if ( iambob == 0 && autxo != 0 ) + { + //if ( (*autxop= LP_utxofind(0,qp->desttxid,qp->destvout)) == 0 ) + // return(-8); + if ( bits256_cmp(autxo->fee.txid,qp->feetxid) != 0 || autxo->fee.vout != qp->feevout ) return(-9); - if ( strcmp((*autxop)->coinaddr,qp->destaddr) != 0 ) + if ( strcmp(autxo->coinaddr,qp->destaddr) != 0 ) return(-10); } - if ( destvalue < qp->desttxfee+qp->destsatoshis || srcvalue < qp->txfee+qp->satoshis ) + if ( autxo != 0 && destvalue < qp->desttxfee+qp->destsatoshis ) { - printf("destvalue %.8f srcvalue %.8f, destsatoshis %.8f or satoshis %.8f is too small txfees %.8f %.8f?\n",dstr(destvalue),dstr(srcvalue),dstr(qp->destsatoshis),dstr(qp->satoshis),dstr(qp->desttxfee),dstr(qp->txfee)); + printf("destvalue %.8f destsatoshis %.8f is too small txfee %.8f?\n",dstr(destvalue),dstr(qp->destsatoshis),dstr(qp->desttxfee)); return(-11); } - qprice = ((double)qp->destsatoshis / qp->satoshis); - if ( qp->satoshis < (srcvalue / LP_MINVOL) || srcvalue < qp->txfee*LP_MINSIZE_TXFEEMULT ) - { - printf("utxo payment %.8f is less than %f covered by Q %.8f or <10x txfee %.8f\n",dstr(srcvalue),1./LP_MINVOL,dstr(qp->satoshis),dstr(qp->txfee)); - return(-12); - } - if ( qp->destsatoshis < (destvalue / LP_MINCLIENTVOL) || destvalue < qp->desttxfee*LP_MINSIZE_TXFEEMULT ) + if ( butxo != 0 && srcvalue < qp->txfee+qp->satoshis ) { - printf("destsatoshis %.8f is less than %f of value %.8f or < 10x txfee %.8f\n",dstr(qp->destsatoshis),1./LP_MINCLIENTVOL,dstr(destvalue),dstr(qp->desttxfee)); - return(-13); + printf("srcvalue %.8f [%.8f] satoshis %.8f is too small txfee %.8f?\n",dstr(srcvalue),dstr(srcvalue) - dstr(qp->txfee+qp->satoshis),dstr(qp->satoshis),dstr(qp->txfee)); + return(-33); } + if ( qp->satoshis != 0 ) + qprice = ((double)qp->destsatoshis / (qp->satoshis-qp->txfee)); LP_txfees(&txfee,&desttxfee,qp->srccoin,qp->destcoin); - printf("qprice %.8f <- %.8f/%.8f txfees.(%.8f %.8f) vs (%.8f %.8f)\n",qprice,dstr(qp->destsatoshis),dstr(qp->satoshis),dstr(qp->txfee),dstr(qp->desttxfee),dstr(txfee),dstr(desttxfee)); + if ( txfee < qp->txfee ) + txfee = qp->txfee; + if ( desttxfee < qp->desttxfee ) + desttxfee = qp->desttxfee; + //printf("qprice %.8f <- %.8f/%.8f txfees.(%.8f %.8f) vs (%.8f %.8f)\n",qprice,dstr(qp->destsatoshis),dstr(qp->satoshis),dstr(qp->txfee),dstr(qp->desttxfee),dstr(txfee),dstr(desttxfee)); if ( qp->txfee < LP_REQUIRED_TXFEE*txfee || qp->desttxfee < LP_REQUIRED_TXFEE*desttxfee ) return(-14); + if ( butxo != 0 ) + { + if ( qp->satoshis < (srcvalue / LP_MINVOL) || srcvalue < qp->txfee*LP_MINSIZE_TXFEEMULT ) + { + printf("utxo payment %.8f is less than %f covered by Q %.8f or <10x txfee %.8f [%d %d]\n",dstr(srcvalue),1./LP_MINVOL,dstr(qp->satoshis),dstr(qp->txfee),qp->satoshis < (srcvalue / LP_MINVOL),srcvalue < qp->txfee*LP_MINSIZE_TXFEEMULT); + return(-12); + } + } + if ( autxo != 0 ) + { + if ( qp->destsatoshis < (destvalue / LP_MINCLIENTVOL) || destvalue < qp->desttxfee*LP_MINSIZE_TXFEEMULT ) + { + printf("destsatoshis %.8f is less than %f of value %.8f or < 10x txfee %.8f\n",dstr(qp->destsatoshis),1./LP_MINCLIENTVOL,dstr(destvalue),dstr(qp->desttxfee)); + return(-13); + } + } return(qprice); } @@ -322,42 +241,6 @@ int32_t LP_arrayfind(cJSON *array,bits256 txid,int32_t vout) return(-1); } -double LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct LP_quoteinfo *qp) -{ - cJSON *reqjson; char *msg; int32_t i,flag = 0; double price = 0.; struct LP_utxoinfo *utxo; - if ( strcmp(method,"request") == 0 ) - { - if ( (utxo= LP_utxofind(0,qp->desttxid,qp->destvout)) != 0 && LP_ismine(utxo) > 0 && LP_isavailable(utxo) > 0 ) - LP_unavailableset(utxo,qp->srchash); - else - { - printf("couldnt find my txid to make request\n"); - return(0.); - } - } - reqjson = LP_quotejson(qp); - if ( bits256_nonz(qp->desthash) != 0 ) - flag = 1; - jaddbits256(reqjson,"pubkey",qp->srchash); - jaddstr(reqjson,"method",method); - msg = jprint(reqjson,1); - printf("QUERY.(%s)\n",msg); - LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,qp->srchash,msg); - for (i=0; i<30; i++) - { - if ( (price= LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout)) > SMALLVAL ) - { - if ( flag == 0 || bits256_nonz(qp->desthash) != 0 ) - { - printf("break out of loop.%d price %.8f %s/%s\n",i,price,qp->srccoin,qp->destcoin); - break; - } - } - usleep(100000); - } - return(price); -} - int32_t LP_nanobind(void *ctx,char *pairstr) { int32_t i,r,pairsock = -1; uint16_t mypullport; char bindaddr[128]; @@ -369,7 +252,7 @@ int32_t LP_nanobind(void *ctx,char *pairstr) { for (i=0; i<10; i++) { - r = (10000 + (rand() % 50000)) & 0xffff; + r = (10000 + (LP_rand() % 50000)) & 0xffff; if ( LP_fixed_pairport != 0 ) r = LP_fixed_pairport; nanomsg_transportname(0,pairstr,LP_myipaddr,r); @@ -390,403 +273,956 @@ int32_t LP_nanobind(void *ctx,char *pairstr) return(pairsock); } -int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJSON *argjson,char *base,char *rel,double price,struct LP_quoteinfo *qp) +int32_t LP_nearest_utxovalue(struct iguana_info *coin,char *coinaddr,struct LP_address_utxo **utxos,int32_t n,uint64_t targetval) +{ + int32_t i,replacei,bestheight,mini = -1; struct LP_address_utxo *up,*bestup; struct electrum_info *backupep=0,*ep; int64_t dist,bestdist; uint64_t mindist = (1LL << 60); + if ( (ep= coin->electrum) != 0 ) + { + if ( (backupep= ep->prev) == 0 ) + backupep = ep; + } + //printf("LP_nearest_utxovalue %s utxos[%d] target %.8f\n",coin->symbol,n,dstr(targetval)); + for (i=0; iU.value - targetval); + //printf("nearest i.%d target %.8f val %.8f dist %.8f mindist %.8f mini.%d spent.%d\n",i,dstr(targetval),dstr(up->U.value),dstr(dist),dstr(mindist),mini,up->spendheight); + if ( up->spendheight <= 0 ) + { + if ( dist >= 0 && dist < mindist ) + { + //printf("(%.8f %.8f %.8f).%d ",dstr(up->U.value),dstr(dist),dstr(mindist),mini); + mini = i; + mindist = dist; + } + } + } + } + if ( mini >= 0 && (bestup= utxos[mini]) != 0 ) + { + bestdist = (bestup->U.value - targetval); + replacei = -1; + bestheight = bestup->U.height; + for (i=0; iU.value - targetval); + if ( dist > 0 && up->U.height < bestheight ) + { + if ( (double)dist/bestdist < sqrt(bestheight - up->U.height) ) + { + replacei = i; + bestheight = up->U.height; + } //else printf("almost ratio %.3f dist %.8f vs best %.8f, ht %d vs best ht %d\n",(double)dist/bestdist,dstr(dist),dstr(bestdist),up->U.height,bestheight); + } + } + } + if ( replacei >= 0 ) + { + //printf("REPLACE bestdist %.8f height %d with dist %.8f height %d\n",dstr(bestdist),bestup->U.height,dstr(utxos[replacei]->U.value - targetval),utxos[replacei]->U.height); + return(replacei); + } + } + //printf("return mini.%d\n",mini); + return(mini); +} + +void LP_butxo_set(struct LP_utxoinfo *butxo,struct iguana_info *coin,struct LP_address_utxo *up,struct LP_address_utxo *up2,int64_t satoshis) +{ + butxo->pubkey = G.LP_mypub25519; + safecopy(butxo->coin,coin->symbol,sizeof(butxo->coin)); + safecopy(butxo->coinaddr,coin->smartaddr,sizeof(butxo->coinaddr)); + butxo->payment.txid = up->U.txid; + butxo->payment.vout = up->U.vout; + butxo->payment.value = up->U.value; + butxo->iambob = 1; + butxo->deposit.txid = up2->U.txid; + butxo->deposit.vout = up2->U.vout; + butxo->deposit.value = up2->U.value; + butxo->S.satoshis = satoshis; +} + +void LP_abutxo_set(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,struct LP_quoteinfo *qp) +{ + if ( butxo != 0 ) + { + memset(butxo,0,sizeof(*butxo)); + butxo->pubkey = qp->srchash; + safecopy(butxo->coin,qp->srccoin,sizeof(butxo->coin)); + safecopy(butxo->coinaddr,qp->coinaddr,sizeof(butxo->coinaddr)); + butxo->payment.txid = qp->txid; + butxo->payment.vout = qp->vout; + //butxo->payment.value = qp->value; + butxo->iambob = 1; + butxo->deposit.txid = qp->txid2; + butxo->deposit.vout = qp->vout2; + //butxo->deposit.value = up2->U.value; + butxo->S.satoshis = qp->satoshis; + } + if ( autxo != 0 ) + { + memset(autxo,0,sizeof(*autxo)); + autxo->pubkey = qp->desthash; + safecopy(autxo->coin,qp->destcoin,sizeof(autxo->coin)); + safecopy(autxo->coinaddr,qp->destaddr,sizeof(autxo->coinaddr)); + autxo->payment.txid = qp->desttxid; + autxo->payment.vout = qp->destvout; + //autxo->payment.value = qp->value; + autxo->iambob = 0; + autxo->fee.txid = qp->feetxid; + autxo->fee.vout = qp->feevout; + //autxo->deposit.value = up2->U.value; + autxo->S.satoshis = qp->destsatoshis; + } +} + +uint64_t LP_basesatoshis(double relvolume,double price,uint64_t txfee,uint64_t desttxfee) +{ + //printf("basesatoshis %.8f (rel %.8f / price %.8f)\n",dstr(SATOSHIDEN * ((relvolume) / price) + 2*txfee),relvolume,price); + if ( relvolume > dstr(desttxfee) && price > SMALLVAL ) + return(SATOSHIDEN * (relvolume / price) + 2*txfee); + else return(0); +} + +struct LP_utxoinfo *LP_address_myutxopair(struct LP_utxoinfo *butxo,int32_t iambob,struct LP_address_utxo **utxos,int32_t max,struct iguana_info *coin,char *coinaddr,uint64_t txfee,double relvolume,double price,uint64_t desttxfee) +{ + struct LP_address *ap; uint64_t targetval,targetval2; int32_t m,mini; struct LP_address_utxo *up,*up2; + memset(butxo,0,sizeof(*butxo)); + targetval = LP_basesatoshis(relvolume,price,txfee,desttxfee); + targetval2 = (targetval / 8) * 9 + 2*txfee; + if ( coin != 0 && (ap= LP_address(coin,coinaddr)) != 0 ) + { + if ( (m= LP_address_utxo_ptrs(coin,iambob,utxos,max,ap,coinaddr)) > 1 ) + { + if ( 0 ) + { + int32_t i; + for (i=0; iU.value >= targetval ) + printf("%.8f ",dstr(utxos[i]->U.value)); + printf("targetval %.8f vol %.8f price %.8f txfee %.8f %s %s\n",dstr(targetval),relvolume,price,dstr(txfee),coin->symbol,coinaddr); + } + mini = -1; + if ( targetval != 0 && (mini= LP_nearest_utxovalue(coin,coinaddr,utxos,m,targetval+txfee)) >= 0 ) + { + up = utxos[mini]; + utxos[mini] = 0; +//printf("found mini.%d %.8f for targetval %.8f -> targetval2 %.8f, ratio %.2f\n",mini,dstr(up->U.value),dstr(targetval),dstr(targetval2),(double)up->U.value/targetval); + if ( (double)up->U.value/targetval < LP_MINVOL-1 ) + + { + if ( (mini= LP_nearest_utxovalue(coin,coinaddr,utxos,m,(targetval2+2*txfee) * 1.01)) >= 0 ) + { + if ( up != 0 && (up2= utxos[mini]) != 0 ) + { + /*if ( (utxo= LP_utxoadd(1,coin->symbol,up->U.txid,up->U.vout,up->U.value,up2->U.txid,up2->U.vout,up2->U.value,coinaddr,ap->pubkey,G.gui,0,targetval)) != 0 ) + { + utxo->S.satoshis = targetval; + char str[65],str2[65]; printf("butxo.%p targetval %.8f, found val %.8f %s | targetval2 %.8f val2 %.8f %s\n",utxo,dstr(targetval),dstr(up->U.value),bits256_str(str,utxo->payment.txid),dstr(targetval2),dstr(up2->U.value),bits256_str(str2,utxo->deposit.txid)); + return(butxo); + }*/ + LP_butxo_set(butxo,coin,up,up2,targetval); + return(butxo); + } + } else printf("cant find targetval2 %.8f\n",dstr(targetval2)); + } else printf("failed ratio test %.8f\n",(double)up->U.value/targetval); + } else if ( targetval != 0 && mini >= 0 ) + printf("targetval %.8f mini.%d\n",dstr(targetval),mini); + } else printf("no %s utxos pass LP_address_utxo_ptrs filter\n",coinaddr); + } else printf("address_myutxopair couldnt find %s %s\n",coin->symbol,coinaddr); + return(0); +} + +int32_t LP_connectstartbob(void *ctx,int32_t pubsock,cJSON *argjson,char *base,char *rel,double price,struct LP_quoteinfo *qp) { - char pairstr[512],*msg; cJSON *retjson; bits256 privkey; int32_t pair=-1,retval = -1,DEXselector = 0; struct basilisk_swap *swap; struct iguana_info *coin; + char pairstr[512]; cJSON *retjson; bits256 privkey; int32_t pair=-1,retval = -1,DEXselector = 0; struct basilisk_swap *swap; struct iguana_info *coin; printf("LP_connectstartbob.(%s) with.(%s) %s\n",LP_myipaddr,jprint(argjson,0),LP_myipaddr); qp->quotetime = (uint32_t)time(NULL); - if ( (coin= LP_coinfind(utxo->coin)) == 0 ) + if ( (coin= LP_coinfind(qp->srccoin)) == 0 ) { - printf("cant find coin.%s\n",utxo->coin); + printf("cant find coin.%s\n",qp->srccoin); return(-1); } - privkey = LP_privkey(utxo->coinaddr,coin->taddr); - if ( bits256_nonz(privkey) != 0 && qp->quotetime >= qp->timestamp-3 && qp->quotetime <= utxo->T.swappending && bits256_cmp(LP_mypub25519,qp->srchash) == 0 ) + privkey = LP_privkey(coin->smartaddr,coin->taddr); + if ( bits256_nonz(privkey) != 0 && bits256_cmp(G.LP_mypub25519,qp->srchash) == 0 ) { + LP_requestinit(&qp->R,qp->srchash,qp->desthash,base,qp->satoshis-qp->txfee,rel,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector); + if ( LP_pendingswap(qp->R.requestid,qp->R.quoteid) > 0 ) + { + printf("requestid.%u quoteid.%u is already in progres\n",qp->R.requestid,qp->R.quoteid); + return(-1); + } + if ( (swap= LP_swapinit(1,0,privkey,&qp->R,qp)) == 0 ) + { + printf("cant initialize swap\n"); + return(-1); + } if ( (pair= LP_nanobind(ctx,pairstr)) >= 0 ) { - LP_requestinit(&qp->R,qp->srchash,qp->desthash,base,qp->satoshis-qp->txfee,rel,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector); - swap = LP_swapinit(1,0,privkey,&qp->R,qp); swap->N.pair = pair; - utxo->S.swap = swap; - swap->utxo = utxo; + //utxo->S.swap = swap; + //swap->utxo = utxo; if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_bobloop,(void *)swap) == 0 ) { retjson = LP_quotejson(qp); jaddstr(retjson,"method","connected"); jaddstr(retjson,"pair",pairstr); - jaddnum(retjson,"requestid",qp->R.requestid); - jaddnum(retjson,"quoteid",qp->R.quoteid); - char str[65]; printf("BOB pubsock.%d binds to %d (%s)\n",pubsock,pair,bits256_str(str,utxo->S.otherpubkey)); - msg = jprint(retjson,1); - LP_broadcast_message(pubsock,base,rel,utxo->S.otherpubkey,msg); + char str[65]; printf("BOB pubsock.%d binds to %d (%s)\n",pubsock,pair,bits256_str(str,qp->desthash)); + LP_reserved_msg(1,base,rel,qp->desthash,jprint(retjson,0)); + sleep(1); + bits256 zero; + memset(zero.bytes,0,sizeof(zero)); + LP_reserved_msg(1,base,rel,zero,jprint(retjson,0)); + free_json(retjson); retval = 0; } else printf("error launching swaploop\n"); } else printf("couldnt bind to any port %s\n",pairstr); } - else - { - printf("dest %.8f vs required %.8f (%d %d %d %d %d)\n",dstr(qp->destsatoshis),dstr(price*(utxo->S.satoshis-qp->txfee)),bits256_nonz(privkey) != 0 ,qp->timestamp == utxo->T.swappending-LP_RESERVETIME,qp->quotetime >= qp->timestamp-3,qp->quotetime < utxo->T.swappending,bits256_cmp(LP_mypub25519,qp->srchash) == 0); - } if ( retval < 0 ) { if ( pair >= 0 ) nn_close(pair); - LP_availableset(utxo); - } else LP_unavailableset(utxo,utxo->S.otherpubkey); + LP_availableset(qp->txid,qp->vout); + LP_availableset(qp->txid2,qp->vout2); + } return(retval); } +char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp,double maxprice,int32_t timeout,int32_t duration,uint32_t tradeid,bits256 destpubkey) +{ + struct LP_utxoinfo *aliceutxo; double price; + if ( (aliceutxo= LP_utxopairfind(0,qp->desttxid,qp->destvout,qp->feetxid,qp->feevout)) == 0 ) + { + char str[65],str2[65]; printf("dest.(%s)/v%d fee.(%s)/v%d\n",bits256_str(str,qp->desttxid),qp->destvout,bits256_str(str2,qp->feetxid),qp->feevout); + return(clonestr("{\"error\":\"cant find alice utxopair\"}")); + } + price = 0.; + memset(qp->txid.bytes,0,sizeof(qp->txid)); + qp->txid2 = qp->txid; + qp->aliceid = LP_aliceid_calc(qp->desttxid,qp->destvout,qp->feetxid,qp->feevout); + if ( (qp->tradeid= tradeid) == 0 ) + qp->tradeid = LP_rand(); + LP_query(ctx,myipaddr,mypubsock,"request",qp); + LP_Alicequery = *qp, LP_Alicemaxprice = maxprice, Alice_expiration = qp->timestamp + timeout, LP_Alicedestpubkey = destpubkey; + char str[65]; printf("LP_trade %s/%s %.8f vol %.8f dest.(%s) maxprice %.8f\n",qp->srccoin,qp->destcoin,dstr(qp->satoshis),dstr(qp->destsatoshis),bits256_str(str,LP_Alicedestpubkey),maxprice); + return(LP_recent_swaps(0)); +} + +int32_t LP_quotecmp(int32_t strictflag,struct LP_quoteinfo *qp,struct LP_quoteinfo *qp2) +{ + if ( bits256_nonz(LP_Alicedestpubkey) != 0 ) + { + if (bits256_cmp(LP_Alicedestpubkey,qp->srchash) != 0 ) + { + printf("reject quote from non-matching pubkey\n"); + return(-1); + } else printf("dont reject quote from destpubkey\n"); + } + if ( bits256_cmp(qp->desthash,qp2->desthash) == 0 && strcmp(qp->srccoin,qp2->srccoin) == 0 && strcmp(qp->destcoin,qp2->destcoin) == 0 && bits256_cmp(qp->desttxid,qp2->desttxid) == 0 && qp->destvout == qp2->destvout && bits256_cmp(qp->feetxid,qp2->feetxid) == 0 && qp->feevout == qp2->feevout && qp->destsatoshis == qp2->destsatoshis && qp->txfee >= qp2->txfee && qp->desttxfee == qp2->desttxfee ) + { + if ( strictflag == 0 || (qp->aliceid == qp2->aliceid && qp->R.requestid == qp2->R.requestid && qp->R.quoteid == qp2->R.quoteid && qp->vout == qp2->vout && qp->vout2 == qp2->vout2 && qp->satoshis == qp2->satoshis && bits256_cmp(qp->txid,qp2->txid) == 0 && bits256_cmp(qp->txid2,qp2->txid2) == 0 && bits256_cmp(qp->srchash,qp2->srchash) == 0) ) + return(0); + else printf("strict compare failure\n"); + } + return(-1); +} + +void LP_alicequery_clear() +{ + memset(&LP_Alicequery,0,sizeof(LP_Alicequery)); + memset(&LP_Alicedestpubkey,0,sizeof(LP_Alicedestpubkey)); + LP_Alicemaxprice = 0.; + Alice_expiration = 0; +} + +int32_t LP_alice_eligible(uint32_t quotetime) +{ + if ( Alice_expiration != 0 && quotetime > Alice_expiration ) + { + printf("time expired for Alice_request\n"); + LP_alicequery_clear(); + } + return(Alice_expiration == 0 || time(NULL) < Alice_expiration); +} + +void LP_reserved(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp) +{ + double price=0.,maxprice = LP_Alicemaxprice; + if ( LP_quotecmp(0,qp,&LP_Alicequery) == 0 ) + { + price = LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout); + if ( LP_pricevalid(price) > 0 && maxprice > SMALLVAL && price <= maxprice ) + { + qp->tradeid = LP_Alicequery.tradeid; + LP_Alicereserved = *qp; + LP_alicequery_clear(); + printf("send CONNECT\n"); + LP_query(ctx,myipaddr,mypubsock,"connect",qp); + } else printf("LP_reserved price %.8f vs maxprice %.8f\n",price,maxprice*1.005); + } else printf("probably a timeout, reject reserved due to not eligible.%d or mismatched quote price %.8f vs maxprice %.8f\n",LP_alice_eligible(qp->quotetime),price,maxprice); +} + char *LP_connectedalice(cJSON *argjson) // alice { - cJSON *retjson; double bid,ask,price,qprice; int32_t pairsock = -1; char *pairstr; int32_t DEXselector = 0; struct LP_utxoinfo *autxo,*butxo; struct LP_quoteinfo Q; struct basilisk_swap *swap; struct iguana_info *coin; + cJSON *retjson; double bid,ask,price,qprice; int32_t pairsock = -1; char *pairstr; int32_t DEXselector = 0; struct LP_utxoinfo *autxo,A,B,*butxo; struct LP_quoteinfo Q; struct basilisk_swap *swap; struct iguana_info *coin; if ( LP_quoteparse(&Q,argjson) < 0 ) + { + LP_aliceid(Q.tradeid,Q.aliceid,"error0",0,0); clonestr("{\"error\":\"cant parse quote\"}"); - if ( bits256_cmp(Q.desthash,LP_mypub25519) != 0 ) + } + if ( bits256_cmp(Q.desthash,G.LP_mypub25519) != 0 ) + { + LP_aliceid(Q.tradeid,Q.aliceid,"error1",0,0); return(clonestr("{\"result\",\"update stats\"}")); - printf("CONNECTED.(%s)\n",jprint(argjson,0)); - if ( (qprice= LP_quote_validate(&autxo,&butxo,&Q,0)) <= SMALLVAL ) + } + printf("CONNECTED.(%s) numpending.%d tradeid.%u requestid.%u quoteid.%u\n",jprint(argjson,0),G.LP_pendingswaps,Q.tradeid,Q.R.requestid,Q.R.quoteid); + LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-Q.txfee,Q.destcoin,Q.destsatoshis-Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector); + printf("calculated requestid.%u quoteid.%u\n",Q.R.requestid,Q.R.quoteid); + if ( LP_pendingswap(Q.R.requestid,Q.R.quoteid) > 0 ) + { + printf("requestid.%u quoteid.%u is already in progres\n",Q.R.requestid,Q.R.quoteid); + retjson = cJSON_CreateObject(); + jaddstr(retjson,"error","swap already in progress"); + return(jprint(retjson,1)); + } + if ( LP_quotecmp(1,&Q,&LP_Alicereserved) == 0 ) { - LP_availableset(autxo); - LP_pendingswaps--; + printf("mismatched between reserved and connected\n"); + } + memset(&LP_Alicereserved,0,sizeof(LP_Alicereserved)); + LP_aliceid(Q.tradeid,Q.aliceid,"connected",Q.R.requestid,Q.R.quoteid); + autxo = &A; + butxo = &B; + memset(autxo,0,sizeof(*autxo)); + memset(butxo,0,sizeof(*butxo)); + LP_abutxo_set(autxo,butxo,&Q); + if ( (qprice= LP_quote_validate(autxo,butxo,&Q,0)) <= SMALLVAL ) + { + LP_availableset(Q.desttxid,Q.vout); + LP_availableset(Q.feetxid,Q.feevout); + LP_aliceid(Q.tradeid,Q.aliceid,"error4",0,0); printf("quote validate error %.0f\n",qprice); return(clonestr("{\"error\":\"quote validation error\"}")); } if ( LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin) <= SMALLVAL || bid <= SMALLVAL ) { printf("this node has no price for %s/%s (%.8f %.8f)\n",Q.destcoin,Q.srccoin,bid,ask); - LP_availableset(autxo); - LP_pendingswaps--; + LP_availableset(Q.desttxid,Q.vout); + LP_availableset(Q.feetxid,Q.feevout); + LP_aliceid(Q.tradeid,Q.aliceid,"error5",0,0); return(clonestr("{\"error\":\"no price set\"}")); } - printf("%s/%s bid %.8f ask %.8f\n",Q.srccoin,Q.destcoin,bid,ask); - //if ( (price= ask) == 0. ) - price = bid; - /*if ( SATOSHIDEN*qprice > (SATOSHIDEN * price) * 1.001 + 10 ) - { - printf("qprice %.8f too big vs %.8f\n",qprice,price); - LP_availableset(autxo); - LP_pendingswaps--; - return(clonestr("{\"error\":\"quote price too expensive\"}")); - }*/ + printf("%s/%s bid %.8f ask %.8f values %.8f %.8f\n",Q.srccoin,Q.destcoin,bid,ask,dstr(butxo->payment.value),dstr(butxo->deposit.value)); + price = bid; if ( (coin= LP_coinfind(Q.destcoin)) == 0 ) { - LP_pendingswaps--; + LP_aliceid(Q.tradeid,Q.aliceid,"error6",0,0); return(clonestr("{\"error\":\"cant get alicecoin\"}")); } Q.privkey = LP_privkey(Q.destaddr,coin->taddr); - if ( bits256_nonz(Q.privkey) != 0 && Q.quotetime >= Q.timestamp-3 ) + if ( bits256_nonz(Q.privkey) != 0 )//&& Q.quotetime >= Q.timestamp-3 ) { retjson = cJSON_CreateObject(); + if ( (swap= LP_swapinit(0,0,Q.privkey,&Q.R,&Q)) == 0 ) + { + jaddstr(retjson,"error","couldnt swapinit"); + LP_availableset(Q.desttxid,Q.vout); + LP_availableset(Q.feetxid,Q.feevout); + LP_aliceid(Q.tradeid,Q.aliceid,"error7",Q.R.requestid,Q.R.quoteid); + return(jprint(retjson,1)); + } if ( (pairstr= jstr(argjson,"pair")) == 0 || (pairsock= nn_socket(AF_SP,NN_PAIR)) < 0 ) + { + LP_aliceid(Q.tradeid,Q.aliceid,"error8",Q.R.requestid,Q.R.quoteid); jaddstr(retjson,"error","couldnt create pairsock"); + } else if ( nn_connect(pairsock,pairstr) >= 0 ) { //timeout = 1; //nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); //nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); - LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-Q.txfee,Q.destcoin,Q.destsatoshis-Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector); - swap = LP_swapinit(0,0,Q.privkey,&Q.R,&Q); + swap->tradeid = Q.tradeid; swap->N.pair = pairsock; - autxo->S.swap = swap; - swap->utxo = autxo; + //autxo->S.swap = swap; + //swap->utxo = autxo; + LP_aliceid(Q.tradeid,Q.aliceid,"started",Q.R.requestid,Q.R.quoteid); printf("alice pairstr.(%s) pairsock.%d\n",pairstr,pairsock); if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_aliceloop,(void *)swap) == 0 ) { + retjson = LP_quotejson(&Q); jaddstr(retjson,"result","success"); - jadd(retjson,"trade",LP_quotejson(&Q)); - jaddnum(retjson,"requestid",Q.R.requestid); - jaddnum(retjson,"quoteid",Q.R.quoteid); - } else jaddstr(retjson,"error","couldnt aliceloop"); - } else printf("connect error %s\n",nn_strerror(nn_errno())); + //jaddnum(retjson,"requestid",Q.R.requestid); + //jaddnum(retjson,"quoteid",Q.R.quoteid); + } + else + { + LP_aliceid(Q.tradeid,Q.aliceid,"error9",Q.R.requestid,Q.R.quoteid); + jaddstr(retjson,"error","couldnt aliceloop"); + } + } + else + { + LP_aliceid(Q.tradeid,Q.aliceid,"error10",Q.R.requestid,Q.R.quoteid); + printf("connect error %s\n",nn_strerror(nn_errno())); + } printf("connected result.(%s)\n",jprint(retjson,0)); if ( jobj(retjson,"error") != 0 ) - LP_availableset(autxo); - else LP_pendingswaps++; + { + LP_availableset(Q.desttxid,Q.vout); + LP_availableset(Q.feetxid,Q.feevout); + } return(jprint(retjson,1)); } else { - LP_availableset(autxo); - printf("no privkey found\n"); + LP_availableset(Q.desttxid,Q.vout); + LP_availableset(Q.feetxid,Q.feevout); + LP_aliceid(Q.tradeid,Q.aliceid,"error11",0,0); + printf("no privkey found coin.%s %s taddr.%u\n",Q.destcoin,Q.destaddr,coin->taddr); return(clonestr("{\"error\",\"no privkey\"}")); } } +int32_t LP_listunspent_both(char *symbol,char *coinaddr,int32_t fullflag) +{ + int32_t i,v,numconfs,height,n=0; uint64_t value; bits256 txid; char buf[512]; cJSON *array,*item; uint32_t now; struct iguana_info *coin = LP_coinfind(symbol); + if ( coin != 0 )//&& (IAMLP != 0 || coin->inactive == 0) ) + { + if ( coin->electrum != 0 || LP_address_ismine(symbol,coinaddr) <= 0 ) + { + //printf("issue path electrum.%p\n",coin->electrum); + //if ( coin->electrum != 0 && (array= electrum_address_gethistory(symbol,coin->electrum,&array,coinaddr)) != 0 ) + // free_json(array); + n = LP_listunspent_issue(symbol,coinaddr,fullflag); + } + else + { + if ( strcmp(symbol,"BTC") == 0 ) + numconfs = 0; + else numconfs = 1; + //printf("my coin electrum.%p\n",coin->electrum); + sprintf(buf,"[%d, 99999999, [\"%s\"]]",numconfs,coinaddr); + if ( (array= bitcoin_json(coin,"listunspent",buf)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + now = (uint32_t)time(NULL); + for (i=0; iinactive:-1); + return(n); +} + +char *LP_bestfit(char *rel,double relvolume) +{ + struct LP_utxoinfo *autxo; + if ( relvolume <= 0. || LP_priceinfofind(rel) == 0 ) + return(clonestr("{\"error\":\"invalid parameter\"}")); + if ( (autxo= LP_utxo_bestfit(rel,SATOSHIDEN * relvolume)) == 0 ) + return(clonestr("{\"error\":\"cant find utxo that is big enough\"}")); + return(jprint(LP_utxojson(autxo),1)); +} + +int32_t LP_aliceonly(char *symbol) +{ + if ( strcmp(symbol,"GAME") == 0 ) + return(1); + else return(0); +} + +int32_t LP_validSPV(char *symbol,char *coinaddr,bits256 txid,int32_t vout) +{ + struct electrum_info *ep,*backupep; cJSON *txobj; struct LP_address_utxo *up; struct iguana_info *coin; struct LP_transaction *tx; + coin = LP_coinfind(symbol); + if ( coin != 0 && (ep= coin->electrum) != 0 ) + { + if ( (up= LP_address_utxofind(coin,coinaddr,txid,vout)) == 0 ) + { + if ( (txobj= electrum_transaction(symbol,ep,&txobj,txid,coinaddr)) != 0 ) + free_json(txobj); + if ( (tx= LP_transactionfind(coin,txid)) != 0 ) + { + if ( vout < tx->numvouts && tx->height > 0 ) + { + printf("added missing utxo for SPV checking\n"); + LP_address_utxoadd((uint32_t)time(NULL),"LP_validSPV",coin,coinaddr,txid,vout,tx->outpoints[vout].value,tx->height,-1); + } + } + } + if ( (up= LP_address_utxofind(coin,coinaddr,txid,vout)) != 0 ) + { + if ( up->SPV < 0 ) + return(-1); + if ( (backupep= ep->prev) == 0 ) + backupep = ep; + up->SPV = LP_merkleproof(coin,coinaddr,backupep,up->U.txid,up->U.height); + if ( up->SPV <= 0 ) + return(-1); + } + } + return(0); +} + int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen) { - char *method,*msg; cJSON *retjson; double qprice,price,bid,ask; struct LP_utxoinfo *autxo,*butxo; int32_t retval = -1; struct LP_quoteinfo Q; - if ( (method= jstr(argjson,"method")) != 0 && (strcmp(method,"request") == 0 ||strcmp(method,"connect") == 0) ) + char *method,*msg,*retstr,str[65]; int32_t DEXselector = 0; uint64_t aliceid; cJSON *retjson; double qprice,range,bestprice,price,bid,ask; struct LP_utxoinfo A,B,*autxo,*butxo; struct iguana_info *coin; struct LP_address_utxo *utxos[1000]; struct LP_quoteinfo Q; int32_t r,counter,retval = -1,max=(int32_t)(sizeof(utxos)/sizeof(*utxos)); + if ( (method= jstr(argjson,"method")) != 0 && (strcmp(method,"reserved") == 0 ||strcmp(method,"connected") == 0 || strcmp(method,"request") == 0 || strcmp(method,"connect") == 0) ) { - printf("TRADECOMMAND.(%s)\n",jprint(argjson,0)); + // LP_checksig + LP_quoteparse(&Q,argjson); + LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-Q.txfee,Q.destcoin,Q.destsatoshis-Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector); + LP_tradecommand_log(argjson); + printf("(%-10u %10u) %12s aliceid.%22llu %5s/%-5s %12.8f -> %12.8f price %12.8f\n",Q.R.requestid,Q.R.quoteid,method,(long long)Q.aliceid,Q.srccoin,Q.destcoin,dstr(Q.satoshis),dstr(Q.destsatoshis),(double)Q.destsatoshis/Q.satoshis); retval = 1; - if ( LP_quoteparse(&Q,argjson) == 0 && bits256_cmp(LP_mypub25519,Q.srchash) == 0 ) + autxo = &A; + butxo = &B; + memset(autxo,0,sizeof(*autxo)); + memset(butxo,0,sizeof(*butxo)); + LP_abutxo_set(autxo,butxo,&Q); + aliceid = j64bits(argjson,"aliceid"); + qprice = jdouble(argjson,"price"); + if ( strcmp(method,"reserved") == 0 ) { - if ( (price= LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin)) <= SMALLVAL || ask <= SMALLVAL ) + bestprice = LP_bob_competition(&counter,aliceid,qprice,1); + //printf("%s lag %ld: aliceid.%llu price %.8f -> bestprice %.8f Alice max %.8f\n",jprint(argjson,0),Q.quotetime - (time(NULL)-20),(long long)aliceid,qprice,bestprice,LP_Alicemaxprice); + if ( LP_Alicemaxprice == 0. ) + return(retval); + if ( bits256_nonz(LP_Alicedestpubkey) != 0 ) { - printf("this node has no price for %s/%s\n",Q.srccoin,Q.destcoin); - return(-3); + if (bits256_cmp(LP_Alicedestpubkey,Q.srchash) != 0 ) + { + printf("got reserved response from different node %s\n",bits256_str(str,Q.srchash)); + return(retval); + } else printf("got reserved response from destpubkey %s\n",bits256_str(str,Q.srchash)); } - price = ask; - if ( (qprice= LP_quote_validate(&autxo,&butxo,&Q,1)) <= SMALLVAL ) + if ( bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 && Q.quotetime > time(NULL)-20 && LP_alice_eligible(Q.quotetime) > 0 ) { - printf("quote validate error %.0f\n",qprice); - return(-4); + printf("alice %s received RESERVED.(%s)\n",bits256_str(str,G.LP_mypub25519),jprint(argjson,0)); + if ( (qprice= LP_quote_validate(autxo,butxo,&Q,0)) <= SMALLVAL ) + { + printf("reserved quote validate error %.0f\n",qprice); + return(retval); + } + if ( LP_validSPV(Q.srccoin,Q.coinaddr,Q.txid,Q.vout) < 0 ) + { + printf("%s src %s failed SPV check\n",Q.srccoin,bits256_str(str,Q.txid)); + return(retval); + } + else if ( LP_validSPV(Q.srccoin,Q.coinaddr,Q.txid2,Q.vout2) < 0 ) + { + printf("%s src2 %s failed SPV check\n",Q.srccoin,bits256_str(str,Q.txid2)); + return(retval); + } + LP_aliceid(Q.tradeid,Q.aliceid,"reserved",0,0); + if ( (retstr= LP_quotereceived(argjson)) != 0 ) + free(retstr); + LP_reserved(ctx,myipaddr,pubsock,&Q); + } + return(retval); + } + else if ( strcmp(method,"connected") == 0 ) + { + bestprice = LP_bob_competition(&counter,aliceid,qprice,1000); + if ( bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 ) + { + if ( (qprice= LP_quote_validate(autxo,butxo,&Q,0)) <= SMALLVAL ) + { + printf("quote validate error %.0f\n",qprice); + return(retval); + } + if ( LP_validSPV(Q.srccoin,Q.coinaddr,Q.txid,Q.vout) < 0 ) + { + printf("%s src %s failed SPV check\n",Q.srccoin,bits256_str(str,Q.txid)); + return(retval); + } + else if (LP_validSPV(Q.srccoin,Q.coinaddr,Q.txid2,Q.vout2) < 0 ) + { + printf("%s src2 %s failed SPV check\n",Q.srccoin,bits256_str(str,Q.txid2)); + return(retval); + } + //printf("alice %s received CONNECTED.(%s)\n",bits256_str(str,G.LP_mypub25519),jprint(argjson,0)); + if ( (retstr= LP_connectedalice(argjson)) != 0 ) + free(retstr); } - if ( qprice < (price - 0.00000001) * 0.9999 ) + return(retval); + } + price = LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin); + if ( (coin= LP_coinfind(Q.srccoin)) == 0 || price <= SMALLVAL || ask <= SMALLVAL ) + { + //printf("this node has no price for %s/%s\n",Q.srccoin,Q.destcoin); + return(retval); + } + price = ask; + //printf("MYPRICE %s/%s %.8f vs qprice %.8f\n",Q.srccoin,Q.destcoin,price,qprice); + if ( LP_validSPV(Q.destcoin,Q.destaddr,Q.desttxid,Q.destvout) < 0 ) + { + printf("%s dest %s failed SPV check\n",Q.destcoin,bits256_str(str,Q.desttxid)); + return(retval); + } + else if (LP_validSPV(Q.destcoin,Q.destaddr,Q.feetxid,Q.feevout) < 0 ) + { + printf("%s dexfee %s failed SPV check\n",Q.destcoin,bits256_str(str,Q.feetxid)); + return(retval); + } + if ( LP_aliceonly(Q.srccoin) > 0 ) + { + printf("{\"error\":\"GAME can only be alice coin\"}\n"); + return(retval); + } + if ( strcmp(method,"request") == 0 ) + { + char str[65]; + if ( bits256_nonz(Q.srchash) == 0 || bits256_cmp(Q.srchash,G.LP_mypub25519) == 0 ) + { + qprice = (double)Q.destsatoshis / Q.satoshis; + strcpy(Q.gui,G.gui); + strcpy(Q.coinaddr,coin->smartaddr); + strcpy(butxo->coinaddr,coin->smartaddr); + Q.srchash = G.LP_mypub25519; + memset(&Q.txid,0,sizeof(Q.txid)); + memset(&Q.txid2,0,sizeof(Q.txid2)); + Q.vout = Q.vout2 = -1; + } else return(retval); + if ( qprice > price ) { - printf("(%.8f %.8f) quote price %.8f too low vs %.8f for %s/%s\n",bid,ask,qprice,price,Q.srccoin,Q.destcoin); - return(-5); + r = (LP_rand() % 100); + range = (qprice - price); + price += (r * range) / 100.; + bestprice = LP_bob_competition(&counter,aliceid,price,0); + printf(">>>>>>>>>>>>> price %.8f qprice %.8f r.%d range %.8f -> %.8f, bestprice %.8f counter.%d\n",ask,qprice,r,range,price,bestprice,counter); + if ( counter > 3 || price > bestprice ) // skip if late or bad price + return(retval); + } else return(retval); + LP_RTmetrics_update(Q.srccoin,Q.destcoin); + if ( LP_RTmetrics_blacklisted(Q.desthash) >= 0 ) + { + printf("request from blacklisted %s, ignore\n",bits256_str(str,Q.desthash)); + return(retval); } - if ( butxo->S.swap == 0 && time(NULL) > butxo->T.swappending ) - butxo->T.swappending = 0; - if ( strcmp(method,"request") == 0 ) // bob needs apayment + fee tx's + LP_address_utxo_reset(coin); + if ( (butxo= LP_address_myutxopair(butxo,1,utxos,max,LP_coinfind(Q.srccoin),Q.coinaddr,Q.txfee,dstr(Q.destsatoshis),price,Q.desttxfee)) != 0 ) { - if ( LP_isavailable(butxo) > 0 ) - { - butxo->T.swappending = Q.timestamp + LP_RESERVETIME; - retjson = LP_quotejson(&Q); - butxo->S.otherpubkey = jbits256(argjson,"desthash"); - LP_unavailableset(butxo,butxo->S.otherpubkey); - jaddnum(retjson,"quotetime",juint(argjson,"quotetime")); - jaddnum(retjson,"pending",butxo->T.swappending); - jaddbits256(retjson,"desthash",butxo->S.otherpubkey); - jaddbits256(retjson,"pubkey",butxo->S.otherpubkey); - jaddstr(retjson,"method","reserved"); - msg = jprint(retjson,1); - printf("set swappending.%u accept qprice %.8f, min %.8f\n(%s)",butxo->T.swappending,qprice,price,msg); - LP_broadcast_message(pubsock,Q.srccoin,Q.destcoin,butxo->S.otherpubkey,msg); - butxo->T.lasttime = (uint32_t)time(NULL); - } else printf("warning swappending.%u swap.%p\n",butxo->T.swappending,butxo->S.swap); + strcpy(Q.gui,G.gui); + strcpy(Q.coinaddr,coin->smartaddr); + Q.srchash = G.LP_mypub25519; + Q.txid = butxo->payment.txid; + Q.vout = butxo->payment.vout; + Q.txid2 = butxo->deposit.txid; + Q.vout2 = butxo->deposit.vout; + Q.satoshis = butxo->S.satoshis; + Q.quotetime = (uint32_t)time(NULL); + printf("found %.8f -> %.8f newprice %.8f vs ask %.8f += %.8f qprice %.8f\n",dstr(Q.satoshis),dstr(Q.destsatoshis),(double)Q.destsatoshis/Q.satoshis,ask,price,qprice); } - else if ( strcmp(method,"connect") == 0 ) // bob + else { - retval = 4; - if ( butxo->T.swappending != 0 && butxo->S.swap == 0 ) - LP_connectstartbob(ctx,pubsock,butxo,argjson,Q.srccoin,Q.destcoin,qprice,&Q); - else printf("pend.%u swap %p when connect came in (%s)\n",butxo->T.swappending,butxo->S.swap,jprint(argjson,0)); + printf("cant find utxopair aliceid.%llu %s/%s %.8f -> relvol %.8f\n",(long long)aliceid,Q.srccoin,Q.destcoin,dstr(LP_basesatoshis(dstr(Q.destsatoshis),price,Q.txfee,Q.desttxfee)),dstr(Q.destsatoshis)); + return(retval); } } + else if ( strcmp(method,"connect") == 0 ) + { + if ( bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 || bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 ) + return(retval); + } + if ( strcmp(Q.coinaddr,coin->smartaddr) != 0 ) + { + printf("bob is patching Q.coinaddr %s mismatch != %s\n",Q.coinaddr,coin->smartaddr); + strcpy(Q.coinaddr,coin->smartaddr); + } + if ( butxo == 0 || bits256_nonz(butxo->payment.txid) == 0 || bits256_nonz(butxo->deposit.txid) == 0 || butxo->payment.vout < 0 || butxo->deposit.vout < 0 ) + { + char str[65],str2[65]; printf("couldnt find bob utxos for autxo %s/v%d %s/v%d %.8f -> %.8f\n",bits256_str(str,Q.txid),Q.vout,bits256_str(str2,Q.txid2),Q.vout2,dstr(Q.satoshis),dstr(Q.destsatoshis)); + return(retval); + } + if ( (qprice= LP_quote_validate(autxo,butxo,&Q,1)) <= SMALLVAL ) + { + printf("quote validate error %.0f\n",qprice); + return(-3); + } + if ( qprice < (ask - 0.00000001) * 0.998 ) + { + printf("(%.8f %.8f) quote price %.8f too low vs %.8f for %s/%s %.8f < %.8f\n",bid,ask,qprice,price,Q.srccoin,Q.destcoin,qprice,(ask - 0.00000001) * 0.998); + return(retval); + } + char *astr = jprint(argjson,0); + char str[65],str2[65]; printf("(%s/v%d %s/v%d) TRADECOMMAND.(%s)\n",bits256_str(str,Q.txid),Q.vout,bits256_str(str2,Q.txid2),Q.vout2,astr); + free(astr); + if ( strcmp(method,"request") == 0 ) // bob needs apayment + fee tx's + { + if ( LP_allocated(Q.txid,Q.vout) == 0 && LP_allocated(Q.txid2,Q.vout2) == 0 ) + { + retjson = LP_quotejson(&Q); + LP_unavailableset(Q.txid,Q.vout,Q.timestamp + LP_RESERVETIME,Q.desthash); + LP_unavailableset(Q.txid2,Q.vout2,Q.timestamp + LP_RESERVETIME,Q.desthash); + if ( Q.quotetime == 0 ) + Q.quotetime = (uint32_t)time(NULL); + jaddnum(retjson,"quotetime",Q.quotetime); + jaddnum(retjson,"pending",Q.timestamp + LP_RESERVETIME); + //jaddbits256(retjson,"desthash",Q.desthash); + jaddstr(retjson,"method","reserved"); + msg = jprint(retjson,0); + printf("return after queued RESERVED: set swappending.%u accept qprice %.8f, min %.8f\n(%s)\n",Q.timestamp + LP_RESERVETIME,qprice,ask,msg); + LP_reserved_msg(1,Q.srccoin,Q.destcoin,Q.desthash,clonestr(msg)); + sleep(1); + bits256 zero; + memset(zero.bytes,0,sizeof(zero)); + LP_reserved_msg(1,Q.srccoin,Q.destcoin,zero,msg); + free_json(retjson); + butxo->T.lasttime = (uint32_t)time(NULL); + return(retval); + } else printf("request processing selected ineligible utxos?\n"); + } + else if ( strcmp(method,"connect") == 0 ) // bob + { + retval = 4; + if ( LP_reservation_check(Q.txid,Q.vout,Q.desthash) == 0 && LP_reservation_check(Q.txid2,Q.vout2,Q.desthash) == 0 ) + { + LP_connectstartbob(ctx,pubsock,argjson,Q.srccoin,Q.destcoin,qprice,&Q); + return(retval); + } else printf("connect message from non-reserved (%s)\n",jprint(argjson,0)); + } } return(retval); } -struct LP_utxoinfo *LP_bestutxo(double *ordermatchpricep,int64_t *bestsatoshisp,int64_t *bestdestsatoshisp,struct LP_utxoinfo *autxo,char *base,double maxprice,int32_t duration,uint64_t txfee,uint64_t desttxfee,uint64_t maxdestsatoshis) +#ifdef oldway +struct LP_utxoinfo *LP_ordermatch_iter(struct LP_address_utxo **utxos,int32_t max,double *ordermatchpricep,int64_t *bestsatoshisp,int64_t *bestdestsatoshisp,struct iguana_info *basecoin,char *coinaddr,uint64_t asatoshis,double price,uint64_t txfee,uint64_t desttxfee,bits256 pubkey,char *gui) +{ + uint64_t basesatoshis; struct LP_utxoinfo *bestutxo; + basesatoshis = LP_basesatoshis(dstr(asatoshis),price,txfee,desttxfee); + //printf("basesatoshis %.8f price %.8f txfee %.8f desttxfee %.8f\n",dstr(basesatoshis),price,dstr(txfee),dstr(desttxfee)); + if ( basesatoshis != 0 && (bestutxo= LP_address_utxopair(0,utxos,max,basecoin,coinaddr,txfee,dstr(basesatoshis)*price,price,desttxfee)) != 0 ) + { + bestutxo->pubkey = pubkey; + safecopy(bestutxo->gui,gui,sizeof(bestutxo->gui)); + *bestsatoshisp = basesatoshis; + *ordermatchpricep = price; + *bestdestsatoshisp = asatoshis; + return(bestutxo); + } + return(0); +} + +struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,int64_t *bestdestsatoshisp,struct LP_utxoinfo *autxo,char *base,double maxprice,int32_t duration,uint64_t txfee,uint64_t desttxfee,char *gui,bits256 *avoids,int32_t numavoids,bits256 destpubkey) { - int64_t satoshis,destsatoshis; uint64_t val,val2; bits256 txid,pubkey; char *obookstr; cJSON *orderbook,*asks,*item; struct LP_utxoinfo *butxo,*bestutxo = 0; int32_t i,n,j,vout,numasks; double bestmetric=0.,metric,vol,price,qprice,bestprice = 0.; struct LP_pubkeyinfo *pubp; + bits256 pubkey; char *obookstr,coinaddr[64]; cJSON *orderbook,*asks,*rawasks,*item; int32_t maxiters,i,j,numasks,max; struct LP_address_utxo **utxos; double price; struct LP_pubkeyinfo *pubp; uint64_t asatoshis; struct iguana_info *basecoin; struct LP_utxoinfo *bestutxo = 0; + maxiters = 100; *ordermatchpricep = 0.; *bestsatoshisp = *bestdestsatoshisp = 0; + basecoin = LP_coinfind(base); if ( duration <= 0 ) duration = LP_ORDERBOOK_DURATION; - if ( maxprice <= 0. || LP_priceinfofind(base) == 0 ) + if ( maxprice <= 0. || LP_priceinfofind(base) == 0 || basecoin == 0 ) return(0); + if ( basecoin->electrum == 0 ) + max = 1000; + else max = LP_MAXDESIRED_UTXOS; + utxos = calloc(max,sizeof(*utxos)); LP_txfees(&txfee,&desttxfee,base,autxo->coin); + printf("LP_buyutxo maxprice %.8f relvol %.8f %s/%s %.8f %.8f\n",maxprice,dstr(autxo->S.satoshis),base,autxo->coin,dstr(txfee),dstr(desttxfee)); if ( (obookstr= LP_orderbook(base,autxo->coin,duration)) != 0 ) { if ( (orderbook= cJSON_Parse(obookstr)) != 0 ) { - if ( (asks= jarray(&numasks,orderbook,"asks")) != 0 ) + if ( (rawasks= jarray(&numasks,orderbook,"asks")) != 0 ) { + if ( (asks= LP_RTmetrics_sort(base,autxo->coin,rawasks,numasks,maxprice,dstr(autxo->S.satoshis))) == 0 ) + asks = rawasks; for (i=0; i maxprice*0.8) + // price = price * 0.9 + 0.1 * maxprice; + //else price *= 1.005; + pubkey = jbits256(item,"pubkey"); + if ( bits256_nonz(destpubkey) != 0 && bits256_cmp(destpubkey,pubkey) != 0 ) + continue; + if ( LP_RTmetrics_blacklisted(pubkey) >= 0 ) + continue; +//printf("[%d/%d] %s pubcmp %d price %.8f vs maxprice %.8f asatoshis %.8f\n",i,numasks,jprint(item,0),bits256_cmp(pubkey,G.LP_mypub25519),price,maxprice,dstr(autxo->S.satoshis)); if ( LP_pricevalid(price) > 0 && price <= maxprice ) { - //price *= 1.0001; - //if ( price > maxprice ) - // price = maxprice; - pubkey = jbits256(item,"pubkey"); - if ( bits256_cmp(pubkey,LP_mypub25519) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 && pubp->numerrors < LP_MAXPUBKEY_ERRORS ) + if ( bits256_nonz(destpubkey) == 0 ) + { + for (j=0; jS.satoshis && LP_isavailable(butxo) > 0 && LP_ismine(butxo) == 0 )//&& butxo->T.bestflag == 0 ) + bitcoin_address(coinaddr,basecoin->taddr,basecoin->pubtype,pubp->rmd160,sizeof(pubp->rmd160)); + asatoshis = autxo->S.satoshis; + //LP_listunspent_query(base,coinaddr); + for (j=0; jiambob,butxo->coin,butxo->payment.txid,butxo->payment.vout,butxo->S.satoshis,butxo->deposit.txid,butxo->deposit.vout) > 0 ) - { - destsatoshis = ((butxo->S.satoshis - txfee) * price); - satoshis = (destsatoshis / price + 0.49) - txfee; - if ( satoshis <= 0 ) - continue; - qprice = (double)destsatoshis / satoshis; - n = (int32_t)((double)destsatoshis / desttxfee); - if ( n < 10 ) - n = 10; - else n = 3; - for (j=0; jS.satoshis,txfee,autxo->payment.value,maxdestsatoshis,desttxfee)) > price+SMALLVAL ) - break; - } - //printf("j.%d/%d qprice %.8f vs price %.8f best.(%.8f %.8f)\n",j,n,qprice,price,dstr(satoshis),dstr(destsatoshis)); - if ( metric < 1.2 && destsatoshis > desttxfee && destsatoshis-desttxfee > (autxo->payment.value / LP_MINCLIENTVOL) && satoshis-txfee > (butxo->S.satoshis / LP_MINVOL) && satoshis <= butxo->payment.value-txfee ) - { - printf("value %.8f price %.8f/%.8f best %.8f destsatoshis %.8f * metric %.8f -> (%f)\n",dstr(autxo->payment.value),price,bestprice,bestmetric,dstr(destsatoshis),metric,dstr(destsatoshis) * metric * metric * metric); - metric = dstr(destsatoshis) * metric * metric * metric; - if ( bestmetric == 0. || metric < bestmetric ) - { - bestutxo = butxo; - *ordermatchpricep = price; - *bestdestsatoshisp = destsatoshis; - *bestsatoshisp = satoshis; - bestmetric = metric; - printf("set best!\n"); - } - } // else printf("skip.(%d %d %d %d %d) metric %f destsatoshis %.8f value %.8f destvalue %.8f txfees %.8f %.8f sats %.8f\n",metric < 1.2,destsatoshis > desttxfee,destsatoshis-desttxfee > (autxo->payment.value / LP_MINCLIENTVOL),satoshis-txfee > (butxo->S.satoshis / LP_MINVOL),satoshis < butxo->payment.value-txfee,metric,dstr(destsatoshis),dstr(butxo->S.satoshis),dstr(autxo->payment.value),dstr(txfee),dstr(desttxfee),dstr(satoshis)); - } - else + if ( (bestutxo= LP_ordermatch_iter(utxos,max,ordermatchpricep,bestsatoshisp,bestdestsatoshisp,basecoin,coinaddr,asatoshis,maxprice*.999,txfee,desttxfee,pubp->pubkey,gui)) != 0 ) { - printf("ineligible.(%.8f %.8f)\n",price,dstr(butxo->S.satoshis)); - if ( butxo->T.spentflag == 0 ) - butxo->T.spentflag = (uint32_t)time(NULL); + //printf("j.%d/%d ordermatch %.8f best satoshis %.8f destsatoshis %.8f txfees (%.8f %.8f)\n",j,maxiters,price,dstr(*bestsatoshisp),dstr(*bestdestsatoshisp),dstr(txfee),dstr(desttxfee)); + break; } + asatoshis = (asatoshis / 64) * 63; } - else - { - if ( butxo != 0 ) - printf("%llu %llu %d %d %d: ",(long long)(vol*SATOSHIDEN),(long long)butxo->S.satoshis,vol*SATOSHIDEN == butxo->S.satoshis,LP_isavailable(butxo) > 0,LP_ismine(butxo) == 0); - printf("cant find butxo.%p or value mismatch %.8f != %.8f or bestflag.%d\n",butxo,vol,butxo!=0?dstr(butxo->S.satoshis):0,butxo->T.bestflag); - } + if ( j < maxiters ) + break; } else printf("self trading or blacklisted peer\n"); } else { if ( i == 0 ) - printf("maxprice %.8f vs %.8f\n",maxprice,price); + printf("too expensive maxprice %.8f vs %.8f\n",maxprice,price); break; } } + if ( asks != 0 && asks != rawasks ) + free_json(asks); } free_json(orderbook); } free(obookstr); } - if ( bestutxo == 0 || *ordermatchpricep == 0. || *bestdestsatoshisp == 0 ) + free(utxos); + if ( *ordermatchpricep == 0. || *bestdestsatoshisp == 0 ) return(0); int32_t changed; LP_mypriceset(&changed,autxo->coin,base,1. / *ordermatchpricep); return(bestutxo); } +#endif -char *LP_bestfit(char *rel,double relvolume) -{ - struct LP_utxoinfo *autxo; - if ( relvolume <= 0. || LP_priceinfofind(rel) == 0 ) - return(clonestr("{\"error\":\"invalid parameter\"}")); - if ( (autxo= LP_utxo_bestfit(rel,SATOSHIDEN * relvolume)) == 0 ) - return(clonestr("{\"error\":\"cant find utxo that is big enough\"}")); - return(jprint(LP_utxojson(autxo),1)); -} - -char *LP_ordermatch(char *base,int64_t txfee,double maxprice,double maxvolume,char *rel,bits256 txid,int32_t vout,bits256 feetxid,int32_t feevout,int64_t desttxfee,int32_t duration) -{ - struct LP_quoteinfo Q; int64_t bestsatoshis=0,bestdestsatoshis = 0; double ordermatchprice = 0.; struct LP_utxoinfo *autxo,*bestutxo; - txfee = LP_txfeecalc(base,txfee); - desttxfee = LP_txfeecalc(rel,desttxfee); - if ( (autxo= LP_utxopairfind(0,txid,vout,feetxid,feevout)) == 0 ) - return(clonestr("{\"error\":\"cant find alice utxopair\"}")); - if ( (bestutxo= LP_bestutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,SATOSHIDEN*maxvolume)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) - return(clonestr("{\"error\":\"cant find ordermatch utxo\"}")); - if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestsatoshis,bestdestsatoshis) < 0 ) - return(clonestr("{\"error\":\"cant set ordermatch quote\"}")); - if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,LP_mypub25519,autxo->coinaddr) < 0 ) - return(clonestr("{\"error\":\"cant set ordermatch quote info\"}")); - return(jprint(LP_quotejson(&Q),1)); -} - -char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp,double maxprice,int32_t timeout,int32_t duration) +char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel,double maxprice,double relvolume,int32_t timeout,int32_t duration,char *gui,uint32_t nonce,bits256 destpubkey,uint32_t tradeid) { - struct LP_utxoinfo *bobutxo,*aliceutxo; cJSON *bestitem=0; int32_t DEXselector=0; uint32_t expiration; double price; struct LP_pubkeyinfo *pubp; - if ( (aliceutxo= LP_utxopairfind(0,qp->desttxid,qp->destvout,qp->feetxid,qp->feevout)) == 0 ) - { - char str[65],str2[65]; printf("dest.(%s)/v%d fee.(%s)/v%d\n",bits256_str(str,qp->desttxid),qp->destvout,bits256_str(str2,qp->feetxid),qp->feevout); - return(clonestr("{\"error\":\"cant find alice utxopair\"}")); - } - if ( (bobutxo= LP_utxopairfind(1,qp->txid,qp->vout,qp->txid2,qp->vout2)) == 0 ) - return(clonestr("{\"error\":\"cant find bob utxopair\"}")); - bobutxo->T.bestflag = (uint32_t)time(NULL); - //if ( (retstr= LP_registerall(0)) != 0 ) - // free(retstr); - price = LP_query(ctx,myipaddr,mypubsock,"request",qp); - bestitem = LP_quotejson(qp); - if ( LP_pricevalid(price) > 0 ) - { - if ( price <= maxprice ) - { - price = LP_query(ctx,myipaddr,mypubsock,"connect",qp); - LP_requestinit(&qp->R,qp->srchash,qp->desthash,bobutxo->coin,qp->satoshis-qp->txfee,qp->destcoin,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector); - expiration = (uint32_t)time(NULL) + timeout; - while ( time(NULL) < expiration ) - { - if ( aliceutxo->S.swap != 0 ) - break; - sleep(1); - } - if ( aliceutxo->S.swap == 0 ) - { - if ( (pubp= LP_pubkeyadd(bobutxo->pubkey)) != 0 ) - pubp->numerrors++; - jaddstr(bestitem,"status","couldnt establish connection"); - } else jaddstr(bestitem,"status","connected"); - jaddnum(bestitem,"quotedprice",price); - jaddnum(bestitem,"maxprice",maxprice); - jaddnum(bestitem,"requestid",qp->R.requestid); - jaddnum(bestitem,"quoteid",qp->R.quoteid); - printf("Alice r.%u qp->%u\n",qp->R.requestid,qp->R.quoteid); - } - else - { - jaddnum(bestitem,"quotedprice",price); - jaddnum(bestitem,"maxprice",maxprice); - jaddstr(bestitem,"status","too expensive"); - } - } - else + uint64_t desttxfee,txfee; uint32_t lastnonce; int64_t bestsatoshis=0,destsatoshis; struct iguana_info *basecoin,*relcoin; struct LP_utxoinfo *autxo,B; struct LP_quoteinfo Q; bits256 pubkeys[100]; + basecoin = LP_coinfind(base); + relcoin = LP_coinfind(rel); + if ( gui == 0 ) + gui = "nogui"; + if ( basecoin == 0 || basecoin->inactive != 0 || relcoin == 0 || relcoin->inactive != 0 ) + return(clonestr("{\"error\":\"base or rel not found or inactive\"}")); + if ( LP_aliceonly(base) > 0 ) + return(clonestr("{\"error\":\"GAME can only be alice coin\"}")); + printf("LP_autobuy %s/%s price %.8f vol %.8f nonce %u\n",base,rel,maxprice,relvolume,nonce); + if ( (lastnonce= LP_lastnonce) != 0 && nonce <= lastnonce ) { - jaddnum(bestitem,"maxprice",maxprice); - jaddstr(bestitem,"status","no response to request"); + printf("nonce.%u not bigger than lastnonce.%u\n",nonce,lastnonce); + return(clonestr("{\"error\":\"invalid nonce\"}")); } - if ( aliceutxo->S.swap == 0 ) - LP_availableset(aliceutxo); - return(jprint(bestitem,0)); -} - -char *LP_autotrade(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel,double maxprice,double relvolume,int32_t timeout,int32_t duration) -{ - uint64_t desttxfee,txfee; int64_t bestsatoshis=0,bestdestsatoshis=0; struct LP_utxoinfo *autxo,*butxo,*bestutxo = 0; double qprice,ordermatchprice=0.; struct LP_quoteinfo Q; + LP_lastnonce = nonce; if ( duration <= 0 ) duration = LP_ORDERBOOK_DURATION; if ( timeout <= 0 ) timeout = LP_AUTOTRADE_TIMEOUT; + if ( basecoin->electrum != 0 && relcoin->electrum != 0 ) + { + if ( timeout < 2*LP_AUTOTRADE_TIMEOUT ) + timeout = 2*LP_AUTOTRADE_TIMEOUT; + } + else if ( basecoin->electrum != 0 || relcoin->electrum != 0 ) + { + if ( timeout < 1.5*LP_AUTOTRADE_TIMEOUT ) + timeout = 1.5*LP_AUTOTRADE_TIMEOUT; + } + if ( time(NULL) < Alice_expiration ) + return(clonestr("{\"error\":\"only one pending request at a time\"}")); + else LP_alicequery_clear(); if ( maxprice <= 0. || relvolume <= 0. || LP_priceinfofind(base) == 0 || LP_priceinfofind(rel) == 0 ) return(clonestr("{\"error\":\"invalid parameter\"}")); - if ( (autxo= LP_utxo_bestfit(rel,SATOSHIDEN * relvolume)) == 0 ) - return(clonestr("{\"error\":\"cant find utxo that is big enough\"}")); + if ( strcmp("BTC",rel) == 0 ) + maxprice *= 1.01; + else maxprice *= 1.001; + memset(pubkeys,0,sizeof(pubkeys)); LP_txfees(&txfee,&desttxfee,base,rel); - if ( (bestutxo= LP_bestutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,SATOSHIDEN*relvolume)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) + destsatoshis = SATOSHIDEN * relvolume; + LP_address_utxo_reset(relcoin); + if ( (autxo= LP_utxo_bestfit(rel,destsatoshis + 2*desttxfee)) == 0 ) + return(clonestr("{\"error\":\"cant find alice utxo that is big enough\"}")); + //printf("bestfit selected alice (%.8f %.8f) for %.8f sats %.8f\n",dstr(autxo->payment.value),dstr(autxo->fee.value),dstr(destsatoshis),dstr(autxo->S.satoshis)); + if ( destsatoshis - desttxfee < autxo->S.satoshis ) + { + destsatoshis -= desttxfee; + autxo->S.satoshis = destsatoshis; + //printf("first path dest %.8f from %.8f\n",dstr(destsatoshis),dstr(autxo->S.satoshis)); + } + else if ( autxo->S.satoshis - desttxfee < destsatoshis ) + { + autxo->S.satoshis -= desttxfee; + destsatoshis = autxo->S.satoshis; + printf("second path dest %.8f from %.8f\n",dstr(destsatoshis),dstr(autxo->S.satoshis)); + } + if ( destsatoshis < (autxo->payment.value / LP_MINCLIENTVOL) || autxo->payment.value < desttxfee*LP_MINSIZE_TXFEEMULT ) { - printf("bestutxo.%p ordermatchprice %.8f bestdestsatoshis %.8f\n",bestutxo,ordermatchprice,dstr(bestdestsatoshis)); - return(clonestr("{\"error\":\"cant find ordermatch utxo\"}")); + printf("destsatoshis %.8f vs utxo %.8f this would have triggered an quote error -13\n",dstr(destsatoshis),dstr(autxo->payment.value)); + return(clonestr("{\"error\":\"cant find alice utxo that is small enough\"}")); } - if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestsatoshis,bestdestsatoshis) < 0 ) + bestsatoshis = 1.001 * LP_basesatoshis(dstr(destsatoshis),maxprice,txfee,desttxfee); + memset(&B,0,sizeof(B)); + strcpy(B.coin,base); + if ( LP_quoteinfoinit(&Q,&B,rel,maxprice,bestsatoshis,destsatoshis) < 0 ) return(clonestr("{\"error\":\"cant set ordermatch quote\"}")); - if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,LP_mypub25519,autxo->coinaddr) < 0 ) + if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,G.LP_mypub25519,autxo->coinaddr) < 0 ) return(clonestr("{\"error\":\"cant set ordermatch quote info\"}")); - if ( (qprice= LP_quote_validate(&autxo,&butxo,&Q,0)) <= SMALLVAL ) + int32_t changed; + LP_mypriceset(&changed,autxo->coin,base,1. / maxprice); + return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration,tradeid,destpubkey)); +#ifdef oldway + LP_RTmetrics_update(base,rel); + while ( 1 ) { - printf("quote validate error %.0f\n",qprice); - return(clonestr("{\"error\":\"quote validation error\"}")); + if ( (bestutxo= LP_buyutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,gui,pubkeys,numpubs,destpubkey)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) + { + printf("bestutxo.%p ordermatchprice %.8f bestdestsatoshis %.8f\n",bestutxo,ordermatchprice,dstr(bestdestsatoshis)); + return(clonestr("{\"error\":\"cant find ordermatch utxo, need to change relvolume to be closer to available\"}")); + } + pubkeys[numpubs++] = bestutxo->pubkey; + if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestsatoshis,bestdestsatoshis) < 0 ) + return(clonestr("{\"error\":\"cant set ordermatch quote\"}")); + if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,G.LP_mypub25519,autxo->coinaddr) < 0 ) + return(clonestr("{\"error\":\"cant set ordermatch quote info\"}")); + maxiters = 200; + qprice = 1. / SMALLVAL; + for (i=0; i maxprice ) + { + printf("i.%d maxiters.%d qprice %.8f vs maxprice %.8f, no acceptable quote for this pubkey\n",i,maxiters,dstr(qprice),dstr(maxprice)); + if ( bits256_nonz(destpubkey) == 0 ) + continue; + else return(clonestr("{\"error\":\"cant ordermatch to destpubkey\"}")); + } + printf("i.%d maxiters.%d qprice %.8f vs maxprice %.8f\n",i,maxiters,dstr(qprice),dstr(maxprice)); + return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration,tradeid,destpubkey)); } - printf("do quote.(%s)\n",jprint(LP_quotejson(&Q),1)); - return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration)); + return(clonestr("{\"error\":\"cant get here\"}")); +#endif } - - diff --git a/iguana/exchanges/LP_peers.c b/iguana/exchanges/LP_peers.c index 5e7a26cc3..4e5e9a231 100644 --- a/iguana/exchanges/LP_peers.c +++ b/iguana/exchanges/LP_peers.c @@ -31,13 +31,13 @@ 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 ) { - jaddnum(item,"session",LP_sessionid); - if ( LP_mypeer != 0 ) - jaddnum(item,"numutxos",LP_mypeer->numutxos); + jaddnum(item,"session",G.LP_sessionid); + //if ( LP_mypeer != 0 ) + // jaddnum(item,"numutxos",LP_mypeer->numutxos); } else jaddnum(item,"session",peer->sessionid); //jaddnum(item,"profit",peer->profitmargin); return(item); @@ -49,14 +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 pushsock,subsock,timeout; char checkip[64],pushaddr[64],subaddr[64]; struct LP_peerinfo *peer = 0; + 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); @@ -67,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 ) @@ -76,22 +79,34 @@ 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 = LP_sessionid; + peer->sessionid = G.LP_sessionid; else peer->sessionid = sessionid; peer->pushsock = peer->subsock = pushsock = subsock = -1; 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); + valid = 0; if ( nn_connect(pushsock,pushaddr) >= 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) %d\n",pushaddr,pushsock); + 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 ) @@ -100,50 +115,62 @@ 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); + valid = 0; if ( nn_connect(subsock,subaddr) >= 0 ) + valid++; + //if ( nn_connect(subsock,subaddr2) >= 0 ) + // valid++; + if ( valid > 0 ) { peer->subsock = subsock; - printf("connected to sub.(%s) %d\n",subaddr,peer->subsock); - } else nn_close(subsock); + printf("connected to sub.(%s) subsock.%d valid.%d\n",subaddr,peer->subsock,valid); + } + else + { + printf("error connecting to subsock.%d (%s)\n",subsock,subaddr); + nn_close(subsock); + subsock = -1; + } } } else { nn_close(pushsock); + pushsock = -1; printf("error connecting to push.(%s)\n",pushaddr); } } else printf("%s pushport.%u subport.%u pushsock.%d\n",ipaddr,pushport,subport,pushsock); - //peer->profitmargin = profitmargin; - peer->ipbits = ipbits; - peer->port = port; - peer->ip_port = ((uint64_t)port << 32) | ipbits; - portable_mutex_lock(&LP_peermutex); - HASH_ADD(hh,LP_peerinfos,ip_port,sizeof(peer->ip_port),peer); - if ( mypeer != 0 ) + if ( peer->pushsock >= 0 && peer->subsock >= 0 ) { - mypeer->numpeers++; - printf("_LPaddpeer %s -> numpeers.%d mypubsock.%d other.(%d %d)\n",ipaddr,mypeer->numpeers,mypubsock,numpeers,numutxos); - } 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 *msg,busaddr[64]; - msg = jprint(LP_peerjson(peer),1); - memset(zero.bytes,0,sizeof(zero)); - //LP_send(mypubsock,msg,(int32_t)strlen(msg)+1,1); - LP_broadcast_message(mypubsock,"","",zero,msg); - if ( 0 ) + //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)\n",ipaddr,mypeer->numpeers,mypubsock,isLP); + } else peer->numpeers = 1; // will become mypeer + portable_mutex_unlock(&LP_peermutex); + if ( IAMLP != 0 && mypubsock >= 0 ) { - HASH_ITER(hh,LP_coins,coin,ctmp) + 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(0,"","",zero,jprint(LP_peerjson(peer),1)); + if ( 0 ) { - if ( coin->bussock >= 0 ) + HASH_ITER(hh,LP_coins,coin,ctmp) { - nanomsg_transportname(0,busaddr,peer->ipaddr,coin->busport); - nn_connect(coin->bussock,busaddr); + if ( coin->bussock >= 0 ) + { + nanomsg_transportname(0,busaddr,peer->ipaddr,coin->busport); + nn_connect(coin->bussock,busaddr); + } } } } - } + } else printf("%s invalid pushsock.%d or subsock.%d\n",peer->ipaddr,peer->pushsock,peer->subsock); } } else printf("LP_addpeer: checkip.(%s) vs (%s)\n",checkip,ipaddr); return(peer); @@ -179,75 +206,76 @@ 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) +void LP_peer_recv(char *ipaddr,int32_t ismine) { - 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 ) + struct LP_peerinfo *peer; + if ( (peer= LP_peerfind((uint32_t)calc_ipbits(ipaddr),RPC_port)) != 0 ) { - if ( (n= cJSON_GetArraySize(array)) > 0 ) - { - for (i=0; ilasttime = now; - if ( strcmp(argipaddr,destipaddr) == 0 && destport == argport && peer->numpeers != n ) - peer->numpeers = n; - } - } - } - } - free_json(array); + peer->numrecv++; + if ( ismine != 0 ) + peer->recvtime = (uint32_t)time(NULL); } - return(n); } -void LP_peersquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *myipaddr,uint16_t myport) +int32_t LP_numpeers() +{ + struct LP_peerinfo *peer,*tmp; int32_t numpeers = 0; + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + if ( peer->isLP != 0 ) + numpeers++; + } + return(numpeers); +} + +uint16_t LP_randpeer(char *destip) { - char *retstr; struct LP_peerinfo *peer,*tmp; 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,mypeer!=0?mypeer->numutxos:0)) != 0 ) + struct LP_peerinfo *peer,*tmp; uint16_t port = 0; int32_t n,r,numpeers = 0; + destip[0] = 0; + numpeers = LP_numpeers(); + if ( numpeers > 0 ) { - //printf("got.(%s)\n",retstr); - now = (uint32_t)time(NULL); - LP_peersparse(mypeer,mypubsock,destipaddr,destport,retstr,now); - free(retstr); - if ( IAMLP != 0 ) + r = LP_rand() % numpeers; + n = 0; + HASH_ITER(hh,LP_peerinfos,peer,tmp) { - HASH_ITER(hh,LP_peerinfos,peer,tmp) + if ( peer->isLP != 0 ) { - if ( peer->lasttime != now ) + if ( n++ == r ) { - printf("{%s:%u}.%d ",peer->ipaddr,peer->port,peer->lasttime - now); - flag++; - if ( (retstr= issue_LP_notify(destipaddr,destport,peer->ipaddr,peer->port,peer->numpeers,0,peer->sessionid)) != 0 ) - free(retstr); + strcpy(destip,peer->ipaddr); + port = peer->port; + break; } } - if ( flag != 0 ) - printf(" <- missing peers\n"); } } + return(port); } -int32_t LP_numpeers() +uint16_t LP_rarestpeer(char *destip) { - struct LP_peerinfo *peer,*tmp; int32_t numpeers = 0; - HASH_ITER(hh,LP_peerinfos,peer,tmp) + 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++) { - numpeers++; + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + if ( iter == 0 && peer->recvtime < now-3600*24 ) + continue; + if ( peer->isLP != 0 ) + { + if ( rarest == 0 || peer->numrecv < rarest->numrecv ) + rarest = peer; + } + } + if ( rarest != 0 ) + break; } - return(numpeers); + if ( rarest == 0 ) + LP_randpeer(destip); + else strcpy(destip,rarest->ipaddr); + return(rarest != 0 ? rarest->port : RPC_port); } + diff --git a/iguana/exchanges/LP_portfolio.c b/iguana/exchanges/LP_portfolio.c index a5982444d..4004a8c41 100644 --- a/iguana/exchanges/LP_portfolio.c +++ b/iguana/exchanges/LP_portfolio.c @@ -18,7 +18,7 @@ // marketmaker // -char LP_portfolio_base[16],LP_portfolio_rel[16]; +char LP_portfolio_base[128],LP_portfolio_rel[128]; double LP_portfolio_relvolume; cJSON *LP_portfolio_entry(struct iguana_info *coin) @@ -57,15 +57,13 @@ uint64_t LP_balance(uint64_t *valuep,int32_t iambob,char *symbol,char *coinaddr) for (i=0; i 0 && is_cJSON_Array(array) != 0 ) { @@ -91,11 +89,12 @@ char *LP_portfolio() { HASH_ITER(hh,LP_coins,coin,tmp) { - if ( coin->inactive != 0 ) + if ( coin->inactive != 0 )//|| (coin->electrum != 0 && coin->obooktime == 0) ) continue; if ( iter == 0 ) { - LP_privkey_init(-1,coin,LP_mypriv25519,LP_mypub25519); + //printf("from portfolio\n"); + 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 ) @@ -186,17 +185,26 @@ char *LP_portfolio_goal(char *symbol,double goal) coin->goal = kmdbtc * 0.5; if ( (coin= LP_coinfind("BTC")) != 0 && coin->inactive == 0 ) coin->goal = kmdbtc * 0.5; + if ( coin->goal != 0 ) + coin->obooktime = (uint32_t)time(NULL); return(LP_portfolio()); } else if ( (coin= LP_coinfind(symbol)) != 0 && coin->inactive == 0 ) { coin->goal = goal; printf("set %s goal %f\n",coin->symbol,goal); + if ( coin->goal != 0 ) + coin->obooktime = (uint32_t)time(NULL); return(LP_portfolio()); } else return(clonestr("{\"error\":\"cant set goal for inactive coin\"}")); } -int32_t LP_autoprices; +int32_t LP_autoprices,num_LP_autorefs; + +struct LP_autoprice_ref +{ + char refbase[65],refrel[65],base[65],rel[65]; +} LP_autorefs[100]; /*int32_t LP_autofill(char *base,char *rel,double maxprice,double totalrelvolume) { @@ -211,38 +219,104 @@ int32_t LP_autoprices; return(-1); }*/ -int32_t LP_autoprice(char *base,char *rel,double minprice,double margin,char *type) +int32_t LP_autoprice(char *base,char *rel,cJSON *argjson) { - struct LP_priceinfo *basepp,*relpp; + //curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"MNZ\",\"rel\":\"KMD\",\"offset\":0.1,\"refbase\":\"KMD\",\refrel\":\"BTC\",\"factor\":15000,\"margin\":0.01}" + struct LP_priceinfo *basepp,*relpp; int32_t i; char *refbase="",*refrel=""; double minprice,margin,offset,factor,fixedprice; + //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; + if ( fixedprice > SMALLVAL || ((refbase= jstr(argjson,"refbase")) != 0 && (refrel= jstr(argjson,"refrel")) != 0) ) + { + if ( fixedprice > SMALLVAL ) + { + refbase = base; + refrel = rel; + } + for (i=0; imargins[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. ) { - if ( margin == 0. ) - margin = oppomargin; - //printf("min %.8f %s/%s %.8f dir.%d margin %.8f (%.8f %.8f)\n",basepp->minprices[relpp->ind],relpp->symbol,basepp->symbol,price,dir,margin,1. / (price * (1. - margin)),(price * (1. + margin))); - if ( dir > 0 ) - price = 1. / (price * (1. - margin)); - else price = (price * (1. + margin)); - if ( (minprice= basepp->minprices[relpp->ind]) == 0. || price >= minprice ) + offset = basepp->offsets[relpp->ind]; + factor = basepp->factors[relpp->ind]; + if ( fabs(price) < SMALLVAL && refbase != 0 && refrel != 0 ) + { + price = LP_myprice(&bid,&ask,refbase,refrel); + //printf("%s/%s USE ref %s/%s %.8f factor %.8f offset %.8f margin %.8f\n",basepp->symbol,relpp->symbol,refbase,refrel,price,factor,offset,margin); + } + if ( LP_pricevalid(price) > 0 ) { - LP_mypriceset(&changed,relpp->symbol,basepp->symbol,price); - //printf("changed.%d\n",changed); - if ( changed != 0 ) - LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,relpp->symbol,basepp->symbol,price); + if ( factor > SMALLVAL ) + { + //double tmp = (price * factor) + offset; + //printf("price %.8f -> %.8f factor %.8f offset %.8f margin %.8f [%.8f %.8f] [%.8f %.8f]\n",price,tmp,factor,offset,margin,(tmp * (1. + margin)),1./(tmp * (1. - margin)),(tmp * (1. - margin)),1./(tmp * (1. + margin))); + price = (price * factor) + offset; + } + if ( margin == 0. ) + margin = oppomargin; + //printf("min %.8f %s/%s %.8f dir.%d margin %.8f (%.8f %.8f)\n",basepp->minprices[relpp->ind],relpp->symbol,basepp->symbol,price,dir,margin,1. / (price * (1. - margin)),(price * (1. + margin))); + if ( dir > 0 ) + newprice = (1. / price) * (1. + margin); + else newprice = (price * (1. + margin)); + if ( (minprice= basepp->minprices[relpp->ind]) == 0. || price >= minprice ) + { + LP_mypriceset(&changed,relpp->symbol,basepp->symbol,newprice); + //printf("autoprice changed.%d %s/%s <- %.8f\n",changed,basepp->symbol,relpp->symbol,price); + if ( changed != 0 || time(NULL) > lasttime+LP_ORDERBOOK_DURATION*.777) + { + lasttime = (uint32_t)time(NULL); + LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,relpp->symbol,basepp->symbol,newprice); + } + } } } } @@ -251,7 +325,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); @@ -323,8 +397,8 @@ double LP_pricesparse(void *ctx,int32_t trexflag,char *retstr,struct LP_priceinf //printf("have trex: iter.%d trexflag.%d %s %.8f %.8f\n",iter,trexflag,symbol,coinpp->bid[1],coinpp->ask[1]); continue; } - LP_autopriceset(ctx,1,refpp,coinpp,price); - LP_autopriceset(ctx,-1,coinpp,refpp,price); + LP_autopriceset(ctx,1,coinpp,refpp,price,0,0); + LP_autopriceset(ctx,-1,refpp,coinpp,price,0,0); } } } @@ -340,23 +414,9 @@ double LP_pricesparse(void *ctx,int32_t trexflag,char *retstr,struct LP_priceinf return(nxtkmd); } -static char *assetids[][3] = -{ - { "12071612744977229797", "UNITY", "10000" }, - { "15344649963748848799", "DEX", "1" }, - { "6883271355794806507", "PANGEA", "10000" }, - { "17911762572811467637", "JUMBLR", "10000" }, - { "17083334802666450484", "BET", "10000" }, - { "13476425053110940554", "CRYPTO", "1000" }, - { "6932037131189568014", "HODL", "1" }, - { "3006420581923704757", "SHARK", "10000" }, - { "17571711292785902558", "BOTS", "1" }, - { "10524562908394749924", "MGW", "1" }, -}; - void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp) { - char *retstr; cJSON *retjson,*bid,*ask; uint64_t bidsatoshis,asksatoshis; int32_t i; double nxtkmd,price; struct LP_priceinfo *kmdpp,*fiatpp,*nxtpp; + char *retstr; cJSON *retjson,*bid,*ask; uint64_t bidsatoshis,asksatoshis; int32_t i; double nxtkmd,price; struct LP_priceinfo *kmdpp,*fiatpp,*nxtpp,*basepp,*relpp; if ( (retstr= issue_curlt("https://bittrex.com/api/v1.1/public/getmarketsummaries",LP_HTTP_TIMEOUT*10)) == 0 ) { printf("trex error getting marketsummaries\n"); @@ -383,8 +443,8 @@ void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp) { //printf("(%s %.8f %.8f) ",CURRENCIES[i],jdouble(retjson,"price"),jdouble(retjson,"invprice")); price = jdouble(retjson,"price"); - LP_autopriceset(ctx,1,kmdpp,fiatpp,price); - LP_autopriceset(ctx,-1,fiatpp,kmdpp,price); + LP_autopriceset(ctx,1,fiatpp,kmdpp,price,0,0); + LP_autopriceset(ctx,-1,kmdpp,fiatpp,price,0,0); free_json(retjson); } } @@ -407,19 +467,29 @@ void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp) if ( bidsatoshis != 0 && asksatoshis != 0 ) price = 0.5 * dstr(bidsatoshis + asksatoshis) * nxtkmd; } - LP_autopriceset(ctx,1,kmdpp,nxtpp,price); - LP_autopriceset(ctx,-1,nxtpp,kmdpp,price); + LP_autopriceset(ctx,1,nxtpp,kmdpp,price,0,0); + LP_autopriceset(ctx,-1,kmdpp,nxtpp,price,0,0); //printf("%s %s -> (%s) nxtkmd %.8f %.8f %.8f\n",assetids[i][1],assetids[i][0],jprint(retjson,0),nxtkmd,0.5*dstr(bidsatoshis + asksatoshis),price); free_json(retjson); } } } } + for (i=0; ifixedprices[basepp->ind],basepp->fixedprices[relpp->ind]); + LP_autopriceset(ctx,1,basepp,relpp,0.,LP_autorefs[i].refbase,LP_autorefs[i].refrel); + } + } } -int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,struct iguana_info *buy,struct iguana_info *sell,double relvolume,int32_t setbaserel) +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; uint32_t requestid,quoteid,iter,i; cJSON *retjson2; + char *retstr2; double bid,ask,maxprice; bits256 zero; uint32_t requestid,quoteid,iter,i; cJSON *retjson2; requestid = quoteid = 0; LP_myprice(&bid,&ask,buy->symbol,sell->symbol); maxprice = ask; @@ -429,7 +499,7 @@ int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,str strcpy(LP_portfolio_rel,""); LP_portfolio_relvolume = 0.; } - printf("pending.%d base buy.%s, rel sell.%s relvolume %f maxprice %.8f (%.8f %.8f)\n",LP_pendingswaps,buy->symbol,sell->symbol,sell->relvolume,maxprice,bid,ask); + printf("pending.%d base buy.%s, rel sell.%s relvolume %f maxprice %.8f (%.8f %.8f)\n",G.LP_pendingswaps,buy->symbol,sell->symbol,sell->relvolume,maxprice,bid,ask); if ( LP_pricevalid(maxprice) > 0 ) { relvolume = sell->relvolume; @@ -439,7 +509,8 @@ int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,str break; if ( LP_utxo_bestfit(sell->symbol,SATOSHIDEN * relvolume) != 0 ) { - if ( (retstr2= LP_autotrade(ctx,"127.0.0.1",-1,buy->symbol,sell->symbol,maxprice,relvolume,60,24*3600)) != 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,1)) != 0 ) { if ( (retjson2= cJSON_Parse(retstr2)) != 0 ) { @@ -482,7 +553,7 @@ 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]; }; +struct LP_portfoliotrade { double metric; char buycoin[65],sellcoin[65]; }; int32_t LP_portfolio_order(struct LP_portfoliotrade *trades,int32_t max,cJSON *array) { @@ -530,13 +601,19 @@ int32_t LP_portfolio_order(struct LP_portfoliotrade *trades,int32_t max,cJSON *a return(n); } -void prices_loop(void *ignore) +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 ) { + printf("prices_loop BTC not in LP_priceinfofind\n"); sleep(60); continue; } @@ -548,7 +625,7 @@ void prices_loop(void *ignore) { if ( (buycoin= jstr(retjson,"buycoin")) != 0 && (buy= LP_coinfind(buycoin)) != 0 && (sellcoin= jstr(retjson,"sellcoin")) != 0 && (sell= LP_coinfind(sellcoin)) != 0 && buy->inactive == 0 && sell->inactive == 0 ) { - if ( LP_portfolio_trade(ctx,&requestid,"eid,buy,sell,sell->relvolume,1) < 0 ) + if ( LP_portfolio_trade(ctx,&requestid,"eid,buy,sell,sell->relvolume,1,"portfolio") < 0 ) { array = jarray(&m,retjson,"portfolio"); if ( array != 0 && (n= LP_portfolio_order(trades,(int32_t)(sizeof(trades)/sizeof(*trades)),array)) > 0 ) @@ -559,7 +636,7 @@ void prices_loop(void *ignore) { buy = LP_coinfind(trades[i].buycoin); sell = LP_coinfind(trades[i].sellcoin); - if ( buy != 0 && sell != 0 && LP_portfolio_trade(ctx,&requestid,"eid,buy,sell,sell->relvolume,0) == 0 ) + if ( buy != 0 && sell != 0 && LP_portfolio_trade(ctx,&requestid,"eid,buy,sell,sell->relvolume,0,"portfolio") == 0 ) break; } } @@ -570,7 +647,7 @@ void prices_loop(void *ignore) } free(retstr); } - sleep(60); + sleep(30); } } diff --git a/iguana/exchanges/LP_prices.c b/iguana/exchanges/LP_prices.c index d68ae2257..7c91647aa 100644 --- a/iguana/exchanges/LP_prices.c +++ b/iguana/exchanges/LP_prices.c @@ -18,22 +18,24 @@ // marketmaker // -struct LP_orderbookentry { bits256 txid,txid2,pubkey; double price; uint64_t basesatoshis; int32_t vout,vout2,age; }; +struct LP_orderbookentry { bits256 pubkey; double price; uint64_t avesatoshis,maxsatoshis,depth; uint32_t timestamp; int32_t numutxos; char coinaddr[64]; }; -#define LP_MAXPRICEINFOS 256 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 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]; + //FILE *fps[LP_MAXPRICEINFOS]; } LP_priceinfos[LP_MAXPRICEINFOS]; int32_t LP_numpriceinfos; @@ -46,13 +48,92 @@ struct LP_cacheinfo uint32_t timestamp; } *LP_cacheinfos; -struct LP_pubkeyinfo + +float LP_pubkey_price(int32_t *numutxosp,int64_t *avesatoshisp,int64_t *maxsatoshisp,struct LP_pubkeyinfo *pubp,uint32_t baseind,uint32_t relind) { - UT_hash_handle hh; - bits256 pubkey; - double matrix[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS]; - uint32_t timestamp,istrusted,numerrors; -} *LP_pubkeyinfos; + 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_pubkeyinfo *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() + } + 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; + //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 ) + return(0); + else return(&LP_priceinfos[ind]); +} + +char *LP_priceinfostr(int32_t ind) +{ + if ( ind < 0 || ind >= LP_MAXPRICEINFOS ) + return("UNKNOWN"); + else return(LP_priceinfos[ind].symbol); +} int32_t LP_pricevalid(double price) { @@ -77,6 +158,14 @@ struct LP_priceinfo *LP_priceinfofind(char *symbol) return(0); } +int32_t LP_priceinfoind(char *symbol) +{ + struct LP_priceinfo *pp; + if ( (pp= LP_priceinfofind(symbol)) != 0 ) + return(pp->ind); + else return(-1); +} + struct LP_priceinfo *LP_priceinfoptr(int32_t *indp,char *base,char *rel) { struct LP_priceinfo *basepp,*relpp; @@ -125,6 +214,52 @@ 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_pubkeyinfo *pubp=0,*tmp; + portable_mutex_lock(&LP_pubkeymutex); + HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) + { + if ( memcmp(rmd160,pubp->rmd160,sizeof(pubp->rmd160)) == 0 ) + break; + pubp = 0; + } + portable_mutex_unlock(&LP_pubkeymutex); + return(pubp); +} + +struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr) +{ + uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkeyinfo *pubp; + HASH_FIND(hh,coin->addresses,coinaddr,strlen(coinaddr),ap); + if ( ap != 0 && bits256_nonz(ap->pubkey) == 0 ) + { + bitcoin_addr2rmd160(coin->taddr,&addrtype,rmd160,coinaddr); + if ( (pubp= LP_pubkey_rmd160find(rmd160)) != 0 ) + { + ap->pubkey = pubp->pubkey; + memcpy(ap->pubsecp,pubp->pubsecp,sizeof(ap->pubsecp)); + } + } + return(ap); +} + +struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr) +{ + uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkeyinfo *pubp; + ap = calloc(1,sizeof(*ap)); + safecopy(ap->coinaddr,coinaddr,sizeof(ap->coinaddr)); + bitcoin_addr2rmd160(coin->taddr,&addrtype,rmd160,coinaddr); + if ( (pubp= LP_pubkey_rmd160find(rmd160)) != 0 ) + { + ap->pubkey = pubp->pubkey; + memcpy(ap->pubsecp,pubp->pubsecp,sizeof(ap->pubsecp)); + } + //printf("LP_ADDRESS %s ADD.(%s)\n",coin->symbol,coinaddr); + HASH_ADD_KEYPTR(hh,coin->addresses,ap->coinaddr,strlen(ap->coinaddr),ap); + return(ap); +} + struct LP_pubkeyinfo *LP_pubkeyfind(bits256 pubkey) { struct LP_pubkeyinfo *pubp=0; @@ -136,24 +271,31 @@ struct LP_pubkeyinfo *LP_pubkeyfind(bits256 pubkey) struct LP_pubkeyinfo *LP_pubkeyadd(bits256 pubkey) { - struct LP_pubkeyinfo *pubp=0; - if ( (pubp= LP_pubkeyfind(pubkey)) == 0 ) + char str[65]; struct LP_pubkeyinfo *pubp=0; + portable_mutex_lock(&LP_pubkeymutex); + HASH_FIND(hh,LP_pubkeyinfos,&pubkey,sizeof(pubkey),pubp); + if ( pubp == 0 ) { - portable_mutex_lock(&LP_pubkeymutex); pubp = calloc(1,sizeof(*pubp)); pubp->pubkey = pubkey; + if ( bits256_cmp(G.LP_mypub25519,pubkey) == 0 ) + { + memcpy(pubp->rmd160,G.LP_myrmd160,sizeof(pubp->rmd160)); + memcpy(pubp->pubsecp,G.LP_pubsecp,sizeof(pubp->pubsecp)); + } HASH_ADD_KEYPTR(hh,LP_pubkeyinfos,&pubp->pubkey,sizeof(pubp->pubkey),pubp); - portable_mutex_unlock(&LP_pubkeymutex); - if ( (pubp= LP_pubkeyfind(pubkey)) == 0 ) - printf("pubkeyadd find error after add\n"); + HASH_FIND(hh,LP_pubkeyinfos,&pubkey,sizeof(pubkey),pubp); + if ( pubp == 0 ) + printf("pubkeyadd find %s error after add\n",bits256_str(str,pubp->pubkey)); } + portable_mutex_unlock(&LP_pubkeymutex); return(pubp); } int32_t LP_pubkey_istrusted(bits256 pubkey) { struct LP_pubkeyinfo *pubp; - if ( (pubp= LP_pubkeyfind(pubkey)) != 0 ) + if ( (pubp= LP_pubkeyadd(pubkey)) != 0 ) return(pubp->istrusted != 0); return(0); } @@ -161,7 +303,7 @@ int32_t LP_pubkey_istrusted(bits256 pubkey) char *LP_pubkey_trustset(bits256 pubkey,uint32_t trustval) { struct LP_pubkeyinfo *pubp; - if ( (pubp= LP_pubkeyfind(pubkey)) != 0 ) + if ( (pubp= LP_pubkeyadd(pubkey)) != 0 ) { pubp->istrusted = trustval; return(clonestr("{\"result\":\"success\"}")); @@ -169,9 +311,41 @@ char *LP_pubkey_trustset(bits256 pubkey,uint32_t trustval) return(clonestr("{\"error\":\"pubkey not found\"}")); } +char *LP_pubkey_trusted() +{ + struct LP_pubkeyinfo *pubp,*tmp; cJSON *array = cJSON_CreateArray(); + HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) + { + if ( pubp->istrusted != 0 ) + jaddibits256(array,pubp->pubkey); + } + return(jprint(array,1)); +} + +uint64_t LP_unspents_metric(struct iguana_info *coin,char *coinaddr) +{ + cJSON *array,*item; int32_t i,n; uint64_t metric=0,total; + LP_listunspent_both(coin->symbol,coinaddr,0); + if ( (array= LP_address_utxos(coin,coinaddr,1)) != 0 ) + { + total = 0; + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; imatrix[baseid][relid]; + price = LP_pubkey_price(&numutxos,&avesatoshis,&maxsatoshis,pubp,baseid,relid);//pubp->matrix[baseid][relid]; if ( LP_pricevalid(price) > 0 ) { item = cJSON_CreateArray(); @@ -191,6 +365,12 @@ cJSON *LP_pubkeyjson(struct LP_pubkeyinfo *pubp) } } jaddbits256(obj,"pubkey",pubp->pubkey); + init_hexbytes_noT(hexstr,pubp->rmd160,sizeof(pubp->rmd160)); + jaddstr(obj,"rmd160",hexstr); + init_hexbytes_noT(hexstr2,pubp->pubsecp,sizeof(pubp->pubsecp)); + jaddstr(obj,"pubsecp",hexstr2); + init_hexbytes_noT(sigstr,pubp->sig,pubp->siglen); + jaddstr(obj,"sig",sigstr); jaddnum(obj,"timestamp",pubp->timestamp); jadd(obj,"asks",array); if ( pubp->istrusted != 0 ) @@ -208,15 +388,26 @@ char *LP_prices() return(jprint(array,1)); } -void LP_prices_parse(cJSON *obj) +/*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; int32_t i,n,relid; char *base,*rel; double askprice; + 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 ( (timestamp= juint(obj,"timestamp")) > pubp->timestamp && (asks= jarray(&n,obj,"asks")) != 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 ) { - pubp->timestamp = timestamp; for (i=0; iind,relid,askprice); + //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); @@ -241,23 +433,30 @@ void LP_prices_parse(cJSON *obj) } } -void LP_peer_pricesquery(char *destipaddr,uint16_t destport) +void LP_peer_pricesquery(struct LP_peerinfo *peer) { char *retstr; cJSON *array; int32_t i,n; - if ( (retstr= issue_LP_getprices(destipaddr,destport)) != 0 ) + if ( strcmp(peer->ipaddr,LP_myipaddr) == 0 ) + return; + peer->needping = (uint32_t)time(NULL); + if ( (retstr= issue_LP_getprices(peer->ipaddr,peer->port)) != 0 ) { if ( (array= cJSON_Parse(retstr)) != 0 ) { if ( is_cJSON_Array(array) && (n= cJSON_GetArraySize(array)) > 0 ) { for (i=0; ineedping != 0 ) + { + //printf("%s needs ping\n",peer->ipaddr); + } +}*/ double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,int32_t vout) { @@ -271,9 +470,9 @@ double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,i ptr->price = (double)ptr->Q.destsatoshis / ptr->Q.satoshis; if ( LP_pricevalid(ptr->price) <= 0 ) ptr->price = 0.; - //printf("LP_pricecache: set %s/%s ptr->price %.8f\n",base,rel,ptr->price); + 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); @@ -358,18 +557,21 @@ int32_t LP_mypriceset(int32_t *changedp,char *base,char *rel,double price) { struct LP_priceinfo *basepp,*relpp; struct LP_pubkeyinfo *pubp; *changedp = 0; - if ( base != 0 && rel != 0 && LP_pricevalid(price) > 0 && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) + if ( base != 0 && rel != 0 && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) { - if ( fabs(basepp->myprices[relpp->ind] - price) > SMALLVAL ) + + if ( fabs(basepp->myprices[relpp->ind] - price)/price > 0.001 ) *changedp = 1; basepp->myprices[relpp->ind] = price; // ask //printf("LP_mypriceset base.%s rel.%s <- price %.8f\n",base,rel,price); //relpp->myprices[basepp->ind] = (1. / price); // bid - if ( (pubp= LP_pubkeyadd(LP_mypub25519)) != 0 ) + if ( (pubp= LP_pubkeyadd(G.LP_mypub25519)) != 0 ) { - pubp->matrix[basepp->ind][relpp->ind] = price; - //pubp->matrix[relpp->ind][basepp->ind] = (1. / price); pubp->timestamp = (uint32_t)time(NULL); + 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); } else return(-1); @@ -495,108 +697,168 @@ static int _cmp_orderbook(const void *a,const void *b) { #undef ptr_a #undef ptr_b -#define ptr_a ((struct LP_orderbookentry *)a)->basesatoshis -#define ptr_b ((struct LP_orderbookentry *)b)->basesatoshis +#define ptr_a ((struct LP_orderbookentry *)a)->maxsatoshis +#define ptr_b ((struct LP_orderbookentry *)b)->maxsatoshis + if ( ptr_b > ptr_a ) + return(-1); + else if ( ptr_b < ptr_a ) + return(1); + } + // printf("%.8f vs %.8f -> %d\n",ptr_a,ptr_b,retval); + return(retval); +#undef ptr_a +#undef ptr_b +} + +static int _revcmp_orderbook(const void *a,const void *b) +{ + int32_t retval = 0; +#define ptr_a (*(struct LP_orderbookentry **)a)->price +#define ptr_b (*(struct LP_orderbookentry **)b)->price + if ( ptr_b > ptr_a ) + retval = 1; + else if ( ptr_b < ptr_a ) + retval = -1; + else + { +#undef ptr_a +#undef ptr_b +#define ptr_a ((struct LP_orderbookentry *)a)->maxsatoshis +#define ptr_b ((struct LP_orderbookentry *)b)->maxsatoshis if ( ptr_b > ptr_a ) return(-1); else if ( ptr_b < ptr_a ) return(1); } - // printf("%.8f vs %.8f -> %d\n",ptr_a,ptr_b,retval); + // printf("%.8f vs %.8f -> %d\n",ptr_a,ptr_b,retval); return(retval); #undef ptr_a #undef ptr_b } -cJSON *LP_orderbookjson(struct LP_orderbookentry *op) +cJSON *LP_orderbookjson(char *symbol,struct LP_orderbookentry *op) { cJSON *item = cJSON_CreateObject(); if ( LP_pricevalid(op->price) > 0 ) { + jaddstr(item,"coin",symbol); + jaddstr(item,"address",op->coinaddr); jaddnum(item,"price",op->price); - jaddnum(item,"volume",dstr(op->basesatoshis)); - jaddbits256(item,"txid",op->txid); - jaddnum(item,"vout",op->vout); + jaddnum(item,"numutxos",op->numutxos); + 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",op->age); + jaddnum(item,"age",time(NULL)-op->timestamp); } return(item); } -struct LP_orderbookentry *LP_orderbookentry(char *base,char *rel,bits256 txid,int32_t vout,bits256 txid2,int32_t vout2,double price,uint64_t basesatoshis,bits256 pubkey,int32_t age) +struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,double price,int32_t numutxos,uint64_t avesatoshis,uint64_t maxsatoshis,bits256 pubkey,uint32_t timestamp,uint64_t balance) { struct LP_orderbookentry *op; if ( (op= calloc(1,sizeof(*op))) != 0 ) { - op->txid = txid; - op->vout = vout; - op->txid2 = txid2; - op->vout2 = vout2; + safecopy(op->coinaddr,address,sizeof(op->coinaddr)); op->price = price; - op->basesatoshis = basesatoshis; + op->numutxos = numutxos; + op->avesatoshis = avesatoshis; + op->maxsatoshis = maxsatoshis; op->pubkey = pubkey; - op->age = age; + op->timestamp = timestamp; + op->depth = balance; } return(op); } -int32_t LP_orderbookfind(struct LP_orderbookentry **array,int32_t num,bits256 txid,int32_t vout) +void LP_pubkeys_query() { - int32_t i; - for (i=0; ivout == vout && bits256_cmp(array[i]->txid,txid) == 0) || (array[i]->vout2 == vout && bits256_cmp(array[i]->txid2,txid) == 0) ) - return(i); - return(-1); + uint8_t zeroes[20]; bits256 zero; cJSON *reqjson; struct LP_pubkeyinfo *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) > pubp->lasttime+60 ) + { + 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(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) { - struct LP_utxoinfo *utxo,*tmp; struct LP_pubkeyinfo *pubp=0; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; uint32_t oldest; double price; int32_t baseid,relid; uint64_t basesatoshis,val,val2; + char coinaddr[64]; uint8_t zeroes[20]; struct LP_pubkeyinfo *pubp=0,*tmp; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; struct LP_address *ap; struct iguana_info *basecoin; uint32_t oldest; double price; int32_t baseid,relid,n; int64_t maxsatoshis,balance,avesatoshis; if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 ) baseid = basepp->ind; else return(num); + if ( (basecoin= LP_coinfind(base)) == 0 ) + return(-1); now = (uint32_t)time(NULL); oldest = now - duration; - HASH_ITER(hh,LP_utxoinfos[1],utxo,tmp) + memset(zeroes,0,sizeof(zeroes)); + HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) { - if ( pubp == 0 || bits256_cmp(pubp->pubkey,utxo->pubkey) != 0 ) - pubp = LP_pubkeyfind(utxo->pubkey); - if ( pubp != 0 && pubp->numerrors >= LP_MAXPUBKEY_ERRORS ) + if ( memcmp(zeroes,pubp->rmd160,sizeof(pubp->rmd160)) == 0 ) + { + //printf("skip pubp since no rmd160\n"); + continue; + } + if ( pubp->timestamp < oldest ) continue; - //char str[65],str2[65]; printf("check utxo.%s/v%d from %s\n",bits256_str(str,utxo->payment.txid),utxo->payment.vout,bits256_str(str2,utxo->pubkey)); - if ( strcmp(base,utxo->coin) == 0 && LP_isavailable(utxo) > 0 && pubp != 0 && (price= pubp->matrix[baseid][relid]) > SMALLVAL && pubp->timestamp > oldest && pubp->timestamp <= now ) + bitcoin_address(coinaddr,basecoin->taddr,basecoin->pubtype,pubp->rmd160,sizeof(pubp->rmd160)); + avesatoshis = maxsatoshis = n = 0; + ap = 0; + if ( (price= LP_pubkey_price(&n,&avesatoshis,&maxsatoshis,pubp,baseid,relid)) > SMALLVAL ) //pubp->matrix[baseid][relid]) > SMALLVAL )//&& pubp->timestamps[baseid][relid] >= oldest ) { - if ( LP_orderbookfind(*arrayp,cachednum,utxo->payment.txid,utxo->payment.vout) < 0 ) + balance = avesatoshis * n; + //if ( (ap= LP_addressfind(basecoin,coinaddr)) != 0 ) { - if ( LP_iseligible(&val,&val2,utxo->iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,utxo->deposit.txid,utxo->deposit.vout) == 0 ) - continue; + //n = LP_address_minmax(&balance,&minsatoshis,&maxsatoshis,ap); if ( polarity > 0 ) - basesatoshis = utxo->S.satoshis; - else basesatoshis = utxo->S.satoshis * price; - //char str[65]; printf("found utxo not in orderbook %s/v%d %.8f %.8f\n",bits256_str(str,utxo->payment.txid),utxo->payment.vout,dstr(basesatoshis),polarity > 0 ? price : 1./price); - if ( (op= LP_orderbookentry(base,rel,utxo->payment.txid,utxo->payment.vout,utxo->deposit.txid,utxo->deposit.vout,polarity > 0 ? price : 1./price,basesatoshis,utxo->pubkey,now - pubp->timestamp)) != 0 ) { - *arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1)); - (*arrayp)[num++] = op; - if ( LP_ismine(utxo) > 0 && utxo->T.lasttime == 0 ) - LP_utxo_clientpublish(utxo); + balance *= 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,avesatoshis,maxsatoshis,pubp->pubkey,pubp->timestamp,balance)) != 0 ) + { + *arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1)); + (*arrayp)[num++] = op; } } + //printf("pubp.(%s) %.8f %p\n",coinaddr,price,ap); } return(num); } char *LP_orderbook(char *base,char *rel,int32_t duration) { - uint32_t now,i; struct LP_priceinfo *basepp=0,*relpp=0; struct LP_orderbookentry **bids = 0,**asks = 0; cJSON *retjson,*array; int32_t numbids=0,numasks=0,cachenumbids,cachenumasks,baseid,relid; + 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; + basecoin = LP_coinfind(base); + relcoin = LP_coinfind(rel); + if ( basecoin == 0 || relcoin == 0 ) + return(clonestr("{\"error\":\"base or rel not added\"}")); if ( (basepp= LP_priceinfofind(base)) == 0 || (relpp= LP_priceinfofind(rel)) == 0 ) return(clonestr("{\"error\":\"base or rel not added\"}")); if ( duration <= 0 ) + { + if ( duration < 0 ) + suppress_prefetch = 1; duration = LP_ORDERBOOK_DURATION; + } + LP_pubkeys_query(); baseid = basepp->ind; relid = relpp->ind; now = (uint32_t)time(NULL); + basecoin->obooktime = now; + relcoin->obooktime = now; cachenumbids = numbids, cachenumasks = numasks; //printf("start cache.(%d %d) numbids.%d numasks.%d\n",cachenumbids,cachenumasks,numbids,numasks); numasks = LP_orderbook_utxoentries(now,1,base,rel,&asks,numasks,cachenumasks,duration); @@ -604,32 +866,70 @@ char *LP_orderbook(char *base,char *rel,int32_t duration) retjson = cJSON_CreateObject(); array = cJSON_CreateArray(); if ( numbids > 1 ) - qsort(bids,numbids,sizeof(*bids),_cmp_orderbook); + { + qsort(bids,numbids,sizeof(*bids),_revcmp_orderbook); + depth = 0; + for (i=0; idepth; + bids[i]->depth = depth; + } + } if ( numasks > 1 ) { - //for (i=0; iprice); - //printf(" -> "); qsort(asks,numasks,sizeof(*asks),_cmp_orderbook); - //for (i=0; iprice); - //printf("sorted asks.%d\n",numasks); + depth = 0; + for (i=0; idepth; + asks[i]->depth = depth; + } } - for (i=0; inumutxos == 0 ) + { + //printf("bid ping %s %s\n",rel,bids[i]->coinaddr); + LP_address(relcoin,bids[i]->coinaddr); + if ( 0 && relcoin->electrum == 0 ) + { + LP_listunspent_issue(rel,bids[i]->coinaddr,0); + //else if ( (tmpjson= LP_listunspent(rel,bids[i]->coinaddr)) != 0 ) + // free_json(tmpjson); + LP_listunspent_query(rel,bids[i]->coinaddr); + } + n++; + } free(bids[i]); bids[i] = 0; } + if ( n > 0 && relcoin->lastmonitor > 3600 ) + relcoin->lastmonitor -= 3600; jadd(retjson,"bids",array); jaddnum(retjson,"numbids",numbids); array = cJSON_CreateArray(); - for (i=0; inumutxos == 0 ) + { + //printf("ask ping %s %s\n",base,asks[i]->coinaddr); + LP_address(basecoin,asks[i]->coinaddr); + if ( 0 && basecoin->electrum == 0 ) + { + LP_listunspent_issue(base,asks[i]->coinaddr,0); + //else if ( (tmpjson= LP_listunspent(base,asks[i]->coinaddr)) != 0 ) + // free_json(tmpjson); + LP_listunspent_query(base,asks[i]->coinaddr); + } + n++; + } free(asks[i]); asks[i] = 0; } + if ( n > 0 && basecoin->lastmonitor > 3600 ) + basecoin->lastmonitor -= 3600; jadd(retjson,"asks",array); jaddnum(retjson,"numasks",numasks); jaddstr(retjson,"base",base); @@ -642,28 +942,39 @@ char *LP_orderbook(char *base,char *rel,int32_t duration) return(jprint(retjson,1)); } -char *LP_pricestr(char *base,char *rel,double origprice) +uint64_t LP_KMDvalue(struct iguana_info *coin,uint64_t balance) { - cJSON *retjson; double price = 0.; - if ( base != 0 && base[0] != 0 && rel != 0 && rel[0] != 0 ) + cJSON *bids,*asks,*orderbook,*item; double bid=0,ask=0,price = 0.; int32_t numasks,numbids; char *retstr; uint64_t KMDvalue=0; + if ( balance != 0 ) { - price = LP_price(base,rel); - if ( origprice > SMALLVAL && origprice < price ) - price = origprice; + if ( strcmp(coin->symbol,"KMD") == 0 ) + KMDvalue = balance; + else if ( (retstr= LP_orderbook(coin->symbol,"KMD",-1)) != 0 ) + { + 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); + } + KMDvalue = price * balance; + free_json(orderbook); + } + free(retstr); + } } - if ( LP_pricevalid(price) > 0 ) - { - retjson = cJSON_CreateObject(); - jaddstr(retjson,"result","success"); - jaddstr(retjson,"method","postprice"); - jaddbits256(retjson,"pubkey",LP_mypub25519); - jaddstr(retjson,"base",base); - jaddstr(retjson,"rel",rel); - jaddnum(retjson,"price",price); - jadd(retjson,"theoretical",LP_priceinfomatrix(0)); - jadd(retjson,"quotes",LP_priceinfomatrix(1)); - return(jprint(retjson,1)); - } else return(clonestr("{\"error\":\"cant find baserel pair\"}")); + return(KMDvalue); } void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32]) @@ -799,16 +1110,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) { struct LP_priceinfo *basepp,*relpp; uint32_t now; uint64_t price64; struct LP_pubkeyinfo *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 ) { @@ -816,12 +1127,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 ) { @@ -829,21 +1140,25 @@ 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() % 100) == 0 && fabs(pubp->matrix[basepp->ind][relpp->ind] - price) > SMALLVAL ) + 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); + pubp->timestamp = (uint32_t)time(NULL); + 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->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); } - pubp->timestamp = (uint32_t)time(NULL); - } else printf("error creating pubkey entry\n"); + } else printf("error finding pubkey entry %s, ok if rare\n",bits256_str(str,pubkey)); } - else if ( (rand() % 100) == 0 ) - printf("error finding %s/%s %.8f\n",base,rel,price); + //else if ( (rand() % 100) == 0 ) + // printf("error finding %s/%s %.8f\n",base,rel,price); } diff --git a/iguana/exchanges/LP_remember.c b/iguana/exchanges/LP_remember.c index 9e25a6241..f5ea3229a 100644 --- a/iguana/exchanges/LP_remember.c +++ b/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,&swap->bobcoin,coinaddr,rawtx->txbytes,rawtx->I.datalen); + 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,"{\"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->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); @@ -152,7 +158,10 @@ void basilisk_dontforget(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx fprintf(fp,",\"otherfee\":\"%s\"",bits256_str(str,swap->otherfee.I.actualtxid)); if ( bits256_nonz(swap->myfee.I.actualtxid) != 0 ) fprintf(fp,",\"myfee\":\"%s\"",bits256_str(str,swap->myfee.I.actualtxid)); - fprintf(fp,",\"dest33\":\""); + fprintf(fp,",\"other33\":\""); + for (i=0; i<33; i++) + fprintf(fp,"%02x",swap->persistent_other33[i]); + fprintf(fp,"\",\"dest33\":\""); for (i=0; i<33; i++) fprintf(fp,"%02x",swap->persistent_pubkey33[i]); fprintf(fp,"\"}\n"); @@ -244,30 +253,35 @@ bits256 basilisk_swap_privBn_extract(bits256 *bobrefundp,char *bobcoin,bits256 b return(privBn); } -bits256 basilisk_swap_spendupdate(char *symbol,int32_t *sentflags,bits256 *txids,int32_t utxoind,int32_t alicespent,int32_t bobspent,int32_t vout,char *aliceaddr,char *bobaddr) +bits256 basilisk_swap_spendupdate(int32_t iambob,char *symbol,char *spentaddr,int32_t *sentflags,bits256 *txids,int32_t utxoind,int32_t alicespent,int32_t bobspent,int32_t vout,char *aliceaddr,char *bobaddr,char *Adest,char *dest) { - bits256 spendtxid,txid; char destaddr[64]; + bits256 spendtxid,txid; char destaddr[64],str[65]; struct iguana_info *coin; cJSON *histobj; + if ( (coin= LP_coinfind(symbol)) != 0 && coin->electrum != 0 ) + { + if ( (histobj= electrum_address_gethistory(symbol,coin->electrum,&histobj,spentaddr)) != 0 ) + { + //printf("processed history.(%s)\n",jprint(histobj,0)); + free_json(histobj); + } + } txid = txids[utxoind]; memset(&spendtxid,0,sizeof(spendtxid)); - /*if ( aliceaddr != 0 ) - printf("aliceaddr.(%s)\n",aliceaddr); - if ( bobaddr != 0 ) - printf("bobaddr.(%s)\n",bobaddr);*/ - if ( bits256_nonz(txid) != 0 ) + if ( bits256_nonz(txid) != 0 )//&& sentflags[utxoind] != 0 ) { - //char str[65]; + destaddr[0] = 0; spendtxid = LP_swap_spendtxid(symbol,destaddr,txid,vout); if ( bits256_nonz(spendtxid) != 0 ) { sentflags[utxoind] = 1; - if ( aliceaddr != 0 && strcmp(destaddr,aliceaddr) == 0 ) + //printf("utxoind.%d Alice.(%s %s) Bob.(%s %s) vs destaddr.(%s)\n",utxoind,aliceaddr,Adest,bobaddr,dest,destaddr); + if ( aliceaddr != 0 && (strcmp(destaddr,aliceaddr) == 0 || strcmp(Adest,destaddr) == 0) ) { //printf("ALICE spent.(%s) -> %s\n",bits256_str(str,txid),destaddr); sentflags[alicespent] = 1; sentflags[bobspent] = 0; txids[alicespent] = spendtxid; } - else if ( bobaddr != 0 && strcmp(destaddr,bobaddr) == 0 ) + else if ( bobaddr != 0 && (strcmp(destaddr,bobaddr) == 0 || strcmp(dest,destaddr) == 0) ) { //printf("BOB spent.(%s) -> %s\n",bits256_str(str,txid),destaddr); sentflags[bobspent] = 1; @@ -276,39 +290,25 @@ bits256 basilisk_swap_spendupdate(char *symbol,int32_t *sentflags,bits256 *txids } else { - //printf("OTHER dest spent.(%s) -> %s\n",bits256_str(str,txid),destaddr); - if ( aliceaddr != 0 ) + printf("OTHER dest spent.(%s) -> %s\n",bits256_str(str,txid),destaddr); + if ( iambob == 0 ) { sentflags[bobspent] = 1; sentflags[alicespent] = 0; txids[bobspent] = spendtxid; } - else if ( bobaddr != 0 ) + else { sentflags[alicespent] = 1; sentflags[bobspent] = 0; txids[alicespent] = spendtxid; } } - } + } //else printf("no spend of %s/v%d detected\n",bits256_str(str,txid),vout); } 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 ) @@ -330,7 +330,6 @@ int32_t basilisk_isbobcoin(int32_t iambob,int32_t ind) } } -// add blocktrail presence requirement for BTC int32_t basilisk_swap_isfinished(int32_t iambob,bits256 *txids,int32_t *sentflags,bits256 paymentspent,bits256 Apaymentspent,bits256 depositspent) { int32_t i,n = 0; @@ -339,19 +338,19 @@ int32_t basilisk_swap_isfinished(int32_t iambob,bits256 *txids,int32_t *sentflag n++; if ( n == 0 ) { - printf("if nothing sent, it is finished\n"); + //printf("if nothing sent, it is finished\n"); return(1); } if ( iambob != 0 ) { if ( bits256_nonz(txids[BASILISK_BOBDEPOSIT]) == 0 && sentflags[BASILISK_BOBDEPOSIT] == 0 ) return(1); - else if ( bits256_nonz(txids[BASILISK_BOBPAYMENT]) == 0 && sentflags[BASILISK_BOBPAYMENT] == 0 ) + else if ( bits256_nonz(txids[BASILISK_BOBPAYMENT]) == 0 || sentflags[BASILISK_BOBPAYMENT] == 0 ) { if ( bits256_nonz(depositspent) != 0 ) return(1); } - else if ( bits256_nonz(paymentspent) != 0 ) + else if ( bits256_nonz(Apaymentspent) != 0 ) return(1); } else @@ -396,99 +395,216 @@ uint32_t LP_extract(uint32_t requestid,uint32_t quoteid,char *rootfname,char *fi return(t); } -cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requestid,uint32_t quoteid) +void LP_totals_update(int32_t iambob,char *alicecoin,char *bobcoin,int64_t *KMDtotals,int64_t *BTCtotals,int32_t *sentflags,int64_t *values) // update to handle all coins { - static void *ctx; - FILE *fp; int32_t sentflags[sizeof(txnames)/sizeof(*txnames)],i,n,j,Predeemlen,Dredeemlen,len,needflag,secretstart,redeemlen,addflag,origfinishedflag = 0,finishedflag = 0,iambob = -1; int64_t srcamount,destamount=0,value,values[sizeof(txnames)/sizeof(*txnames)]; uint8_t secretAm[20],secretAm256[32],secretBn[20],secretBn256[32],pubkey33[33],Predeemscript[1024],Dredeemscript[1024],redeemscript[1024],userdata[1024]; uint32_t plocktime,dlocktime,expiration=0,r,q,state,otherstate; char *secretstr,*srcstr,*deststr,str[65],src[64],dest[64],fname[512],*fstr,*dest33,*rstr,*symbol,*txname,*Adest,*Bdest,*AAdest,*ABdest,destaddr[64],Adestaddr[64],alicepaymentaddr[64],bobpaymentaddr[64],bobdepositaddr[64],alicecoin[64],bobcoin[64],*txbytes[sizeof(txnames)/sizeof(*txnames)]; long fsize; cJSON *txobj,*item,*sentobj,*array; bits256 checktxid,txid,pubA0,pubB0,pubB1,privAm,privBn,paymentspent,Apaymentspent,depositspent,zero,privkey,rev,myprivs[2],txids[sizeof(txnames)/sizeof(*txnames)],signedtxid; struct iguana_info *bob=0,*alice=0; uint64_t Atxfee=0,Btxfee=0; - if ( ctx == 0 ) - ctx = bitcoin_ctx(); - bobpaymentaddr[0] = bobdepositaddr[0] = alicepaymentaddr[0] = 0; - memset(Predeemscript,0,sizeof(Predeemscript)); - memset(Dredeemscript,0,sizeof(Dredeemscript)); - Predeemlen = Dredeemlen = 0; - memset(values,0,sizeof(values)); - memset(txids,0,sizeof(txids)); - memset(secretAm,0,sizeof(secretAm)); - memset(secretAm256,0,sizeof(secretAm256)); - memset(secretBn,0,sizeof(secretBn)); - memset(secretBn256,0,sizeof(secretBn256)); - memset(pubkey33,0,sizeof(pubkey33)); - memset(txbytes,0,sizeof(txbytes)); - memset(sentflags,0,sizeof(sentflags)); - memset(myprivs,0,sizeof(myprivs)); - Apaymentspent = paymentspent = depositspent = rev = zero = pubA0 = pubB0 = pubB1 = privAm = privBn = myprivs[0]; - plocktime = dlocktime = 0; - src[0] = dest[0] = bobcoin[0] = alicecoin[0] = 0; + values[BASILISK_OTHERFEE] = 0; + if ( iambob == 0 ) + { + if ( strcmp(alicecoin,"BTC") == 0 ) + { + BTCtotals[BASILISK_ALICEPAYMENT] -= values[BASILISK_ALICEPAYMENT] * sentflags[BASILISK_ALICEPAYMENT]; + BTCtotals[BASILISK_ALICERECLAIM] += values[BASILISK_ALICEPAYMENT] * sentflags[BASILISK_ALICERECLAIM]; + BTCtotals[BASILISK_MYFEE] -= values[BASILISK_MYFEE] * sentflags[BASILISK_MYFEE]; + } + else if ( strcmp(alicecoin,"KMD") == 0 ) + { + KMDtotals[BASILISK_ALICEPAYMENT] -= values[BASILISK_ALICEPAYMENT] * sentflags[BASILISK_ALICEPAYMENT]; + KMDtotals[BASILISK_ALICERECLAIM] += values[BASILISK_ALICEPAYMENT] * sentflags[BASILISK_ALICERECLAIM]; + KMDtotals[BASILISK_MYFEE] -= values[BASILISK_MYFEE] * sentflags[BASILISK_MYFEE]; + } + if ( strcmp(bobcoin,"KMD") == 0 ) + { + KMDtotals[BASILISK_ALICESPEND] += values[BASILISK_BOBPAYMENT] * sentflags[BASILISK_ALICESPEND]; + KMDtotals[BASILISK_ALICECLAIM] += values[BASILISK_BOBDEPOSIT] * sentflags[BASILISK_ALICECLAIM]; + } + else if ( strcmp(bobcoin,"BTC") == 0 ) + { + BTCtotals[BASILISK_ALICESPEND] += values[BASILISK_BOBPAYMENT] * sentflags[BASILISK_ALICESPEND]; + BTCtotals[BASILISK_ALICECLAIM] += values[BASILISK_BOBDEPOSIT] * sentflags[BASILISK_ALICECLAIM]; + } + } + else + { + if ( strcmp(bobcoin,"BTC") == 0 ) + { + BTCtotals[BASILISK_BOBPAYMENT] -= values[BASILISK_BOBPAYMENT] * sentflags[BASILISK_BOBPAYMENT]; + BTCtotals[BASILISK_BOBDEPOSIT] -= values[BASILISK_BOBDEPOSIT] * sentflags[BASILISK_BOBDEPOSIT]; + BTCtotals[BASILISK_BOBREFUND] += values[BASILISK_BOBREFUND] * sentflags[BASILISK_BOBREFUND]; + BTCtotals[BASILISK_BOBRECLAIM] += values[BASILISK_BOBRECLAIM] * sentflags[BASILISK_BOBRECLAIM]; + BTCtotals[BASILISK_MYFEE] -= values[BASILISK_MYFEE] * sentflags[BASILISK_MYFEE]; + } + else if ( strcmp(bobcoin,"KMD") == 0 ) + { + KMDtotals[BASILISK_BOBPAYMENT] -= values[BASILISK_BOBPAYMENT] * sentflags[BASILISK_BOBPAYMENT]; + KMDtotals[BASILISK_BOBDEPOSIT] -= values[BASILISK_BOBDEPOSIT] * sentflags[BASILISK_BOBDEPOSIT]; + KMDtotals[BASILISK_BOBREFUND] += values[BASILISK_BOBDEPOSIT] * sentflags[BASILISK_BOBREFUND]; + KMDtotals[BASILISK_BOBRECLAIM] += values[BASILISK_BOBPAYMENT] * sentflags[BASILISK_BOBRECLAIM]; + KMDtotals[BASILISK_MYFEE] -= values[BASILISK_MYFEE] * sentflags[BASILISK_MYFEE]; + } + if ( strcmp(alicecoin,"KMD") == 0 ) + { + KMDtotals[BASILISK_BOBSPEND] += values[BASILISK_BOBSPEND] * sentflags[BASILISK_BOBSPEND]; + } + else if ( strcmp(alicecoin,"BTC") == 0 ) + { + BTCtotals[BASILISK_BOBSPEND] += values[BASILISK_ALICEPAYMENT] * sentflags[BASILISK_BOBSPEND]; + } + } +} + +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)); + jaddstr(item,"alice",rswap->dest); + jaddnum(item,"destamount",dstr(rswap->destamount)); + jaddnum(item,"alicetxfee",dstr(rswap->Atxfee)); + jadd64bits(item,"aliceid",rswap->aliceid); + array = cJSON_CreateArray(); + for (i=0; isentflags[i] != 0 ) + jaddistr(array,txnames[i]); + if ( rswap->txbytes[i] != 0 ) + free(rswap->txbytes[i]); + } + jadd(item,"sentflags",array); + array = cJSON_CreateArray(); + for (i=0; ivalues[i])); + 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]); + jaddbits256(item,"bobpayment",rswap->txids[BASILISK_BOBPAYMENT]); + jaddbits256(item,"paymentspent",rswap->paymentspent); + jaddbits256(item,"Apaymentspent",rswap->Apaymentspent); + jaddbits256(item,"depositspent",rswap->depositspent); + return(item); +} + +int32_t LP_rswap_init(struct LP_swap_remember *rswap,uint32_t requestid,uint32_t quoteid) +{ + char fname[1024],*fstr,*secretstr,*srcstr,*deststr,*dest33,*txname; long fsize; cJSON *item,*txobj,*array; bits256 privkey; struct iguana_info *coin; uint32_t r,q; int32_t i,j,n; uint8_t other33[33]; + memset(rswap,0,sizeof(*rswap)); + rswap->requestid = requestid; + rswap->quoteid = quoteid; sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname); if ( (fstr= OS_filestr(&fsize,fname)) != 0 ) { if ( (item= cJSON_Parse(fstr)) != 0 ) { - iambob = jint(item,"iambob"); + 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(secretAm,20,secretstr); + decode_hex(rswap->secretAm,20,secretstr); if ( (secretstr= jstr(item,"secretAm256")) != 0 && strlen(secretstr) == 64 ) - decode_hex(secretAm256,32,secretstr); + decode_hex(rswap->secretAm256,32,secretstr); if ( (secretstr= jstr(item,"secretBn")) != 0 && strlen(secretstr) == 40 ) - decode_hex(secretBn,20,secretstr); + decode_hex(rswap->secretBn,20,secretstr); if ( (secretstr= jstr(item,"secretBn256")) != 0 && strlen(secretstr) == 64 ) - decode_hex(secretBn256,32,secretstr); + decode_hex(rswap->secretBn256,32,secretstr); if ( (srcstr= jstr(item,"src")) != 0 ) - safecopy(src,srcstr,sizeof(src)); + safecopy(rswap->src,srcstr,sizeof(rswap->src)); if ( (deststr= jstr(item,"dest")) != 0 ) - safecopy(dest,deststr,sizeof(dest)); + safecopy(rswap->dest,deststr,sizeof(rswap->dest)); if ( (dest33= jstr(item,"dest33")) != 0 && strlen(dest33) == 66 ) { - decode_hex(pubkey33,33,dest33); + decode_hex(rswap->pubkey33,33,dest33); + if ( rswap->iambob != 0 && (coin= LP_coinfind(rswap->src)) != 0 ) + bitcoin_address(rswap->destaddr,coin->taddr,coin->pubtype,rswap->pubkey33,33); + else if ( rswap->iambob == 0 && (coin= LP_coinfind(rswap->dest)) != 0 ) + bitcoin_address(rswap->Adestaddr,coin->taddr,coin->pubtype,rswap->pubkey33,33); //for (i=0; i<33; i++) // printf("%02x",pubkey33[i]); //printf(" <- %s dest33\n",dest33); } - if ( (plocktime= juint(item,"plocktime")) == 0 ) - plocktime = LP_extract(requestid,quoteid,fname,"plocktime"); - if ( (dlocktime= juint(item,"dlocktime")) == 0 ) - dlocktime = LP_extract(requestid,quoteid,fname,"dlocktime"); + if ( (dest33= jstr(item,"other33")) != 0 && strlen(dest33) == 66 ) + { + decode_hex(other33,33,dest33); + for (i=0; i<33; i++) + if ( other33[i] != 0 ) + break; + if ( i < 33 ) + memcpy(rswap->other33,other33,33); + if ( rswap->iambob != 0 && (coin= LP_coinfind(rswap->dest)) != 0 ) + bitcoin_address(rswap->Adestaddr,coin->taddr,coin->pubtype,rswap->other33,33); + else if ( rswap->iambob == 0 && (coin= LP_coinfind(rswap->src)) != 0 ) + bitcoin_address(rswap->destaddr,coin->taddr,coin->pubtype,rswap->other33,33); + //printf("(%s, %s) <- %s other33\n",rswap->destaddr,rswap->Adestaddr,dest33); + } + if ( (rswap->plocktime= juint(item,"plocktime")) == 0 ) + rswap->plocktime = LP_extract(requestid,quoteid,fname,"plocktime"); + if ( (rswap->dlocktime= juint(item,"dlocktime")) == 0 ) + rswap->dlocktime = LP_extract(requestid,quoteid,fname,"dlocktime"); r = juint(item,"requestid"); q = juint(item,"quoteid"); - Atxfee = j64bits(item,"Atxfee"); - Btxfee = j64bits(item,"Btxfee"); - pubA0 = jbits256(item,"pubA0"); - pubB0 = jbits256(item,"pubB0"); - pubB1 = jbits256(item,"pubB1"); + rswap->Atxfee = j64bits(item,"Atxfee"); + rswap->Btxfee = j64bits(item,"Btxfee"); + rswap->pubA0 = jbits256(item,"pubA0"); + rswap->pubB0 = jbits256(item,"pubB0"); + rswap->pubB1 = jbits256(item,"pubB1"); privkey = jbits256(item,"myprivs0"); if ( bits256_nonz(privkey) != 0 ) - myprivs[0] = privkey; + rswap->myprivs[0] = privkey; privkey = jbits256(item,"myprivs1"); if ( bits256_nonz(privkey) != 0 ) - myprivs[1] = privkey; + rswap->myprivs[1] = privkey; privkey = jbits256(item,"privAm"); if ( bits256_nonz(privkey) != 0 ) { - privAm = privkey; + rswap->privAm = privkey; //printf("set privAm <- %s\n",bits256_str(str,privAm)); } privkey = jbits256(item,"privBn"); if ( bits256_nonz(privkey) != 0 ) { - privBn = privkey; + rswap->privBn = privkey; //printf("set privBn <- %s\n",bits256_str(str,privBn)); } - expiration = juint(item,"expiration"); - state = jint(item,"state"); - otherstate = jint(item,"otherstate"); - srcamount = SATOSHIDEN * jdouble(item,"srcamount"); - destamount = SATOSHIDEN * jdouble(item,"destamount"); - txids[BASILISK_BOBDEPOSIT] = jbits256(item,"Bdeposit"); - txids[BASILISK_BOBREFUND] = jbits256(item,"Brefund"); - txids[BASILISK_ALICECLAIM] = jbits256(item,"Aclaim"); - txids[BASILISK_BOBPAYMENT] = jbits256(item,"Bpayment"); - txids[BASILISK_ALICESPEND] = jbits256(item,"Aspend"); - txids[BASILISK_BOBRECLAIM] = jbits256(item,"Breclaim"); - txids[BASILISK_ALICEPAYMENT] = jbits256(item,"Apayment"); - txids[BASILISK_BOBSPEND] = jbits256(item,"Bspend"); - txids[BASILISK_ALICERECLAIM] = jbits256(item,"Areclaim"); - txids[BASILISK_MYFEE] = jbits256(item,"myfee"); - txids[BASILISK_OTHERFEE] = jbits256(item,"otherfee"); + rswap->expiration = juint(item,"expiration"); + rswap->state = jint(item,"state"); + rswap->otherstate = jint(item,"otherstate"); + rswap->srcamount = SATOSHIDEN * jdouble(item,"srcamount"); + rswap->destamount = SATOSHIDEN * jdouble(item,"destamount"); + rswap->txids[BASILISK_BOBDEPOSIT] = jbits256(item,"Bdeposit"); + rswap->txids[BASILISK_BOBREFUND] = jbits256(item,"Brefund"); + rswap->txids[BASILISK_ALICECLAIM] = jbits256(item,"Aclaim"); + rswap->txids[BASILISK_BOBPAYMENT] = jbits256(item,"Bpayment"); + rswap->txids[BASILISK_ALICESPEND] = jbits256(item,"Aspend"); + rswap->txids[BASILISK_BOBRECLAIM] = jbits256(item,"Breclaim"); + rswap->txids[BASILISK_ALICEPAYMENT] = jbits256(item,"Apayment"); + rswap->txids[BASILISK_BOBSPEND] = jbits256(item,"Bspend"); + rswap->txids[BASILISK_ALICERECLAIM] = jbits256(item,"Areclaim"); + rswap->txids[BASILISK_MYFEE] = jbits256(item,"myfee"); + rswap->txids[BASILISK_OTHERFEE] = jbits256(item,"otherfee"); free_json(item); } free(fstr); @@ -499,12 +615,12 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti //printf("%s -> (%s)\n",fname,fstr); if ( (txobj= cJSON_Parse(fstr)) != 0 ) { - paymentspent = jbits256(txobj,"paymentspent"); - Apaymentspent = jbits256(txobj,"Apaymentspent"); - depositspent = jbits256(txobj,"depositspent"); + rswap->paymentspent = jbits256(txobj,"paymentspent"); + rswap->Apaymentspent = jbits256(txobj,"Apaymentspent"); + rswap->depositspent = jbits256(txobj,"depositspent"); if ( (array= jarray(&n,txobj,"values")) != 0 ) for (i=0; ivalues[i] = SATOSHIDEN * jdouble(jitem(array,i),0); if ( (array= jarray(&n,txobj,"sentflags")) != 0 ) { for (i=0; isentflags[j] = 1; //printf("finished.%s\n",txnames[j]); break; } @@ -522,61 +638,120 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti } } } - origfinishedflag = finishedflag = 1; + rswap->origfinishedflag = basilisk_swap_isfinished(rswap->iambob,rswap->txids,rswap->sentflags,rswap->paymentspent,rswap->Apaymentspent,rswap->depositspent); + rswap->finishedflag = rswap->origfinishedflag; + free(fstr); + } + return(rswap->iambob); +} + +int32_t _LP_refht_update(struct iguana_info *coin,bits256 txid,int32_t refht) +{ + refht -= 9; + if ( refht > 10 && (coin->firstrefht == 0 || refht < coin->firstrefht) ) + { + char str[65]; printf(">>>>>>>>. 1st refht %s %s <- %d, scan %d %d\n",coin->symbol,bits256_str(str,txid),refht,coin->firstscanht,coin->lastscanht); + if ( coin->firstscanht == 0 || refht < coin->firstscanht ) + coin->firstscanht = coin->lastscanht = refht; + coin->firstrefht = refht; + return(1); + } + return(0); +} + +int32_t LP_refht_update(char *symbol,bits256 txid) +{ + int32_t refht; struct iguana_info *coin; + if ( (coin= LP_coinfind(symbol)) != 0 && coin->electrum == 0 ) + { + if ( (refht= LP_txheight(coin,txid)) > 0 && refht > 0 ) + return(_LP_refht_update(coin,txid,refht)); + } + return(0); +} + +int32_t LP_swap_load(struct LP_swap_remember *rswap) +{ + int32_t i,needflag,addflag; long fsize; char fname[1024],*fstr,*symbol,*rstr; cJSON *txobj,*sentobj,*fileobj; bits256 txid,checktxid; uint64_t value; + rswap->iambob = -1; + sprintf(fname,"%s/SWAPS/%u-%u.finished",GLOBAL_DBDIR,rswap->requestid,rswap->quoteid), OS_compatible_path(fname); + if ( (fstr= OS_filestr(&fsize,fname)) != 0 ) + { + if ( (fileobj= cJSON_Parse(fstr)) != 0 ) + { + rswap->finishtime = juint(fileobj,"finishtime"); + rswap->origfinishedflag = rswap->finishedflag = 1; + free_json(fileobj); + } free(fstr); } - if ( iambob < 0 ) - return(0); - item = cJSON_CreateObject(); - array = cJSON_CreateArray(); for (i=0; irequestid,rswap->quoteid,txnames[i]), OS_compatible_path(fname); if ( (fstr= OS_filestr(&fsize,fname)) != 0 ) { - if ( 0 && finishedflag == 0 ) + if ( 0 && rswap->finishedflag == 0 ) printf("%s\n",fname); //printf("%s -> (%s)\n",fname,fstr); if ( (txobj= cJSON_Parse(fstr)) != 0 ) { //printf("TXOBJ.(%s)\n",jprint(txobj,0)); - iambob = jint(txobj,"iambob"); + if ( jobj(txobj,"iambob") != 0 ) + rswap->iambob = jint(txobj,"iambob"); txid = jbits256(txobj,"txid"); if ( bits256_nonz(txid) == 0 ) continue; - txids[i] = txid; + rswap->txids[i] = txid; if ( jstr(txobj,"Apayment") != 0 ) - strcpy(alicepaymentaddr,jstr(txobj,"Apayment")); + safecopy(rswap->alicepaymentaddr,jstr(txobj,"Apayment"),sizeof(rswap->alicepaymentaddr)); if ( jstr(txobj,"Bpayment") != 0 ) - strcpy(bobpaymentaddr,jstr(txobj,"Bpayment")); + safecopy(rswap->bobpaymentaddr,jstr(txobj,"Bpayment"),sizeof(rswap->bobpaymentaddr)); if ( jstr(txobj,"Bdeposit") != 0 ) - strcpy(bobdepositaddr,jstr(txobj,"Bdeposit")); + safecopy(rswap->bobdepositaddr,jstr(txobj,"Bdeposit"),sizeof(rswap->bobdepositaddr)); if ( jobj(txobj,"tx") != 0 ) { - txbytes[i] = clonestr(jstr(txobj,"tx")); + rswap->txbytes[i] = clonestr(jstr(txobj,"tx")); //printf("[%s] TX.(%s)\n",txnames[i],txbytes[i]); } - if ( strcmp(txnames[i],"bobpayment") == 0 && (rstr= jstr(txobj,"redeem")) != 0 && (Predeemlen= is_hexstr(rstr,0)) > 0 ) + if ( strcmp(txnames[i],"bobpayment") == 0 && (rstr= jstr(txobj,"redeem")) != 0 && (rswap->Predeemlen= is_hexstr(rstr,0)) > 0 ) + { + rswap->Predeemlen >>= 1; + decode_hex(rswap->Predeemscript,rswap->Predeemlen,rstr); + } + else if ( strcmp(txnames[i],"bobdeposit") == 0 && (rstr= jstr(txobj,"redeem")) != 0 && (rswap->Dredeemlen= is_hexstr(rstr,0)) > 0 ) { - Predeemlen >>= 1; - decode_hex(Predeemscript,Predeemlen,rstr); + rswap->Dredeemlen >>= 1; + decode_hex(rswap->Dredeemscript,rswap->Dredeemlen,rstr); } - else if ( strcmp(txnames[i],"bobdeposit") == 0 && (rstr= jstr(txobj,"redeem")) != 0 && (Dredeemlen= is_hexstr(rstr,0)) > 0 ) + rswap->values[i] = value = LP_value_extract(txobj,1); + if ( (symbol= jstr(txobj,"src")) != 0 ) { - Dredeemlen >>= 1; - decode_hex(Dredeemscript,Dredeemlen,rstr); + safecopy(rswap->src,symbol,sizeof(rswap->src)); + if ( rswap->iambob >= 0 ) + { + if ( rswap->iambob > 0 ) + safecopy(rswap->bobcoin,symbol,sizeof(rswap->bobcoin)); + else safecopy(rswap->alicecoin,symbol,sizeof(rswap->alicecoin)); + } + } + if ( (symbol= jstr(txobj,"dest")) != 0 ) + { + safecopy(rswap->dest,symbol,sizeof(rswap->dest)); + if ( rswap->iambob >= 0 ) + { + if ( rswap->iambob == 0 ) + safecopy(rswap->bobcoin,symbol,sizeof(rswap->bobcoin)); + else safecopy(rswap->alicecoin,symbol,sizeof(rswap->alicecoin)); + } } - if ( (value= jdouble(txobj,"amount") * SATOSHIDEN) == 0 ) - value = jdouble(txobj,"value") * SATOSHIDEN; - values[i] = value; if ( (symbol= jstr(txobj,"coin")) != 0 ) { if ( i == BASILISK_ALICESPEND || i == BASILISK_BOBPAYMENT || i == BASILISK_BOBDEPOSIT || i == BASILISK_BOBREFUND || i == BASILISK_BOBRECLAIM || i == BASILISK_ALICECLAIM ) - safecopy(bobcoin,symbol,sizeof(bobcoin)); + safecopy(rswap->bobcoin,symbol,sizeof(rswap->bobcoin)); else if ( i == BASILISK_BOBSPEND || i == BASILISK_ALICEPAYMENT || i == BASILISK_ALICERECLAIM ) - safecopy(alicecoin,symbol,sizeof(alicecoin)); - if ( finishedflag == 0 ) + safecopy(rswap->alicecoin,symbol,sizeof(rswap->alicecoin)); + if ( rswap->finishedflag == 0 ) { if ( (sentobj= LP_gettx(symbol,txid)) == 0 ) { @@ -584,437 +759,463 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti } else { - struct iguana_info *coin; int32_t ht = -1; uint32_t locktime,blocktime; checktxid = jbits256(sentobj,"txid"); - if ( (coin= LP_coinfind(symbol)) != 0 && (ht= LP_txheight(&locktime,&blocktime,coin,txid)) > 0 && ht > 0 ) - { - if ( coin->firstrefht == 0 || ht < coin->firstrefht ) - coin->firstrefht = ht; - } if ( bits256_nonz(checktxid) == 0 ) checktxid = jbits256(sentobj,"hash"); + LP_refht_update(symbol,txid); if ( bits256_cmp(checktxid,txid) == 0 ) { //printf(">>>>>> %s txid %s\n",jprint(sentobj,0),bits256_str(str,txid)); - sentflags[i] = 1; + rswap->sentflags[i] = 1; } free_json(sentobj); } - if ( finishedflag == 0 ) - printf("%s %s %.8f\n",txnames[i],bits256_str(str,txid),dstr(value)); + //printf("%s %s %.8f\n",txnames[i],bits256_str(str,txid),dstr(value)); } } } //else printf("no symbol\n"); free(fstr); - } else if ( 0 && finishedflag == 0 ) + } else if ( 0 && rswap->finishedflag == 0 ) printf("%s not finished\n",fname); } - //printf("alicepayment.%s bobpayment.%s bobdeposit.%s\n",alicepaymentaddr,bobpaymentaddr,bobdepositaddr); - //printf("iambob.%d src.%s dest.%s bob.%s alice.%s pubA0.(%s)\n",iambob,src,dest,bobcoin,alicecoin,bits256_str(str,pubA0)); - Adestaddr[0] = destaddr[0] = 0; - Adest = Bdest = AAdest = ABdest = 0; - if ( bobcoin[0] == 0 || alicecoin[0] == 0 ) - return(0); - Atxfee = LP_txfeecalc(alicecoin,Atxfee); - Btxfee = LP_txfeecalc(bobcoin,Btxfee); - //printf("%s %.8f txfee, %s %.8f txfee\n",alicecoin,dstr(Atxfee),bobcoin,dstr(Btxfee)); - //printf("privAm.(%s) %p/%p\n",bits256_str(str,privAm),Adest,AAdest); - //printf("privBn.(%s) %p/%p\n",bits256_str(str,privBn),Bdest,ABdest); - if ( finishedflag == 0 && bobcoin[0] != 0 && alicecoin[0] != 0 ) + if ( rswap->bobcoin[0] == 0 ) + strcpy(rswap->bobcoin,rswap->src); + if ( rswap->alicecoin[0] == 0 ) + strcpy(rswap->alicecoin,rswap->dest); + if ( rswap->src[0] == 0 ) + strcpy(rswap->src,rswap->bobcoin); + if ( rswap->dest[0] == 0 ) + strcpy(rswap->dest,rswap->alicecoin); + return(rswap->finishedflag); +} + +void LP_txbytes_update(char *name,char *symbol,char *txbytes,bits256 *txidp,bits256 *ptr,int32_t *flagp) +{ + bits256 zero; + memset(zero.bytes,0,sizeof(zero)); + if ( txbytes != 0 ) { - if ( iambob == 0 ) + *txidp = LP_broadcast(name,symbol,txbytes,zero); + if ( bits256_nonz(*txidp) != 0 ) { - if ( (alice= LP_coinfind(alicecoin)) != 0 ) - { - bitcoin_address(Adestaddr,alice->taddr,alice->pubtype,pubkey33,33); - AAdest = Adestaddr; - } - if ( (bob= LP_coinfind(bobcoin)) != 0 ) - { - bitcoin_address(destaddr,bob->taddr,bob->pubtype,pubkey33,33); - Adest = destaddr; - } + *flagp = 1; + if ( ptr != 0 ) + *ptr = *txidp; } - else + } +} + +int32_t LP_rswap_checktx(struct LP_swap_remember *rswap,char *symbol,int32_t txi) +{ + int32_t ht; struct iguana_info *coin; //char str[65]; + if ( rswap->sentflags[txi] == 0 && bits256_nonz(rswap->txids[txi]) != 0 ) + { + if ( (coin= LP_coinfind(symbol)) != 0 ) { - if ( (bob= LP_coinfind(bobcoin)) != 0 ) - { - bitcoin_address(destaddr,bob->taddr,bob->pubtype,pubkey33,33); - Bdest = destaddr; - } - if ( (alice= LP_coinfind(alicecoin)) != 0 ) + if ( (ht= LP_txheight(coin,rswap->txids[txi])) > 0 ) { - bitcoin_address(Adestaddr,alice->taddr,alice->pubtype,pubkey33,33); - ABdest = Adestaddr; - } + rswap->sentflags[txi] = 1; + _LP_refht_update(coin,rswap->txids[txi],ht); + } else LP_refht_update(symbol,rswap->txids[txi]); + //printf("[%s] %s txbytes.%p %s ht.%d\n",txnames[txi],txnames[txi],rswap->txbytes[txi],bits256_str(str,rswap->txids[txi]),ht); + } + } //else printf("sent.%d %s txi.%d\n",rswap->sentflags[txi],bits256_str(str,rswap->txids[txi]),txi); + return(0); +} + +int32_t LP_spends_set(struct LP_swap_remember *rswap) +{ + int32_t numspent = 0; + if ( bits256_nonz(rswap->paymentspent) == 0 ) + { + if ( bits256_nonz(rswap->txids[BASILISK_ALICESPEND]) != 0 ) + rswap->paymentspent = rswap->txids[BASILISK_ALICESPEND]; + else rswap->paymentspent = rswap->txids[BASILISK_BOBRECLAIM]; + } else numspent++; + if ( bits256_nonz(rswap->depositspent) == 0 ) + { + if ( bits256_nonz(rswap->txids[BASILISK_BOBREFUND]) != 0 ) + rswap->depositspent = rswap->txids[BASILISK_BOBREFUND]; + else rswap->depositspent = rswap->txids[BASILISK_ALICECLAIM]; + } else numspent++; + if ( bits256_nonz(rswap->Apaymentspent) == 0 ) + { + if ( bits256_nonz(rswap->txids[BASILISK_BOBSPEND]) != 0 ) + rswap->Apaymentspent = rswap->txids[BASILISK_BOBSPEND]; + else rswap->Apaymentspent = rswap->txids[BASILISK_ALICERECLAIM]; + } else numspent++; + return(numspent); +} + +cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requestid,uint32_t quoteid) +{ + static void *ctx; + struct LP_swap_remember rswap; int32_t i,j,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 ) + return(cJSON_Parse("{\"error\":\"couldnt initialize rswap, are all coins active?\"}")); + decode_hex(deadtxid.bytes,32,"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"); + LP_swap_load(&rswap); + 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.(%u %u) %llu files BOB.(%s) Alice.(%s) src.(%s) dest.(%s)\n",rswap.requestid,rswap.quoteid,(long long)rswap.aliceid,rswap.bobcoin,rswap.alicecoin,rswap.src,rswap.dest); + return(cJSON_Parse("{\"error\":\"mismatched bob/alice vs src/dest coins??\"}")); + } + alice = LP_coinfind(rswap.alicecoin); + bob = LP_coinfind(rswap.bobcoin); + rswap.Atxfee = LP_txfeecalc(alice,rswap.Atxfee,0); + rswap.Btxfee = LP_txfeecalc(bob,rswap.Btxfee,0); + if ( rswap.iambob == 0 ) + { + if ( alice != 0 ) + { + bitcoin_address(otheraddr,alice->taddr,alice->pubtype,rswap.other33,33); + destBdest = otheraddr; + destAdest = rswap.Adestaddr; } - if ( bob == 0 || alice == 0 ) + if ( (bob= LP_coinfind(rswap.bobcoin)) != 0 ) { - printf("Bob.%p is null or Alice.%p is null\n",bob,alice); - return(0); + bitcoin_address(rswap.Sdestaddr,bob->taddr,bob->pubtype,rswap.pubkey33,33); + srcAdest = rswap.Sdestaddr; } - if ( alice->inactive != 0 || bob->inactive != 0 ) + srcBdest = rswap.destaddr; + } + else + { + if ( bob != 0 ) { - printf("Alice.%s inactive.%u or Bob.%s inactive.%u\n",alicecoin,alice->inactive,bobcoin,bob->inactive); - return(0); + bitcoin_address(otheraddr,bob->taddr,bob->pubtype,rswap.other33,33); + srcAdest = otheraddr; + srcBdest = rswap.destaddr; } - if ( sentflags[BASILISK_ALICEPAYMENT] == 0 && bits256_nonz(txids[BASILISK_ALICEPAYMENT]) != 0 ) + if ( (alice= LP_coinfind(rswap.alicecoin)) != 0 ) { - printf("txbytes.%p Apayment.%s\n",txbytes[BASILISK_ALICEPAYMENT],bits256_str(str,txids[BASILISK_ALICEPAYMENT])); - if ( txbytes[BASILISK_ALICEPAYMENT] != 0 ) - sentflags[BASILISK_ALICEPAYMENT] = 1; - else if ( (sentobj= LP_gettx(alicecoin,txids[BASILISK_ALICEPAYMENT])) != 0 ) - { - sentflags[BASILISK_ALICEPAYMENT] = 1; - free_json(sentobj); - } + bitcoin_address(rswap.Sdestaddr,alice->taddr,alice->pubtype,rswap.pubkey33,33); + destBdest = rswap.Sdestaddr; } - paymentspent = basilisk_swap_spendupdate(bobcoin,sentflags,txids,BASILISK_BOBPAYMENT,BASILISK_ALICESPEND,BASILISK_BOBRECLAIM,0,Adest,Bdest); - Apaymentspent = basilisk_swap_spendupdate(alicecoin,sentflags,txids,BASILISK_ALICEPAYMENT,BASILISK_ALICERECLAIM,BASILISK_BOBSPEND,0,AAdest,ABdest); - depositspent = basilisk_swap_spendupdate(bobcoin,sentflags,txids,BASILISK_BOBDEPOSIT,BASILISK_ALICECLAIM,BASILISK_BOBREFUND,0,Adest,Bdest); - finishedflag = basilisk_swap_isfinished(iambob,txids,sentflags,paymentspent,Apaymentspent,depositspent); - if ( iambob == 0 ) + destAdest = rswap.Adestaddr; + } + if ( bob == 0 || alice == 0 ) + { + printf("Bob.%p is null or Alice.%p is null\n",bob,alice); + return(cJSON_Parse("{\"error\":\"null bob or alice coin\"}")); + } + //printf("src.(Adest %s, Bdest %s), dest.(Adest %s, Bdest %s)\n",srcAdest,srcBdest,destAdest,destBdest); + //printf("iambob.%d finishedflag.%d %s %.8f txfee, %s %.8f txfee\n",rswap.iambob,rswap.finishedflag,rswap.alicecoin,dstr(rswap.Atxfee),rswap.bobcoin,dstr(rswap.Btxfee)); + //printf("privAm.(%s) %p/%p\n",bits256_str(str,rswap.privAm),Adest,AAdest); + //printf("privBn.(%s) %p/%p\n",bits256_str(str,rswap.privBn),Bdest,ABdest); + if ( rswap.finishedflag == 0 && rswap.bobcoin[0] != 0 && rswap.alicecoin[0] != 0 ) + { + //printf("ALICE.(%s) 1st refht %s <- %d, scan %d %d\n",rswap.Adestaddr,alice->symbol,alice->firstrefht,alice->firstscanht,alice->lastscanht); + //printf("BOB.(%s) 1st refht %s <- %d, scan %d %d\n",rswap.destaddr,bob->symbol,bob->firstrefht,bob->firstscanht,bob->lastscanht); + if ( alice->inactive != 0 || bob->inactive != 0 ) + { + printf("Alice.%s inactive.%u or Bob.%s inactive.%u\n",rswap.alicecoin,alice->inactive,rswap.bobcoin,bob->inactive); + return(cJSON_Parse("{\"error\":\"inactive bob or alice coin\"}")); + } + LP_rswap_checktx(&rswap,rswap.alicecoin,BASILISK_ALICEPAYMENT); + LP_rswap_checktx(&rswap,rswap.bobcoin,BASILISK_BOBPAYMENT); + LP_rswap_checktx(&rswap,rswap.bobcoin,BASILISK_BOBDEPOSIT); + rswap.paymentspent = basilisk_swap_spendupdate(rswap.iambob,rswap.bobcoin,rswap.bobpaymentaddr,rswap.sentflags,rswap.txids,BASILISK_BOBPAYMENT,BASILISK_ALICESPEND,BASILISK_BOBRECLAIM,0,srcAdest,srcBdest,rswap.Adestaddr,rswap.destaddr); + rswap.Apaymentspent = basilisk_swap_spendupdate(rswap.iambob,rswap.alicecoin,rswap.alicepaymentaddr,rswap.sentflags,rswap.txids,BASILISK_ALICEPAYMENT,BASILISK_ALICERECLAIM,BASILISK_BOBSPEND,0,destAdest,destBdest,rswap.Adestaddr,rswap.destaddr); + rswap.depositspent = basilisk_swap_spendupdate(rswap.iambob,rswap.bobcoin,rswap.bobdepositaddr,rswap.sentflags,rswap.txids,BASILISK_BOBDEPOSIT,BASILISK_ALICECLAIM,BASILISK_BOBREFUND,0,srcAdest,srcBdest,rswap.Adestaddr,rswap.destaddr); + rswap.finishedflag = basilisk_swap_isfinished(rswap.iambob,rswap.txids,rswap.sentflags,rswap.paymentspent,rswap.Apaymentspent,rswap.depositspent); + LP_spends_set(&rswap); + if ( rswap.iambob == 0 ) { - if ( sentflags[BASILISK_ALICESPEND] == 0 ) + if ( rswap.sentflags[BASILISK_ALICESPEND] == 0 ) { - if ( sentflags[BASILISK_BOBPAYMENT] != 0 && bits256_nonz(paymentspent) == 0 ) + if ( rswap.sentflags[BASILISK_BOBPAYMENT] != 0 && bits256_nonz(rswap.paymentspent) == 0 ) { - //if ( txbytes[BASILISK_ALICESPEND] == 0 ) + flag = 0; + if ( bob->electrum == 0 ) + { + if ( (txoutobj= LP_gettxout(rswap.bobcoin,rswap.bobpaymentaddr,rswap.txids[BASILISK_BOBPAYMENT],0)) != 0 ) + free_json(txoutobj), flag = 0; + else flag = -1, rswap.paymentspent = deadtxid; + } + if ( flag == 0 ) { - if ( bits256_nonz(txids[BASILISK_BOBPAYMENT]) != 0 ) + if ( bits256_nonz(rswap.txids[BASILISK_BOBPAYMENT]) != 0 ) { // alicespend + memset(rev.bytes,0,sizeof(rev)); for (j=0; j<32; j++) - rev.bytes[j] = privAm.bytes[31 - j]; + rev.bytes[j] = rswap.privAm.bytes[31 - j]; //revcalc_rmd160_sha256(secretAm,rev);//privAm); //vcalc_sha256(0,secretAm256,rev.bytes,sizeof(rev)); - if ( Predeemlen != 0 ) - redeemlen = Predeemlen, memcpy(redeemscript,Predeemscript,Predeemlen); - else redeemlen = basilisk_swap_bobredeemscript(0,&secretstart,redeemscript,plocktime,pubA0,pubB0,pubB1,rev,privBn,secretAm,secretAm256,secretBn,secretBn256); - len = basilisk_swapuserdata(userdata,rev,0,myprivs[0],redeemscript,redeemlen); + if ( rswap.Predeemlen != 0 ) + redeemlen = rswap.Predeemlen, memcpy(redeemscript,rswap.Predeemscript,rswap.Predeemlen); + else redeemlen = basilisk_swap_bobredeemscript(0,&secretstart,redeemscript,rswap.plocktime,rswap.pubA0,rswap.pubB0,rswap.pubB1,rev,rswap.privBn,rswap.secretAm,rswap.secretAm256,rswap.secretBn,rswap.secretBn256); + len = basilisk_swapuserdata(userdata,rev,0,rswap.myprivs[0],redeemscript,redeemlen); { char privaddr[64]; uint8_t privpub33[33]; - bitcoin_pubkey33(ctx,privpub33,myprivs[0]); + bitcoin_pubkey33(ctx,privpub33,rswap.myprivs[0]); bitcoin_address(privaddr,0,60,privpub33,33); - printf("alicespend len.%d redeemlen.%d priv0addr.(%s) priv0.(%s)\n",len,redeemlen,privaddr,bits256_str(str,myprivs[0])); + printf("alicespend len.%d redeemlen.%d priv0addr.(%s) priv0.(%s)\n",len,redeemlen,privaddr,bits256_str(str,rswap.myprivs[0])); } for (j=0; j<32; j++) - rev.bytes[j] = myprivs[0].bytes[31 - j]; - if ( (txbytes[BASILISK_ALICESPEND]= basilisk_swap_bobtxspend(&signedtxid,Btxfee,"alicespend",bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,0,pubkey33,1,expiration,&values[BASILISK_ALICESPEND],0,0,bobpaymentaddr,1)) != 0 ) - printf("alicespend.(%s)\n",txbytes[BASILISK_ALICESPEND]); - } - } - if ( txbytes[BASILISK_ALICESPEND] != 0 ) - { - txids[BASILISK_ALICESPEND] = LP_broadcast("alicespend",bobcoin,txbytes[BASILISK_ALICESPEND],zero); - if ( bits256_nonz(txids[BASILISK_ALICESPEND]) != 0 ) // tested - { - sentflags[BASILISK_ALICESPEND] = 1; - paymentspent = txids[BASILISK_ALICESPEND]; + rev.bytes[j] = rswap.myprivs[0].bytes[31 - j]; + if ( (rswap.txbytes[BASILISK_ALICESPEND]= basilisk_swap_bobtxspend(&signedtxid,rswap.Btxfee,"alicespend",rswap.bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,rswap.myprivs[0],0,redeemscript,redeemlen,userdata,len,rswap.txids[BASILISK_BOBPAYMENT],0,0,rswap.pubkey33,1,rswap.expiration,&rswap.values[BASILISK_ALICESPEND],0,0,rswap.bobpaymentaddr,1,bob->zcash)) != 0 ) + printf("alicespend.(%s)\n",rswap.txbytes[BASILISK_ALICESPEND]); } + LP_txbytes_update("alicespend",rswap.bobcoin,rswap.txbytes[BASILISK_ALICESPEND],&rswap.txids[BASILISK_ALICESPEND],&rswap.paymentspent,&rswap.sentflags[BASILISK_ALICESPEND]); } } } - if ( sentflags[BASILISK_ALICECLAIM] == 0 && sentflags[BASILISK_BOBDEPOSIT] != 0 && bits256_nonz(txids[BASILISK_BOBDEPOSIT]) != 0 && bits256_nonz(depositspent) == 0 ) + 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) > expiration ) + if ( time(NULL) > rswap.expiration ) { - //if ( txbytes[BASILISK_ALICECLAIM] == 0 ) + flag = 0; + if ( bob->electrum == 0 ) { - if ( Dredeemlen != 0 ) - redeemlen = Dredeemlen, memcpy(redeemscript,Dredeemscript,Dredeemlen); - else redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,dlocktime,pubA0,pubB0,pubB1,privAm,zero,secretAm,secretAm256,secretBn,secretBn256); - if ( redeemlen > 0 ) - { - len = basilisk_swapuserdata(userdata,zero,1,myprivs[0],redeemscript,redeemlen); - if ( (txbytes[BASILISK_ALICECLAIM]= basilisk_swap_bobtxspend(&signedtxid,Btxfee,"aliceclaim",bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,0,pubkey33,0,expiration,&values[BASILISK_ALICECLAIM],0,0,bobdepositaddr,1)) != 0 ) - printf("privBn.(%s) aliceclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICECLAIM]); - } + if ( (txoutobj= LP_gettxout(rswap.bobcoin,rswap.bobdepositaddr,rswap.txids[BASILISK_BOBDEPOSIT],0)) != 0 ) + free_json(txoutobj), flag = 0; + else flag = -1, rswap.depositspent = deadtxid; } - if ( txbytes[BASILISK_ALICECLAIM] != 0 ) + if ( flag == 0 ) { - txids[BASILISK_ALICECLAIM] = LP_broadcast("aliceclaim",bobcoin,txbytes[BASILISK_ALICECLAIM],zero); - if ( bits256_nonz(txids[BASILISK_ALICECLAIM]) != 0 ) // tested + if ( rswap.Dredeemlen != 0 ) + redeemlen = rswap.Dredeemlen, memcpy(redeemscript,rswap.Dredeemscript,rswap.Dredeemlen); + else redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,rswap.dlocktime,rswap.pubA0,rswap.pubB0,rswap.pubB1,rswap.privAm,zero,rswap.secretAm,rswap.secretAm256,rswap.secretBn,rswap.secretBn256); + if ( redeemlen > 0 ) { - sentflags[BASILISK_ALICECLAIM] = 1; - depositspent = txids[BASILISK_ALICECLAIM]; + if ( bits256_nonz(rswap.privBn) == 0 ) + rswap.privBn = basilisk_swap_privBn_extract(&rswap.txids[BASILISK_BOBREFUND],rswap.bobcoin,rswap.txids[BASILISK_BOBDEPOSIT],rswap.privBn); + if ( bits256_nonz(rswap.privBn) != 0 ) + { + len = basilisk_swapuserdata(userdata,zero,1,rswap.myprivs[0],redeemscript,redeemlen); + if ( (rswap.txbytes[BASILISK_ALICECLAIM]= basilisk_swap_bobtxspend(&signedtxid,rswap.Btxfee,"aliceclaim",rswap.bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,rswap.myprivs[0],0,redeemscript,redeemlen,userdata,len,rswap.txids[BASILISK_BOBDEPOSIT],0,0,rswap.pubkey33,0,rswap.expiration,&rswap.values[BASILISK_ALICECLAIM],0,0,rswap.bobdepositaddr,1,bob->zcash)) != 0 ) + printf("privBn.(%s) aliceclaim.(%s)\n",bits256_str(str,rswap.privBn),rswap.txbytes[BASILISK_ALICECLAIM]); + } } + LP_txbytes_update("aliceclaim",rswap.bobcoin,rswap.txbytes[BASILISK_ALICECLAIM],&rswap.txids[BASILISK_ALICECLAIM],&rswap.depositspent,&rswap.sentflags[BASILISK_ALICECLAIM]); } - } else printf("now %u before expiration %u\n",(uint32_t)time(NULL),expiration); + } else printf("now %u before expiration %u\n",(uint32_t)time(NULL),rswap.expiration); } - if ( sentflags[BASILISK_ALICEPAYMENT] != 0 && bits256_nonz(Apaymentspent) == 0 && sentflags[BASILISK_ALICECLAIM] == 0 ) + if ( rswap.sentflags[BASILISK_ALICEPAYMENT] != 0 && bits256_nonz(rswap.Apaymentspent) == 0 && rswap.sentflags[BASILISK_ALICECLAIM] == 0 ) { - //if ( txbytes[BASILISK_ALICERECLAIM] == 0 ) + flag = 0; + if ( alice->electrum == 0 ) { - privBn = basilisk_swap_privBn_extract(&txids[BASILISK_BOBREFUND],bobcoin,txids[BASILISK_BOBDEPOSIT],privBn); - if ( bits256_nonz(txids[BASILISK_ALICEPAYMENT]) != 0 && bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 ) - { - if ( (txbytes[BASILISK_ALICERECLAIM]= basilisk_swap_Aspend("alicereclaim",alicecoin,Atxfee,alice->wiftaddr,alice->taddr,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_ALICERECLAIM],alicepaymentaddr)) != 0 ) - printf("privBn.(%s) alicereclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICERECLAIM]); - } + if ( (txoutobj= LP_gettxout(rswap.alicecoin,rswap.alicepaymentaddr,rswap.txids[BASILISK_ALICEPAYMENT],0)) != 0 ) + free_json(txoutobj), flag = 0; + else flag = -1, rswap.Apaymentspent = deadtxid; } - if ( txbytes[BASILISK_ALICERECLAIM] != 0 ) + if ( flag == 0 ) { - txids[BASILISK_ALICERECLAIM] = LP_broadcast("alicereclaim",alicecoin,txbytes[BASILISK_ALICERECLAIM],zero); - if ( bits256_nonz(txids[BASILISK_ALICERECLAIM]) != 0 ) // tested + rswap.privBn = basilisk_swap_privBn_extract(&rswap.txids[BASILISK_BOBREFUND],rswap.bobcoin,rswap.txids[BASILISK_BOBDEPOSIT],rswap.privBn); + if ( bits256_nonz(rswap.txids[BASILISK_ALICEPAYMENT]) != 0 && bits256_nonz(rswap.privAm) != 0 && bits256_nonz(rswap.privBn) != 0 ) { - sentflags[BASILISK_ALICERECLAIM] = 1; - Apaymentspent = txids[BASILISK_ALICERECLAIM]; + if ( (rswap.txbytes[BASILISK_ALICERECLAIM]= basilisk_swap_Aspend("alicereclaim",rswap.alicecoin,rswap.Atxfee,alice->wiftaddr,alice->taddr,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,rswap.privAm,rswap.privBn,rswap.txids[BASILISK_ALICEPAYMENT],0,rswap.pubkey33,rswap.expiration,&rswap.values[BASILISK_ALICERECLAIM],rswap.alicepaymentaddr,alice->zcash)) != 0 ) + printf("privBn.(%s) alicereclaim.(%s)\n",bits256_str(str,rswap.privBn),rswap.txbytes[BASILISK_ALICERECLAIM]); } + LP_txbytes_update("alicereclaim",rswap.alicecoin,rswap.txbytes[BASILISK_ALICERECLAIM],&rswap.txids[BASILISK_ALICERECLAIM],&rswap.Apaymentspent,&rswap.sentflags[BASILISK_ALICERECLAIM]); } } } - else if ( iambob == 1 ) + else if ( rswap.iambob == 1 ) { - if ( sentflags[BASILISK_BOBSPEND] == 0 && bits256_nonz(Apaymentspent) == 0 ) + if ( rswap.sentflags[BASILISK_BOBSPEND] == 0 && bits256_nonz(rswap.Apaymentspent) == 0 ) { - printf("try to bobspend aspend.%s have privAm.%d\n",bits256_str(str,txids[BASILISK_ALICESPEND]),bits256_nonz(privAm)); - if ( bits256_nonz(txids[BASILISK_ALICESPEND]) != 0 || bits256_nonz(privAm) != 0 ) + //printf("try to bobspend aspend.%s have privAm.%d\n",bits256_str(str,rswap.txids[BASILISK_ALICESPEND]),bits256_nonz(rswap.privAm)); + if ( bits256_nonz(rswap.txids[BASILISK_ALICESPEND]) != 0 || bits256_nonz(rswap.privAm) != 0 ) { - //if ( txbytes[BASILISK_BOBSPEND] == 0 ) + flag = 0; + if ( alice->electrum == 0 ) { - if ( bits256_nonz(privAm) == 0 ) - { - privAm = basilisk_swap_privbob_extract(bobcoin,txids[BASILISK_ALICESPEND],0,1); - } - if ( bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 ) - { - if ( (txbytes[BASILISK_BOBSPEND]= basilisk_swap_Aspend("bobspend",alicecoin,Atxfee,alice->wiftaddr,alice->taddr,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_BOBSPEND],alicepaymentaddr)) != 0 ) - printf("bobspend.(%s)\n",txbytes[BASILISK_BOBSPEND]); - } + if ( (txoutobj= LP_gettxout(rswap.alicecoin,rswap.alicepaymentaddr,rswap.txids[BASILISK_ALICEPAYMENT],0)) != 0 ) + free_json(txoutobj), flag = 0; + else flag = -1, rswap.Apaymentspent = deadtxid; } - if ( txbytes[BASILISK_BOBSPEND] != 0 ) + if ( flag == 0 ) { - txids[BASILISK_BOBSPEND] = LP_broadcast("bobspend",alicecoin,txbytes[BASILISK_BOBSPEND],zero); - if ( bits256_nonz(txids[BASILISK_BOBSPEND]) != 0 ) // tested + if ( bits256_nonz(rswap.privAm) == 0 ) + { + rswap.privAm = basilisk_swap_privbob_extract(rswap.bobcoin,rswap.txids[BASILISK_ALICESPEND],0,1); + //printf("try to bobspend aspend.%s have privAm.%d\n",bits256_str(str,rswap.txids[BASILISK_ALICESPEND]),bits256_nonz(rswap.privAm)); + } + if ( bits256_nonz(rswap.privAm) != 0 && bits256_nonz(rswap.privBn) != 0 ) { - sentflags[BASILISK_BOBSPEND] = 1; - Apaymentspent = txids[BASILISK_BOBSPEND]; + if ( (rswap.txbytes[BASILISK_BOBSPEND]= basilisk_swap_Aspend("bobspend",rswap.alicecoin,rswap.Atxfee,alice->wiftaddr,alice->taddr,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,rswap.privAm,rswap.privBn,rswap.txids[BASILISK_ALICEPAYMENT],0,rswap.pubkey33,rswap.expiration,&rswap.values[BASILISK_BOBSPEND],rswap.alicepaymentaddr,alice->zcash)) != 0 ) + printf("bobspend.(%s)\n",rswap.txbytes[BASILISK_BOBSPEND]); } + LP_txbytes_update("bobspend",rswap.alicecoin,rswap.txbytes[BASILISK_BOBSPEND],&rswap.txids[BASILISK_BOBSPEND],&rswap.Apaymentspent,&rswap.sentflags[BASILISK_BOBSPEND]); } } } - if ( sentflags[BASILISK_BOBRECLAIM] == 0 && sentflags[BASILISK_BOBPAYMENT] != 0 && bits256_nonz(txids[BASILISK_BOBPAYMENT]) != 0 && time(NULL) > expiration && bits256_nonz(paymentspent) == 0 ) + if ( rswap.sentflags[BASILISK_BOBRECLAIM] == 0 && rswap.sentflags[BASILISK_BOBPAYMENT] != 0 && bits256_nonz(rswap.txids[BASILISK_BOBPAYMENT]) != 0 && bits256_nonz(rswap.paymentspent) == 0 ) { - //if ( txbytes[BASILISK_BOBRECLAIM] == 0 ) + flag = 0; + if ( bob->electrum == 0 ) + { + if ( (txoutobj= LP_gettxout(rswap.bobcoin,rswap.bobpaymentaddr,rswap.txids[BASILISK_BOBPAYMENT],0)) != 0 ) + free_json(txoutobj), flag = 0; + else flag = -1, rswap.paymentspent = deadtxid; + } + if ( flag == 0 && time(NULL) > rswap.expiration ) { // bobreclaim - redeemlen = basilisk_swap_bobredeemscript(0,&secretstart,redeemscript,plocktime,pubA0,pubB0,pubB1,zero,privBn,secretAm,secretAm256,secretBn,secretBn256); + 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); if ( redeemlen > 0 ) { - len = basilisk_swapuserdata(userdata,zero,1,myprivs[1],redeemscript,redeemlen); - if ( (txbytes[BASILISK_BOBRECLAIM]= basilisk_swap_bobtxspend(&signedtxid,Btxfee,"bobrefund",bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[1],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,0,pubkey33,0,expiration,&values[BASILISK_BOBRECLAIM],0,0,bobpaymentaddr,1)) != 0 ) + len = basilisk_swapuserdata(userdata,zero,1,rswap.myprivs[1],redeemscript,redeemlen); + if ( (rswap.txbytes[BASILISK_BOBRECLAIM]= basilisk_swap_bobtxspend(&signedtxid,rswap.Btxfee,"bobrefund",rswap.bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,rswap.myprivs[1],0,redeemscript,redeemlen,userdata,len,rswap.txids[BASILISK_BOBPAYMENT],0,0,rswap.pubkey33,0,rswap.expiration,&rswap.values[BASILISK_BOBRECLAIM],0,0,rswap.bobpaymentaddr,1,bob->zcash)) != 0 ) { int32_t z; for (z=0; z<20; z++) - printf("%02x",secretAm[z]); - printf(" secretAm, myprivs[1].(%s) bobreclaim.(%s)\n",bits256_str(str,myprivs[1]),txbytes[BASILISK_BOBRECLAIM]); + printf("%02x",rswap.secretAm[z]); + printf(" secretAm, myprivs[1].(%s) bobreclaim.(%s)\n",bits256_str(str,rswap.myprivs[1]),rswap.txbytes[BASILISK_BOBRECLAIM]); } } + LP_txbytes_update("bobreclaim",rswap.bobcoin,rswap.txbytes[BASILISK_BOBRECLAIM],&rswap.txids[BASILISK_BOBRECLAIM],&rswap.paymentspent,&rswap.sentflags[BASILISK_BOBRECLAIM]); } - if ( txbytes[BASILISK_BOBRECLAIM] != 0 ) - { - txids[BASILISK_BOBRECLAIM] = LP_broadcast("bobreclaim",bobcoin,txbytes[BASILISK_BOBRECLAIM],zero); - if ( bits256_nonz(txids[BASILISK_BOBRECLAIM]) != 0 ) // tested - { - sentflags[BASILISK_BOBRECLAIM] = 1; - paymentspent = txids[BASILISK_BOBRECLAIM]; - } - } + else if ( flag == 0 ) + printf("bobpayment: now.%u < expiration %u\n",(uint32_t)time(NULL),rswap.expiration); } - if ( sentflags[BASILISK_BOBREFUND] == 0 && sentflags[BASILISK_BOBDEPOSIT] != 0 && bits256_nonz(txids[BASILISK_BOBDEPOSIT]) != 0 && bits256_nonz(depositspent) == 0 ) + if ( rswap.sentflags[BASILISK_BOBREFUND] == 0 && rswap.sentflags[BASILISK_BOBDEPOSIT] != 0 && bits256_nonz(rswap.txids[BASILISK_BOBDEPOSIT]) != 0 && bits256_nonz(rswap.depositspent) == 0 ) { - if ( bits256_nonz(paymentspent) != 0 || time(NULL) > expiration ) + flag = 0; + if ( bob->electrum == 0 ) + { + if ( (txoutobj= LP_gettxout(rswap.bobcoin,rswap.bobdepositaddr,rswap.txids[BASILISK_BOBDEPOSIT],0)) != 0 ) + free_json(txoutobj), flag = 0; + else flag = -1, rswap.depositspent = deadtxid; + } + if ( flag == 0 && (bits256_nonz(rswap.Apaymentspent) != 0 || time(NULL) > rswap.expiration) ) { - printf("do the refund!\n"); + printf("do the refund! paymentspent.%s now.%u vs expiration.%u\n",bits256_str(str,rswap.paymentspent),(uint32_t)time(NULL),rswap.expiration); //if ( txbytes[BASILISK_BOBREFUND] == 0 ) { - revcalc_rmd160_sha256(secretBn,privBn); - vcalc_sha256(0,secretBn256,privBn.bytes,sizeof(privBn)); - redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,dlocktime,pubA0,pubB0,pubB1,privAm,privBn,secretAm,secretAm256,secretBn,secretBn256); - len = basilisk_swapuserdata(userdata,privBn,0,myprivs[0],redeemscript,redeemlen); - if ( (txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend(&signedtxid,Btxfee,"bobrefund",bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,0,pubkey33,1,expiration,&values[BASILISK_BOBREFUND],0,0,bobdepositaddr,1)) != 0 ) - printf("pubB1.(%s) bobrefund.(%s)\n",bits256_str(str,pubB1),txbytes[BASILISK_BOBREFUND]); + revcalc_rmd160_sha256(rswap.secretBn,rswap.privBn); + vcalc_sha256(0,rswap.secretBn256,rswap.privBn.bytes,sizeof(rswap.privBn)); + redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,rswap.dlocktime,rswap.pubA0,rswap.pubB0,rswap.pubB1,rswap.privAm,rswap.privBn,rswap.secretAm,rswap.secretAm256,rswap.secretBn,rswap.secretBn256); + len = basilisk_swapuserdata(userdata,rswap.privBn,0,rswap.myprivs[0],redeemscript,redeemlen); + if ( (rswap.txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend(&signedtxid,rswap.Btxfee,"bobrefund",rswap.bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,rswap.myprivs[0],0,redeemscript,redeemlen,userdata,len,rswap.txids[BASILISK_BOBDEPOSIT],0,0,rswap.pubkey33,1,rswap.expiration,&rswap.values[BASILISK_BOBREFUND],0,0,rswap.bobdepositaddr,1,bob->zcash)) != 0 ) + printf("pubB1.(%s) bobrefund.(%s)\n",bits256_str(str,rswap.pubB1),rswap.txbytes[BASILISK_BOBREFUND]); } - if ( txbytes[BASILISK_BOBREFUND] != 0 ) - { - txids[BASILISK_BOBREFUND] = LP_broadcast("bobrefund",bobcoin,txbytes[BASILISK_BOBREFUND],zero); - if ( bits256_nonz(txids[BASILISK_BOBREFUND]) != 0 ) // tested - { - sentflags[BASILISK_BOBREFUND] = 1; - depositspent = txids[BASILISK_BOBREFUND]; - } - } - } else printf("bobrefund's time %u vs expiration %u\n",(uint32_t)time(NULL),expiration); + LP_txbytes_update("bobrefund",rswap.bobcoin,rswap.txbytes[BASILISK_BOBREFUND],&rswap.txids[BASILISK_BOBREFUND],&rswap.depositspent,&rswap.sentflags[BASILISK_BOBREFUND]); + } + else if ( flag == 0 ) + printf("bobrefund's time %u vs expiration %u\n",(uint32_t)time(NULL),rswap.expiration); } } } //printf("finish.%d iambob.%d REFUND %d %d %d %d\n",finishedflag,iambob,sentflags[BASILISK_BOBREFUND] == 0,sentflags[BASILISK_BOBDEPOSIT] != 0,bits256_nonz(txids[BASILISK_BOBDEPOSIT]) != 0,bits256_nonz(depositspent) == 0); - if ( sentflags[BASILISK_ALICESPEND] != 0 || sentflags[BASILISK_BOBRECLAIM] != 0 ) - sentflags[BASILISK_BOBPAYMENT] = 1; - if ( sentflags[BASILISK_ALICERECLAIM] != 0 || sentflags[BASILISK_BOBSPEND] != 0 ) - sentflags[BASILISK_ALICEPAYMENT] = 1; - if ( sentflags[BASILISK_ALICECLAIM] != 0 || sentflags[BASILISK_BOBREFUND] != 0 ) - sentflags[BASILISK_BOBDEPOSIT] = 1; - for (i=0; inumswaps; i++) - if ( (swap= myinfo->swaps[i]) != 0 && swap->I.req.requestid == requestid && swap->I.req.quoteid == quoteid ) - { - jaddi(array,basilisk_swapjson(swap)); - flag = 1; - break; - }*/ - if ( flag == 0 ) + //struct basilisk_swap *swap; + int32_t flag = 0; + while ( fread(&requestid,1,sizeof(requestid),fp) == sizeof(requestid) && fread("eid,1,sizeof(quoteid),fp) == sizeof(quoteid) ) { - if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid)) != 0 ) + flag = 0; + for (i=0; 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 ) + { + ridqid = ((uint64_t)requestid << 32) | quoteid; + for (j=0; j 0 ) + if ( 0 && cJSON_GetArraySize(array) > 0 ) { totalsobj = cJSON_CreateObject(); for (Btotal=i=0; i 0 ) jaddnum(retjson,"avesell",(double)-Btotal/Ktotal); } - array = cJSON_CreateArray(); - /*for (i=0; ilinfos)/sizeof(*myinfo->linfos); i++) + /*array = cJSON_CreateArray(); + for (i=0; ilinfos)/sizeof(*myinfo->linfos); i++) { if ( myinfo->linfos[i].base[0] != 0 && myinfo->linfos[i].rel[0] != 0 ) jaddi(array,linfo_json(&myinfo->linfos[i])); @@ -1046,9 +1247,102 @@ char *basilisk_swaplist() char *basilisk_swapentry(uint32_t requestid,uint32_t quoteid) { - char *liststr,*retstr = 0; cJSON *retjson,*array,*item; int32_t i,n; - if ( (liststr= basilisk_swaplist()) != 0 ) + 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)) != 0 ) + return(jprint(item,1)); + else return(clonestr("{\"error\":\"cant find requestid-quoteid\"}")); +} + +extern struct LP_quoteinfo LP_Alicequery; +extern uint32_t Alice_expiration; + +char *LP_recent_swaps(int32_t limit) +{ + char fname[512]; long fsize,offset; FILE *fp; int32_t i=0; uint32_t requestid,quoteid; cJSON *array,*item,*retjson; + if ( limit <= 0 ) + limit = 3; + sprintf(fname,"%s/SWAPS/list",GLOBAL_DBDIR), OS_compatible_path(fname); + array = cJSON_CreateArray(); + if ( (fp= fopen(fname,"rb")) != 0 ) { + fseek(fp,0,SEEK_END); + fsize = ftell(fp); + offset = (sizeof(requestid) + sizeof(quoteid)); + while ( offset <= fsize && i < limit ) + { + i++; + offset = i * (sizeof(requestid) + sizeof(quoteid)); + fseek(fp,fsize-offset,SEEK_SET); + if ( ftell(fp) == fsize-offset ) + { + if ( fread(&requestid,1,sizeof(requestid),fp) == sizeof(requestid) && fread("eid,1,sizeof(quoteid),fp) == sizeof(quoteid) ) + { + item = cJSON_CreateArray(); + jaddinum(item,requestid); + jaddinum(item,quoteid); + jaddi(array,item); + } else break; + } else break; + } + fclose(fp); + } + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jadd(retjson,"swaps",array); + if ( time(NULL) < Alice_expiration ) + { + item = cJSON_CreateObject(); + jaddnum(item,"expiration",Alice_expiration); + jaddnum(item,"timeleft",Alice_expiration-time(NULL)); + 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); + jaddstr(item,"base",LP_Alicequery.srccoin); + jaddnum(item,"basevalue",dstr(LP_Alicequery.satoshis)); + 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)); +} + +uint64_t basilisk_swap_addarray(cJSON *item,char *refbase,char *refrel) +{ + char *base,*rel; uint32_t requestid,quoteid; uint64_t ridqid = 0; + base = jstr(item,"bob"); + rel = jstr(item,"alice"); + if ( refrel == 0 || refrel[0] == 0 ) + { + if ( (base != 0 && strcmp(base,refbase) == 0) || (rel != 0 && strcmp(rel,refbase) == 0) ) + ridqid = 1; + } + else if ( (base != 0 && strcmp(base,refbase) == 0) && (rel != 0 && strcmp(rel,refrel) == 0) ) + ridqid = 1; + if ( ridqid != 0 ) + { + requestid = juint(item,"requestid"); + quoteid = juint(item,"quoteid"); + ridqid = ((uint64_t)requestid << 32) | quoteid; + //printf("%u %u -> %16llx\n",requestid,quoteid,(long long)ridqid); + } + return(ridqid); +} + +char *basilisk_swapentries(char *refbase,char *refrel,int32_t limit) +{ + uint64_t ridqids[1024],ridqid; char *liststr,*retstr2; cJSON *retjson,*array,*pending,*swapjson,*item,*retarray; int32_t i,j,n,count = 0; uint32_t requestid,quoteid; + if ( limit <= 0 ) + limit = 10; + memset(ridqids,0,sizeof(ridqids)); + retarray = cJSON_CreateArray(); + if ( (liststr= basilisk_swaplist(0,0)) != 0 ) + { + //printf("swapentry.(%s)\n",liststr); if ( (retjson= cJSON_Parse(liststr)) != 0 ) { if ( (array= jarray(&n,retjson,"swaps")) != 0 ) @@ -1056,20 +1350,114 @@ char *basilisk_swapentry(uint32_t requestid,uint32_t quoteid) for (i=0; i 0 ) { - retstr = jprint(item,0); - break; + if ( count < sizeof(ridqids)/sizeof(*ridqids) ) + { + ridqids[count++] = ridqid; + //printf("add ridqid.%16llx\n",(long long)ridqid); + } + jaddi(retarray,jduplicate(item)); + } + } + } + free_json(retjson); + } + free(liststr); + } + if ( (liststr= LP_recent_swaps(limit)) != 0 ) + { + if ( (retjson= cJSON_Parse(liststr)) != 0 ) + { + if ( (array= jarray(&n,retjson,"swaps")) != 0 ) + { + for (i=0; i 0 ) + { + if ( count < sizeof(ridqids)/sizeof(*ridqids) ) + ridqids[count++] = ridqid; + jaddi(retarray,swapjson); + } else free_json(swapjson); + } + free(retstr2); + } } } } + if ( (pending= jobj(retjson,"pending")) != 0 ) + { + requestid = juint(pending,"requestid"); + quoteid = juint(pending,"quoteid"); + j = 0; + if ( (ridqid= ((uint64_t)requestid << 32) | quoteid) != 0 ) + { + for (j=0; j 0 ) + jaddi(retarray,pending); + else free_json(pending); + } else free_json(pending); + } free_json(retjson); } free(liststr); } - return(retstr); + 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; ierrors < maxerrs || peer->good >= LP_MINPEER_GOOD) ) { + printf("issue.(%s)\n",url); if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) == 0 ) { if ( peer != 0 ) @@ -37,7 +40,7 @@ char *LP_issue_curl(char *debugstr,char *destip,uint16_t port,char *url) peer->good++; } return(retstr); -} +}*/ char *LP_isitme(char *destip,uint16_t destport) { @@ -48,101 +51,276 @@ 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,int32_t numutxos) +char *LP_apicall(struct iguana_info *coin,char *method,char *params) { - char url[512],*retstr; - sprintf(url,"http://%s:%u/api/stats/getpeers?ipaddr=%s&port=%u&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,numpeers,numutxos); - retstr = LP_issue_curl("getpeers",destip,port,url); - //printf("%s -> getpeers.(%s)\n",destip,retstr); - return(retstr); + cJSON *retjson; char *retstr; + if ( coin == 0 ) + return(0); + if ( coin->electrum != 0 ) + { + if ( (retjson= electrum_submit(coin->symbol,coin->electrum,&retjson,method,params,ELECTRUM_TIMEOUT)) != 0 ) + { + retstr = jprint(retjson,1); + //printf("got.%p (%s)\n",retjson,retstr); + return(retstr); + } return(clonestr("{\"error\":\"electrum no response\"}")); + } else return(bitcoind_passthru(coin->symbol,coin->serverport,coin->userpass,method,params)); } -char *issue_LP_numutxos(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers,int32_t numutxos) +cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params) { - char url[512],*retstr; - sprintf(url,"http://%s:%u/api/stats/numutxos?ipaddr=%s&port=%u&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,numpeers,numutxos); - retstr = LP_issue_curl("numutxos",destip,port,url); - //printf("%s -> getpeers.(%s)\n",destip,retstr); - return(retstr); + cJSON *retjson = 0; char *retstr; + // "getinfo", "getrawmempool", "paxprice", "gettxout", "getrawtransaction", "getblock", "listunspent", "listtransactions", "validateaddress", "importprivkey" + // bitcoind_passthru callers: "importaddress", "estimatefee", "getblockhash", "sendrawtransaction", "signrawtransaction" + if ( coin != 0 ) + { + //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->electrum == 0 ) + { + retstr = bitcoind_passthru(coin->symbol,coin->serverport,coin->userpass,method,params); + if ( 0 && strcmp("KMD",coin->symbol) == 0 ) + printf("%s.(%s %s): %s.%s -> (%s)\n",coin->symbol,coin->serverport,coin->userpass,method,params,retstr); + if ( retstr != 0 && retstr[0] != 0 ) + { + retjson = cJSON_Parse(retstr); + free(retstr); + } + } + else + { + if ( (retjson= electrum_submit(coin->symbol,coin->electrum,&retjson,method,params,ELECTRUM_TIMEOUT)) != 0 ) + { + if ( jobj(retjson,"error") != 0 ) + { + 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\"}"); + } else printf("bitcoin_json cant talk to NULL coin\n"); + return(retjson); } -char *issue_LP_getutxos(char *destip,uint16_t destport,char *coin,int32_t lastn,char *ipaddr,uint16_t port,int32_t numpeers,int32_t numutxos) +void LP_unspents_mark(char *symbol,cJSON *vins) { - char url[512]; - sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=%s&port=%u&numpeers=%d&numutxos=%d",destip,destport,coin,lastn,ipaddr,port,numpeers,numutxos); - return(LP_issue_curl("getutxos",destip,destport,url)); - //return(issue_curlt(url,LP_HTTP_TIMEOUT)); + //printf("LOCK (%s)\n",jprint(vins,0)); } -char *issue_LP_clientgetutxos(char *destip,uint16_t destport,char *coin,int32_t lastn) +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" }, +}; + +void LP_sendtoaddress_line(char *validaddress,char *assetname,uint64_t satoshis,uint64_t txnum) { - char url[512];//,*retstr; - sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=127.0.0.1&port=0",destip,destport,coin,lastn); - return(LP_issue_curl("clientgetutxos",destip,destport,url)); - //retstr = issue_curlt(url,LP_HTTP_TIMEOUT); - //printf("%s clientgetutxos.(%s)\n",url,retstr); - //return(retstr); + 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 + { + strcpy(lowerstr,assetname); + tolowercase(lowerstr); + sprintf(line,"fiat/%s sendtoaddress %s %.8f # txnum.%llu",lowerstr,validaddress,dstr(satoshis),(long long)txnum); + } + printf("%s\n",line); } -char *issue_LP_notify(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers,int32_t numutxos,uint32_t sessionid) +uint64_t LP_assetid_mult(int32_t *assetindp,char *name,uint64_t assetid) { - char url[512],*retstr; - if ( (retstr= LP_isitme(destip,destport)) != 0 ) - return(retstr); - sprintf(url,"http://%s:%u/api/stats/notify?ipaddr=%s&port=%u&numpeers=%d&numutxos=%d&session=%u",destip,destport,ipaddr,port,numpeers,numutxos,sessionid); - return(LP_issue_curl("notify",destip,destport,url)); - //return(issue_curlt(url,LP_HTTP_TIMEOUT)); + int32_t i; uint64_t mult = 0; + name[0] = 0; + *assetindp = -1; + for (i=0; isymbol,coin->serverport,coin->userpass,method,params); - if ( coin->inactive == 0 || strcmp(method,"importprivkey") == 0 || strcmp(method,"validateaddress") == 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 ) { - retstr = bitcoind_passthru(coin->symbol,coin->serverport,coin->userpass,method,params); - if ( retstr != 0 && retstr[0] != 0 ) + if ( (retjson= cJSON_Parse(retstr)) != 0 ) { - //printf("%s: %s.%s -> (%s)\n",coin->symbol,method,params,retstr); - retjson = cJSON_Parse(retstr); - free(retstr); + } - //usleep(100); - //printf("dpow_gettxout.(%s)\n",retstr); - } else retjson = cJSON_Parse("{\"result\":\"disabled\"}"); - } else printf("bitcoin_json cant talk to NULL coin\n"); + free(retstr); + } + } return(retjson); } -void LP_unspents_mark(char *symbol,cJSON *vins) +cJSON *LP_NXT_redeems() { - printf("LOCK (%s)\n",jprint(vins,0)); + char url[1024],*retstr,*recv,*method,*msgstr,assetname[128]; uint64_t totals[20],mult,txnum,assetid,qty; int32_t i,ind,numtx,past_marker=0; cJSON *item,*attach,*decjson,*array,*msgjson,*encjson,*retjson=0; + uint64_t txnum_marker = calc_nxt64bits("0"); + 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= 0 ) + totals[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= 34 ) + strncpy(validaddress,&msgstr[z],34); + 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); + if ( past_marker == 0 ) + { + 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\n"); + for (i=0; iheight; + if ( coin->electrum == 0 && time(NULL) > coin->heighttime+60 ) + { + if ( strcmp(coin->symbol,"BTC") == 0 ) + method = "getblockchaininfo"; + retstr = bitcoind_passthru(coin->symbol,coin->serverport,coin->userpass,method,"[]"); + if ( retstr != 0 && retstr[0] != 0 ) + { + retjson = cJSON_Parse(retstr); + coin->height = height = jint(retjson,"blocks"); + free_json(retjson); + if ( coin->height > 0 ) + coin->heighttime = (uint32_t)time(NULL); + free(retstr); + } + } + return(height); +} + +uint64_t LP_RTsmartbalance(struct iguana_info *coin) { - struct iguana_info *coin = LP_coinfind(symbol); - return(bitcoin_json(coin,"getinfo","[]")); + cJSON *array,*item; char buf[512],*retstr; int32_t i,n; uint64_t valuesum,value; + valuesum = 0; + sprintf(buf,"[0, 99999999, [\"%s\"]]",coin->smartaddr); + retstr = bitcoind_passthru(coin->symbol,coin->serverport,coin->userpass,"listunspent",buf); + if ( retstr != 0 && retstr[0] != 0 ) + { + array = cJSON_Parse(retstr); + if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; ielectrum != 0 && coinaddr == 0) ) + 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)); } cJSON *LP_paxprice(char *fiat) @@ -184,62 +410,308 @@ cJSON *LP_paxprice(char *fiat) return(bitcoin_json(coin,"paxprice",buf)); } -cJSON *LP_gettxout(char *symbol,bits256 txid,int32_t vout) +cJSON *LP_gettx(char *symbol,bits256 txid) { - char buf[128],str[65]; struct iguana_info *coin = LP_coinfind(symbol); - sprintf(buf,"[\"%s\", %d, true]",bits256_str(str,txid),vout); - return(bitcoin_json(coin,"gettxout",buf)); + struct iguana_info *coin; char buf[512],str[65]; 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\"}")); + coin = LP_coinfind(symbol); + if ( coin == 0 ) + return(cJSON_Parse("{\"error\":\"no coin\"}")); + if ( bits256_nonz(txid) == 0 ) + return(cJSON_Parse("{\"error\":\"null txid\"}")); + if ( coin->electrum == 0 ) + { + sprintf(buf,"[\"%s\", 1]",bits256_str(str,txid)); + retjson = bitcoin_json(coin,"getrawtransaction",buf); + return(retjson); + } + else + { + if ( (retjson= electrum_transaction(symbol,coin->electrum,&retjson,txid,0)) != 0 ) + return(retjson); + else printf("failed blockchain.transaction.get %s %s\n",coin->symbol,bits256_str(str,txid)); + return(cJSON_Parse("{\"error\":\"no transaction bytes\"}")); + } } -cJSON *LP_gettx(char *symbol,bits256 txid) +uint32_t LP_locktime(char *symbol,bits256 txid) { - char buf[128],str[65]; struct iguana_info *coin = LP_coinfind(symbol); - sprintf(buf,"[\"%s\", 1]",bits256_str(str,txid)); - return(bitcoin_json(coin,"getrawtransaction",buf)); + cJSON *txobj; uint32_t locktime = 0; + if ( (txobj= LP_gettx(symbol,txid)) != 0 ) + { + locktime = juint(txobj,"locktime"); + free_json(txobj); + } + return(locktime); } -cJSON *LP_getblock(char *symbol,bits256 txid) +/*uint32_t LP_txtime(char *symbol,bits256 txid) { - char buf[128],str[65]; struct iguana_info *coin = LP_coinfind(symbol); - sprintf(buf,"[\"%s\"]",bits256_str(str,txid)); - return(bitcoin_json(coin,"getblock",buf)); -} + struct LP_transaction *tx; struct iguana_info *coin; int32_t timestamp=0,height = 0; + char str[65]; printf("LP_txtime (%s %s)\n",symbol,bits256_str(str,txid)); + if ( (timestamp= LP_locktime(symbol,txid)) != 0 ) + return(timestamp); + if ( (coin= LP_coinfind(symbol)) != 0 ) + { + if ( (tx= LP_transactionfind(coin,txid)) != 0 ) + { + height = tx->height; + timestamp = LP_heighttime(symbol,height); + } + } + return(height); +}*/ -cJSON *LP_getblockhashstr(char *symbol,char *blockhashstr) +cJSON *LP_gettxout_json(bits256 txid,int32_t vout,int32_t height,char *coinaddr,uint64_t value) { - char buf[128]; struct iguana_info *coin = LP_coinfind(symbol); - sprintf(buf,"[\"%s\"]",blockhashstr); - return(bitcoin_json(coin,"getblock",buf)); + cJSON *retjson,*addresses,*sobj; + retjson = cJSON_CreateObject(); + jaddnum(retjson,"value",dstr(value)); + jaddnum(retjson,"height",height); + jaddbits256(retjson,"txid",txid); + jaddnum(retjson,"vout",vout); + addresses = cJSON_CreateArray(); + jaddistr(addresses,coinaddr); + sobj = cJSON_CreateObject(); + jaddnum(sobj,"reqSigs",1); + jaddstr(sobj,"type","pubkey"); + jadd(sobj,"addresses",addresses); + jadd(retjson,"scriptPubKey",sobj); + //printf("GETTXOUT.(%s)\n",jprint(retjson,0)); + return(retjson); } -cJSON *LP_listunspent(char *symbol,char *coinaddr) +cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout) { - char buf[128]; struct iguana_info *coin = LP_coinfind(symbol); - sprintf(buf,"[0, 99999999, [\"%s\"]]",coinaddr); - return(bitcoin_json(coin,"listunspent",buf)); + 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; + if ( symbol == 0 || symbol[0] == 0 ) + return(cJSON_Parse("{\"error\":\"null symbol\"}")); + if ( (coin= LP_coinfind(symbol)) == 0 ) + return(cJSON_Parse("{\"error\":\"no coin\"}")); + if ( bits256_nonz(txid) == 0 ) + return(cJSON_Parse("{\"error\":\"null txid\"}")); + if ( coin->electrum == 0 ) + { + sprintf(buf,"[\"%s\", %d, true]",bits256_str(str,txid),vout); + return(bitcoin_json(coin,"gettxout",buf)); + } + else + { + if ( (tx= LP_transactionfind(coin,txid)) != 0 && vout < tx->numvouts ) + { + if ( tx->outpoints[vout].spendheight > 0 ) + return(0); + //return(LP_gettxout_json(txid,vout,tx->height,tx->outpoints[vout].coinaddr,tx->outpoints[vout].value)); + } + if ( coinaddr[0] == 0 ) + { + if ( (txobj= electrum_transaction(symbol,coin->electrum,&txobj,txid,0)) != 0 ) + { + if ( (vouts= jarray(&n,txobj,"vout")) != 0 && n > 0 ) + LP_destaddr(coinaddr,jitem(vouts,vout)); + free_json(txobj); + } + } + if ( coinaddr[0] != 0 ) + { + if ( (up= LP_address_utxofind(coin,coinaddr,txid,vout)) != 0 ) + { + if ( up->spendheight > 0 ) + 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 ) + { + //printf("array.(%s)\n",jprint(array,0)); + if ( array != 0 && (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; ielectrum != 0 ) + { + retjson = cJSON_CreateObject(); + jaddstr(retjson,"address",address); + bitcoin_addr2rmd160(coin->taddr,&addrtype,rmd160,address); + bitcoin_address(checkaddr,coin->taddr,addrtype,rmd160,20); + jadd(retjson,"isvalid",strcmp(address,checkaddr)==0? cJSON_CreateTrue() : cJSON_CreateFalse()); + if ( addrtype == coin->pubtype ) + { + strcpy(script,"76a914"); + for (i=0; i<20; i++) + sprintf(&script[i*2+6],"%02x",rmd160[i]); + script[i*2+6] = 0; + strcat(script,"88ac"); + jaddstr(retjson,"scriptPubKey",script); + } + 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,"isscript",addrtype == coin->p2shtype ? cJSON_CreateTrue() : cJSON_CreateFalse()); + return(retjson); + } + else + { + sprintf(buf,"[\"%s\"]",address); + return(bitcoin_json(coin,"validateaddress",buf)); + } +} + +int32_t LP_address_ismine(char *symbol,char *address) +{ + int32_t doneflag = 0; cJSON *retjson; + 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 ) + { + doneflag = 1; + //printf("%s ismine (%s)\n",address,jprint(retjson,0)); + } + //printf("%s\n",jprint(retjson,0)); + free_json(retjson); + } + return(doneflag); +} + +int32_t LP_address_isvalid(char *symbol,char *address) +{ + int32_t isvalid = 0; cJSON *retjson; + if ( symbol == 0 || symbol[0] == 0 ) + return(0); + if ( (retjson= LP_validateaddress(symbol,address)) != 0 ) + { + if ( jobj(retjson,"isvalid") != 0 && is_cJSON_True(jobj(retjson,"isvalid")) != 0 ) + { + isvalid = 1; + //printf("%s ismine (%s)\n",address,jprint(retjson,0)); + } + //printf("%s\n",jprint(retjson,0)); + free_json(retjson); + } + return(isvalid); +} + +cJSON *LP_listunspent(char *symbol,char *coinaddr) +{ + char buf[128]; cJSON *retjson; int32_t numconfs; 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 ( strcmp(symbol,"BTC") == 0 ) + numconfs = 0; + else numconfs = 1; + sprintf(buf,"[%d, 99999999, [\"%s\"]]",numconfs,coinaddr); + return(bitcoin_json(coin,"listunspent",buf)); + } else return(LP_address_utxos(coin,coinaddr,0)); + } else return(electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,1)); +} + +int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag) +{ + struct iguana_info *coin; int32_t n = 0; cJSON *retjson=0; char *retstr=0; + 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 ) + { + n = cJSON_GetArraySize(retjson); + //printf("LP_listunspent_issue.%s %s.%d %s\n",symbol,coinaddr,n,jprint(retjson,0)); + } + } + else + { + if ( strcmp(coin->smartaddr,coinaddr) == 0 ) + { + retjson = LP_listunspent(symbol,coinaddr); + coin->numutxos = cJSON_GetArraySize(retjson); + //printf("SELF_LISTUNSPENT.(%s %s)\n",symbol,coinaddr); + } + else if ( IAMLP == 0 ) + { + //printf("LP_listunspent_query.(%s %s)\n",symbol,coinaddr); + LP_listunspent_query(coin->symbol,coin->smartaddr); + } + if ( retjson != 0 ) + { + n = cJSON_GetArraySize(retjson); + if ( electrum_process_array(coin,0,coinaddr,retjson,1) != 0 ) + { + //LP_postutxos(symbol,coinaddr); // might be good to not saturate + } + } + } + //printf("issue listunspent %s (%s)\n",coinaddr,jprint(retjson,0)); + if ( retjson != 0 ) + free_json(retjson); + if ( retstr != 0 ) + free(retstr); + } + return(n); } cJSON *LP_importprivkey(char *symbol,char *wifstr,char *label,int32_t flag) { static void *ctx; char buf[512],address[64]; cJSON *retjson; struct iguana_info *coin; int32_t doneflag = 0; + if ( symbol == 0 || symbol[0] == 0 ) + return(cJSON_Parse("{\"error\":\"null symbol\"}")); coin = LP_coinfind(symbol); + if ( coin == 0 ) + return(cJSON_Parse("{\"error\":\"no coin\"}")); + if ( coin->electrum != 0 ) + return(cJSON_Parse("{\"result\":\"electrum should have local wallet\"}")); if ( ctx == 0 ) ctx = bitcoin_ctx(); bitcoin_wif2addr(ctx,coin->wiftaddr,coin->taddr,coin->pubtype,address,wifstr); @@ -264,62 +736,273 @@ cJSON *LP_importprivkey(char *symbol,char *wifstr,char *label,int32_t flag) int32_t LP_importaddress(char *symbol,char *address) { - char buf[1024],*retstr; cJSON *validatejson; int32_t isvalid=0,doneflag = 0; struct iguana_info *coin = LP_coinfind(symbol); + char buf[1024],*retstr; cJSON *validatejson; int32_t isvalid=0,doneflag = 0; struct iguana_info *coin; + if ( symbol == 0 || symbol[0] == 0 ) + return(-2); + coin = LP_coinfind(symbol); if ( coin == 0 ) return(-2); - if ( (validatejson= LP_validateaddress(symbol,address)) != 0 ) + if ( coin->electrum != 0 ) { - if ( (isvalid= is_cJSON_True(jobj(validatejson,"isvalid")) != 0) != 0 ) + /*if ( (retjson= electrum_address_subscribe(symbol,coin->electrum,&retjson,address)) != 0 ) { - if ( is_cJSON_True(jobj(validatejson,"iswatchonly")) != 0 || is_cJSON_True(jobj(validatejson,"ismine")) != 0 ) - doneflag = 1; - } - free_json(validatejson); + printf("importaddress.(%s) -> %s\n",address,jprint(retjson,0)); + free_json(retjson); + }*/ + return(0); } - if ( isvalid == 0 ) - return(-1); - if ( doneflag != 0 ) - return(0); // success - sprintf(buf,"[\"%s\", \"%s\", false]",address,address); - if ( (retstr= bitcoind_passthru(symbol,coin->serverport,coin->userpass,"importaddress",buf)) != 0 ) + else { - //printf("importaddress.(%s %s) -> (%s)\n",symbol,address,retstr); - free(retstr); - } //else printf("importaddress.(%s %s)\n",symbol,address); - return(1); + if ( (validatejson= LP_validateaddress(symbol,address)) != 0 ) + { + if ( (isvalid= is_cJSON_True(jobj(validatejson,"isvalid")) != 0) != 0 ) + { + if ( is_cJSON_True(jobj(validatejson,"iswatchonly")) != 0 || is_cJSON_True(jobj(validatejson,"ismine")) != 0 ) + doneflag = 1; + } + free_json(validatejson); + } + if ( isvalid == 0 ) + return(-1); + if ( doneflag != 0 ) + return(0); // success + sprintf(buf,"[\"%s\", \"%s\", false]",address,address); + if ( (retstr= bitcoind_passthru(symbol,coin->serverport,coin->userpass,"importaddress",buf)) != 0 ) + { + //printf("importaddress.(%s %s) -> (%s)\n",symbol,address,retstr); + free(retstr); + } //else printf("importaddress.(%s %s)\n",symbol,address); + return(1); + } } -double LP_getestimatedrate(char *symbol) +double _LP_getestimatedrate(struct iguana_info *coin) { - char buf[512],*retstr; double rate = 20; struct iguana_info *coin = LP_coinfind(symbol); - if ( coin != 0 && (strcmp(coin->symbol,"BTC") == 0 || coin->txfee == 0) ) + 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]",3); - if ( (retstr= bitcoind_passthru(symbol,coin->serverport,coin->userpass,"estimatefee",buf)) != 0 ) + numblocks = strcmp(coin->symbol,"BTC") == 0 ? 6 : 2; + if ( coin->electrum == 0 ) { - if ( retstr[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 ) + { + if ( jobj(errjson,"error") != 0 ) + rate = 0.; + free_json(errjson); + } + else if ( retstr[0] != '-' ) { rate = atof(retstr) / 1024.; - //printf("estimated rate.(%s) %s -> %.8f\n",symbol,retstr,rate); + if ( rate < 0.00000020 ) + rate = 0.00000020; + rate *= 1.1; + if ( coin->electrum != 0 ) + rate *= 1.667; + 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); +} + +double LP_getestimatedrate(struct iguana_info *coin) +{ + double rate = 0.00000020; + if ( coin == 0 ) + return(rate); + if ( (rate= _LP_getestimatedrate(coin)) <= 0. ) + rate = dstr(coin->txfee) / LP_AVETXSIZE; + return(rate); +} + +char *LP_sendrawtransaction(char *symbol,char *signedtx) +{ + cJSON *array,*errobj; char *paramstr,*tmpstr,*retstr=0; int32_t n,alreadyflag = 0; cJSON *retjson; struct iguana_info *coin; + if ( symbol == 0 || symbol[0] == 0 || signedtx == 0 || signedtx[0] == 0 ) + { + printf("LP_sendrawtransaction null symbol %p or signedtx.%p\n",symbol,signedtx); + return(0); + } + coin = LP_coinfind(symbol); + if ( coin == 0 ) + { + printf("LP_sendrawtransaction null coin\n"); + return(0); + } + if ( coin->electrum == 0 ) + { + array = cJSON_CreateArray(); + jaddistr(array,signedtx); + paramstr = jprint(array,1); + retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"sendrawtransaction",paramstr); + //printf(">>>>>>>>>>> %s dpow_sendrawtransaction.(%s) -> (%s)\n",coin->symbol,paramstr,retstr); + free(paramstr); + } + else + { + if ( (retjson= electrum_sendrawtransaction(symbol,coin->electrum,&retjson,signedtx)) != 0 ) + { + retstr = jprint(retjson,1); + //electrum sendrawtx (the transaction was rejected by network rules.\n\ntransaction already in block chain) + if ( strstr(retstr,"already in block") != 0 ) + alreadyflag = 1; + //printf("electrum sendrawtx.(%s) -> %s already.%d\n",signedtx,retstr,alreadyflag); + if ( alreadyflag != 0 ) + { + errobj = cJSON_CreateObject(); + jaddstr(errobj,"error","rejected"); + jaddnum(errobj,"code",-27); + free(retstr); + retstr = jprint(errobj,1); + } + else + { + n = (int32_t)strlen(retstr); + if ( retstr[0] == '"' && retstr[n-1] == '"' ) + { + retstr[n-1] = 0; + tmpstr = clonestr(retstr+1); + free(retstr); + retstr = tmpstr; + } + } + } + } + return(retstr); +} + +char *LP_signrawtx(char *symbol,bits256 *signedtxidp,int32_t *completedp,cJSON *vins,char *rawtx,cJSON *privkeys,struct vin_info *V) +{ + cJSON *array,*json,*retjson; int32_t len; uint8_t *data; char str[65],*paramstr,*retstr,*hexstr,*signedtx=0; struct iguana_msgtx msgtx; struct iguana_info *coin; + if ( symbol == 0 || symbol[0] == 0 ) + return(0); + coin = LP_coinfind(symbol); + memset(signedtxidp,0,sizeof(*signedtxidp)); + *completedp = 0; + if ( coin == 0 ) + { + printf("LP_signrawtx cant find coin.(%s)\n",symbol); + return(0); + } + //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) + memset(&msgtx,0,sizeof(msgtx)); + signedtx = 0; + memset(signedtxidp,0,sizeof(*signedtxidp)); + //printf("locktime.%u sequenceid.%x rawtx.(%s) vins.(%s)\n",locktime,sequenceid,rawtxbytes,jprint(vins,0)); + if ( (*completedp= iguana_signrawtransaction(coin->ctx,symbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,1000000,&msgtx,&signedtx,signedtxidp,V,16,rawtx,vins,privkeys,coin->zcash)) < 0 ) + //if ( (signedtx= LP_signrawtx(symbol,signedtxidp,&completed,vins,rawtxbytes,privkeys,V)) == 0 ) + printf("couldnt sign transaction.%s %s\n",rawtx,bits256_str(str,*signedtxidp)); + else if ( *completedp == 0 ) + { + printf("incomplete signing %s (%s)\n",rawtx,jprint(vins,0)); + if ( signedtx != 0 ) + free(signedtx), signedtx = 0; + } else printf("basilisk_swap_bobtxspend %s -> %s\n",rawtx,bits256_str(str,*signedtxidp)); + if ( signedtx == 0 ) + { + retjson = cJSON_CreateObject(); + jaddstr(retjson,"error","couldnt sign tx"); + jaddstr(retjson,"coin",coin->symbol); + jaddstr(retjson,"rawtx",rawtx); + jadd(retjson,"vins",vins); + jadd(retjson,"privkeys",privkeys); + return(jprint(retjson,1)); + } + return(signedtx); + if ( (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 ( (json= cJSON_Parse(retstr)) != 0 ) + { + 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); } free(retstr); } - } else return((double)coin->txfee / LP_AVETXSIZE); - return(SATOSHIDEN * rate); + free(paramstr); + return(signedtx); + } +} + +cJSON *LP_getblock(char *symbol,bits256 txid) +{ + char buf[128],str[65]; struct iguana_info *coin; + if ( symbol == 0 || symbol[0] == 0 ) + return(cJSON_Parse("{\"error\":\"null symbol\"}")); + coin = LP_coinfind(symbol); + if ( coin == 0 || coin->electrum != 0 ) + return(cJSON_Parse("{\"error\":\"no native coin\"}")); + sprintf(buf,"[\"%s\"]",bits256_str(str,txid)); + return(bitcoin_json(coin,"getblock",buf)); } +// not in electrum path uint64_t LP_txfee(char *symbol) { uint64_t txfee = 0; + if ( symbol == 0 || symbol[0] == 0 ) + return(LP_MIN_TXFEE); if ( strcmp(symbol,"BTC") != 0 ) txfee = LP_MIN_TXFEE; return(txfee); } +bits256 LP_getbestblockhash(struct iguana_info *coin) +{ + char *retstr; bits256 blockhash; + memset(blockhash.bytes,0,sizeof(blockhash)); + if ( coin->electrum == 0 ) + { + if ( (retstr= bitcoind_passthru(coin->symbol,coin->serverport,coin->userpass,"getbestblockhash","")) != 0 ) + { + if ( is_hexstr(retstr,0) == sizeof(blockhash)*2 ) + 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 = LP_coinfind(symbol); - if ( coin == 0 ) + cJSON *array; char *paramstr,*retstr; struct iguana_info *coin; + 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); @@ -329,63 +1012,60 @@ char *LP_blockhashstr(char *symbol,int32_t height) return(retstr); } -char *LP_sendrawtransaction(char *symbol,char *signedtx) +cJSON *LP_getblockhashstr(char *symbol,char *blockhashstr) { - cJSON *array; char *paramstr,*retstr; struct iguana_info *coin = LP_coinfind(symbol); - if ( coin == 0 ) - return(0); - array = cJSON_CreateArray(); - jaddistr(array,signedtx); - paramstr = jprint(array,1); - retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"sendrawtransaction",paramstr); - //printf(">>>>>>>>>>> %s dpow_sendrawtransaction.(%s) -> (%s)\n",coin->symbol,paramstr,retstr); - free(paramstr); - return(retstr); + char buf[128]; struct iguana_info *coin; + if ( symbol == 0 || symbol[0] == 0 ) + return(cJSON_Parse("{\"error\":\"null symbol\"}")); + coin = LP_coinfind(symbol); + if ( coin == 0 || coin->electrum != 0 ) + return(cJSON_Parse("{\"error\":\"no native coin daemon\"}")); + sprintf(buf,"[\"%s\"]",blockhashstr); + return(bitcoin_json(coin,"getblock",buf)); } -char *LP_signrawtx(char *symbol,bits256 *signedtxidp,int32_t *completedp,cJSON *vins,char *rawtx,cJSON *privkeys,struct vin_info *V) +uint32_t LP_heighttime(char *symbol,int32_t height) { - cJSON *array,*json; int32_t len; uint8_t *data; char *paramstr,*retstr,*hexstr,*signedtx=0; struct iguana_info *coin = LP_coinfind(symbol); - memset(signedtxidp,0,sizeof(*signedtxidp)); - *completedp = 0; - if ( coin == 0 ) - { - printf("LP_signrawtx cant find coin.(%s)\n",symbol); - return(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 ) + struct electrum_info *ep; uint32_t timestamp = 0; cJSON *retjson; char *blockhashstr; struct iguana_info *coin = LP_coinfind(symbol); + if ( coin != 0 ) { - if ( (json= cJSON_Parse(retstr)) != 0 ) + if ( (ep= coin->electrum) == 0 ) { - if ( (hexstr= jstr(json,"hex")) != 0 ) + if ( (blockhashstr= LP_blockhashstr(symbol,height)) != 0 ) { - len = (int32_t)strlen(hexstr); - signedtx = calloc(1,len+1); - strcpy(signedtx,hexstr); - *completedp = is_cJSON_True(jobj(json,"complete")); - data = malloc(len >> 1); - decode_hex(data,len>>1,hexstr); - *signedtxidp = bits256_doublesha256(0,data,len >> 1); + 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); } - //else - printf("%s signrawtransaction.(%s) params.(%s)\n",coin->symbol,retstr,paramstr); - free_json(json); } - free(retstr); } - free(paramstr); - return(signedtx); + return(timestamp); } cJSON *LP_blockjson(int32_t *heightp,char *symbol,char *blockhashstr,int32_t height) { - cJSON *json = 0; int32_t flag = 0; + cJSON *json = 0; int32_t flag = 0; struct iguana_info *coin; + if ( symbol == 0 || symbol[0] == 0 ) + return(cJSON_Parse("{\"error\":\"null symbol\"}")); + coin = LP_coinfind(symbol); + if ( coin == 0 || coin->electrum != 0 ) + { + printf("unexpected electrum path for %s\n",symbol); + return(0); + } if ( blockhashstr == 0 ) blockhashstr = LP_blockhashstr(symbol,height), flag = 1; if ( blockhashstr != 0 ) @@ -397,7 +1077,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; @@ -410,3 +1090,184 @@ cJSON *LP_blockjson(int32_t *heightp,char *symbol,char *blockhashstr,int32_t hei return(json); } +const char *Notaries_elected[][2] = +{ + { "0_jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, + { "0_jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" }, + { "0_kolo_testA", "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" }, + { "artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, + { "artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, + { "artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, + { "artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, + { "badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, + { "badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, + { "badass_SH", "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" }, + { "crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, // 10 + { "crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, + { "crackers_SH", "02be28310e6312d1dd44651fd96f6a44ccc269a321f907502aae81d246fabdb03e" }, + { "durerus_EU", "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" }, + { "etszombi_AR", "031c79168d15edabf17d9ec99531ea9baa20039d0cdc14d9525863b83341b210e9" }, + { "etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, + { "etszombi_SH", "025d7a193c0757f7437fad3431f027e7b5ed6c925b77daba52a8755d24bf682dde" }, + { "farl4web_EU", "0300ecf9121cccf14cf9423e2adb5d98ce0c4e251721fa345dec2e03abeffbab3f" }, + { "farl4web_SH", "0396bb5ed3c57aa1221d7775ae0ff751e4c7dc9be220d0917fa8bbdf670586c030" }, + { "fullmoon_AR", "0254b1d64840ce9ff6bec9dd10e33beb92af5f7cee628f999cb6bc0fea833347cc" }, + { "fullmoon_NA", "031fb362323b06e165231c887836a8faadb96eda88a79ca434e28b3520b47d235b" }, // 20 + { "fullmoon_SH", "030e12b42ec33a80e12e570b6c8274ce664565b5c3da106859e96a7208b93afd0d" }, + { "grewal_NA", "03adc0834c203d172bce814df7c7a5e13dc603105e6b0adabc942d0421aefd2132" }, + { "grewal_SH", "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" }, + { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + { "jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, + { "jsgalt_NA", "027b3fb6fede798cd17c30dbfb7baf9332b3f8b1c7c513f443070874c410232446" }, + { "karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, // 30 + { "kashifali_EU", "033777c52a0190f261c6f66bd0e2bb299d30f012dcb8bfff384103211edb8bb207" }, + { "kolo_AR", "03016d19344c45341e023b72f9fb6e6152fdcfe105f3b4f50b82a4790ff54e9dc6" }, + { "kolo_SH", "02aa24064500756d9b0959b44d5325f2391d8e95c6127e109184937152c384e185" }, + { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + { "movecrypto_AR", "022783d94518e4dc77cbdf1a97915b29f427d7bc15ea867900a76665d3112be6f3" }, + { "movecrypto_EU", "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" }, + { "movecrypto_NA", "02efb12f4d78f44b0542d1c60146738e4d5506d27ec98a469142c5c84b29de0a80" }, + { "movecrypto_SH", "031f9739a3ebd6037a967ce1582cde66e79ea9a0551c54731c59c6b80f635bc859" }, + { "muros_AR", "022d77402fd7179335da39479c829be73428b0ef33fb360a4de6890f37c2aa005e" }, + { "noashh_AR", "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" }, // 40 + { "noashh_EU", "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" }, + { "noashh_NA", "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" }, + { "nxtswe_EU", "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" }, + { "polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, + { "pondsea_AR", "032e1c213787312099158f2d74a89e8240a991d162d4ce8017d8504d1d7004f735" }, + { "pondsea_EU", "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" }, + { "pondsea_NA", "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" }, + { "pondsea_SH", "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" }, + { "popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, + { "popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, // 50 + { "ptytrader_NA", "0328c61467148b207400b23875234f8a825cce65b9c4c9b664f47410b8b8e3c222" }, + { "ptytrader_SH", "0250c93c492d8d5a6b565b90c22bee07c2d8701d6118c6267e99a4efd3c7748fa4" }, + { "rnr_AR", "029bdb08f931c0e98c2c4ba4ef45c8e33a34168cb2e6bf953cef335c359d77bfcd" }, + { "rnr_EU", "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" }, + { "rnr_NA", "02e17c5f8c3c80f584ed343b8dcfa6d710dfef0889ec1e7728ce45ce559347c58c" }, + { "rnr_SH", "037536fb9bdfed10251f71543fb42679e7c52308bcd12146b2568b9a818d8b8377" }, + { "titomane_AR", "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" }, + { "titomane_EU", "02e41feded94f0cc59f55f82f3c2c005d41da024e9a805b41105207ef89aa4bfbd" }, + { "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" }, + { "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" }, // 60 + { "xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, + { "xxspot1_XX", "02ef445a392fcaf3ad4176a5da7f43580e8056594e003eba6559a713711a27f955" }, + { "xxspot2_XX", "03d85b221ea72ebcd25373e7961f4983d12add66a92f899deaf07bab1d8b6f5573" } +}; + +int32_t LP_txhasnotarization(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 ) + { + if ( (vins= jarray(&numvins,txobj,"vin")) != 0 ) + { + if ( numvins >= DPOW_MIN_ASSETCHAIN_SIGS ) + { + notarymask = numnotaries = 0; + for (i=0; isymbol,spenttxid)) != 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 ) + { + len >>= 1; + decode_hex(script,len,hexstr); + if ( script[0] == 33 && script[34] == 0xac ) + { + for (j=0; j 0 ) + { + if ( numnotaries >= DPOW_MIN_ASSETCHAIN_SIGS ) + hasnotarization = 1; + //printf("numnotaries.%d %s hasnotarization.%d\n",numnotaries,coin->symbol,hasnotarization); + } + } + } + free_json(txobj); + } + return(hasnotarization); +} + +int32_t LP_hasnotarization(struct iguana_info *coin,cJSON *blockjson) +{ + int32_t i,n,hasnotarization = 0; bits256 txid; cJSON *txarray; + if ( (txarray= jarray(&n,blockjson,"tx")) != 0 ) + { + for (i=0; isymbol,blockhash)) != 0 ) + { + if ( *bestheightp < 0 ) + *bestheightp = jint(blockjson,"height"); + if ( (hasnotarization= LP_hasnotarization(coin,blockjson)) > 0 ) + { + height = jint(blockjson,"height"); + //char str[65]; printf("%s height.%d\n",bits256_str(str,blockhash),height); + } + else + { + blockhash = jbits256(blockjson,"previousblockhash"); + if ( bits256_nonz(blockhash) == 0 ) + { + //printf("null prev.(%s)\n",jprint(blockjson,0)); + free_json(blockjson); + break; + } + } + free_json(blockjson); + if ( height > 0 ) + break; + } + } else break; + } + return(height); +} diff --git a/iguana/exchanges/LP_scan.c b/iguana/exchanges/LP_scan.c index cfbc6eb3d..f3b67476b 100644 --- a/iguana/exchanges/LP_scan.c +++ b/iguana/exchanges/LP_scan.c @@ -19,225 +19,34 @@ // -struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr) -{ - struct LP_address *ap; - HASH_FIND(hh,coin->addresses,coinaddr,strlen(coinaddr),ap); - return(ap); -} - -struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr) -{ - struct LP_address *ap; - ap = calloc(1,sizeof(*ap)); - safecopy(ap->coinaddr,coinaddr,sizeof(ap->coinaddr)); - HASH_ADD_KEYPTR(hh,coin->addresses,ap->coinaddr,strlen(ap->coinaddr),ap); - return(ap); -} - -struct LP_address *_LP_address(struct iguana_info *coin,char *coinaddr) -{ - struct LP_address *ap; - if ( (ap= _LP_addressfind(coin,coinaddr)) == 0 ) - ap = _LP_addressadd(coin,coinaddr); - return(ap); -} - -struct LP_transaction *LP_transactionfind(struct iguana_info *coin,bits256 txid) -{ - struct LP_transaction *tx; - portable_mutex_lock(&coin->txmutex); - HASH_FIND(hh,coin->transactions,txid.bytes,sizeof(txid),tx); - portable_mutex_unlock(&coin->txmutex); - return(tx); -} - -struct LP_transaction *LP_transactionadd(struct iguana_info *coin,bits256 txid,int32_t height,int32_t numvouts,int32_t numvins,uint32_t timestamp) -{ - struct LP_transaction *tx; int32_t i; - if ( (tx= LP_transactionfind(coin,txid)) == 0 ) - { - //char str[65]; printf("%s ht.%d u.%u NEW TXID.(%s) vouts.[%d]\n",coin->symbol,height,timestamp,bits256_str(str,txid),numvouts); - //if ( bits256_nonz(txid) == 0 && tx->height == 0 ) - // getchar(); - tx = calloc(1,sizeof(*tx) + (sizeof(*tx->outpoints) * numvouts)); - for (i=0; ioutpoints[i].spendvini = -1; - tx->height = height; - tx->numvouts = numvouts; - tx->numvins = numvins; - tx->timestamp = timestamp; - tx->txid = txid; - portable_mutex_lock(&coin->txmutex); - HASH_ADD_KEYPTR(hh,coin->transactions,tx->txid.bytes,sizeof(tx->txid),tx); - portable_mutex_unlock(&coin->txmutex); - } // else printf("warning adding already existing txid %s\n",bits256_str(str,tx->txid)); - return(tx); -} - -int32_t LP_txheight(uint32_t *timestampp,uint32_t *blocktimep,struct iguana_info *coin,bits256 txid) -{ - bits256 blockhash; cJSON *blockobj,*txobj; int32_t height = 0; - if ( (txobj= LP_gettx(coin->symbol,txid)) != 0 ) - { - *timestampp = juint(txobj,"locktime"); - *blocktimep = juint(txobj,"blocktime"); - blockhash = jbits256(txobj,"blockhash"); - if ( bits256_nonz(blockhash) != 0 && (blockobj= LP_getblock(coin->symbol,blockhash)) != 0 ) - { - height = jint(blockobj,"height"); - //printf("%s LP_txheight.%d\n",coin->symbol,height); - free_json(blockobj); - } //else printf("%s LP_txheight error (%s)\n",coin->symbol,jprint(txobj,0)); - free_json(txobj); - } - return(height); -} - -int32_t LP_undospends(struct iguana_info *coin,int32_t lastheight) -{ - int32_t i,ht,num = 0; uint32_t timestamp,blocktime; struct LP_transaction *tx,*tmp; - HASH_ITER(hh,coin->transactions,tx,tmp) - { - for (i=0; inumvouts; i++) - { - if ( bits256_nonz(tx->outpoints[i].spendtxid) == 0 ) - continue; - if ( (ht= tx->outpoints[i].spendheight) == 0 ) - { - tx->outpoints[i].spendheight = LP_txheight(×tamp,&blocktime,coin,tx->outpoints[i].spendtxid); - } - if ( (ht= tx->outpoints[i].spendheight) != 0 && ht > lastheight ) - { - char str[65]; printf("clear spend %s/v%d at ht.%d > lastheight.%d\n",bits256_str(str,tx->txid),i,ht,lastheight); - tx->outpoints[i].spendheight = 0; - tx->outpoints[i].spendvini = -1; - memset(tx->outpoints[i].spendtxid.bytes,0,sizeof(bits256)); - } - } - } - return(num); -} - -uint64_t LP_txinterestvalue(uint64_t *interestp,char *destaddr,struct iguana_info *coin,bits256 txid,int32_t vout) -{ - uint64_t interest,value = 0; cJSON *txobj,*sobj,*array; int32_t n=0; - *interestp = 0; - destaddr[0] = 0; - if ( (txobj= LP_gettxout(coin->symbol,txid,vout)) != 0 ) - { - if ( (value= jdouble(txobj,"amount")*SATOSHIDEN) == 0 && (value= jdouble(txobj,"value")*SATOSHIDEN) == 0 ) - { - char str[65]; printf("%s LP_txvalue.%s strange utxo.(%s) vout.%d\n",coin->symbol,bits256_str(str,txid),jprint(txobj,0),vout); - } - else if ( strcmp(coin->symbol,"KMD") == 0 ) - { - if ( (interest= jdouble(txobj,"interest")) != 0. ) - { - //printf("add interest of %.8f to %.8f\n",interest,dstr(value)); - *interestp = SATOSHIDEN * interest; - } - } - if ( (sobj= jobj(txobj,"scriptPubKey")) != 0 && (array= jarray(&n,sobj,"addresses")) != 0 ) - { - strcpy(destaddr,jstri(array,0)); - if ( n > 1 ) - printf("LP_txinterestvalue warning: violation of 1 output assumption n.%d\n",n); - } else printf("LP_txinterestvalue no addresses found?\n"); - //char str[65]; printf("%s %.8f <- %s.(%s) txobj.(%s)\n",destaddr,dstr(value),coin->symbol,bits256_str(str,txid),jprint(txobj,0)); - free_json(txobj); - } else { char str[65]; printf("null gettxout return %s/v%d\n",bits256_str(str,txid),vout); } - return(value); -} - -int32_t LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter) -{ - struct LP_transaction *tx; char *address; int32_t i,n,height,numvouts,numvins,spentvout; uint32_t timestamp,blocktime; cJSON *txobj,*vins,*vouts,*vout,*vin,*sobj,*addresses; bits256 spenttxid; char str[65]; - if ( (txobj= LP_gettx(coin->symbol,txid)) != 0 ) - { - //printf("TX.(%s)\n",jprint(txobj,0)); - height = LP_txheight(×tamp,&blocktime,coin,txid); - if ( timestamp == 0 && height > 0 ) - timestamp = blocktime; - vins = jarray(&numvins,txobj,"vin"); - vouts = jarray(&numvouts,txobj,"vout"); - if ( iter == 0 && vouts != 0 && (tx= LP_transactionadd(coin,txid,height,numvouts,numvins,timestamp)) != 0 ) - { - for (i=0; ioutpoints[i].value= SATOSHIDEN * jdouble(vout,"value")) == 0 ) - tx->outpoints[i].value = SATOSHIDEN * jdouble(vout,"amount"); - tx->outpoints[i].interest = SATOSHIDEN * jdouble(vout,"interest"); - if ( (sobj= jobj(vout,"scriptPubKey")) != 0 ) - { - if ( (addresses= jarray(&n,sobj,"addresses")) != 0 && n > 0 ) - { - //printf("%s\n",jprint(addresses,0)); - if ( n > 1 ) - printf("LP_transactioninit: txid.(%s) multiple addresses.[%s]\n",bits256_str(str,txid),jprint(addresses,0)); - if ( (address= jstri(addresses,0)) != 0 && strlen(address) < sizeof(tx->outpoints[i].coinaddr) ) - { - strcpy(tx->outpoints[i].coinaddr,address); - if ( 0 && strcmp(address,"RXzsovGBQ3W97xnVC6JnWxXsV4qb7p7iBi") == 0 ) - printf("%s %.8f at height.%d\n",address,dstr(tx->outpoints[i].value),height); - } - } - } - } - } - if ( iter == 1 && vins != 0 ) - { - for (i=0; inumvouts ) - { - tx->outpoints[spentvout].spendtxid = txid; - tx->outpoints[spentvout].spendvini = i; - tx->outpoints[spentvout].spendheight = height; - //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\n",bits256_str(str,spenttxid),spentvout,tx->numvouts); - } //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(0); - } else printf("LP_transactioninit error for %s %s\n",coin->symbol,bits256_str(str,txid)); - return(-1); -} - int32_t LP_blockinit(struct iguana_info *coin,int32_t height) { - int32_t i,iter,numtx,checkht=-1; cJSON *blockobj,*txs; bits256 txid; struct LP_transaction *tx; - if ( (blockobj= LP_blockjson(&checkht,coin->symbol,0,height)) != 0 ) + int32_t i,iter,numtx,checkht=-1; cJSON *blockobj,*txs,*txobj; bits256 txid; struct LP_transaction *tx; + if ( (blockobj= LP_blockjson(&checkht,coin->symbol,0,height)) != 0 && checkht == height ) { if ( (txs= jarray(&numtx,blockobj,"tx")) != 0 ) { for (iter=0; iter<2; iter++) - for (i=0; iheight == 0 ) - tx->height = height; - else if ( tx->height != height ) + txid = jbits256i(txs,i); + if ( (tx= LP_transactionfind(coin,txid)) != 0 ) { - printf("LP_blockinit: tx->height %d != %d\n",tx->height,height); - tx->height = height; - } - if ( iter == 1 ) - LP_transactioninit(coin,txid,iter); - } else LP_transactioninit(coin,txid,iter); + if ( tx->height == 0 ) + tx->height = height; + else if ( tx->height != height ) + { + printf("LP_blockinit: tx->height %d != %d\n",tx->height,height); + tx->height = height; + } + if ( iter == 1 ) + txobj = LP_transactioninit(coin,txid,iter,0); + } else txobj = LP_transactioninit(coin,txid,iter,0); + if ( txobj != 0 ) + free_json(txobj), txobj = 0; + } } } free_json(blockobj); @@ -259,11 +68,47 @@ int32_t LP_scanblockchain(struct iguana_info *coin,int32_t startheight,int32_t e } n++; if ( (n % 1000) == 0 ) - fprintf(stderr,"%.1f%% ",100. * (double)n/(endheight-startheight+1)); + printf("%.1f%% ",100. * (double)n/(endheight-startheight+1)); } return(endheight); } +char *banned_txids[] = +{ + "78cb4e21245c26b015b888b14c4f5096e18137d2741a6de9734d62b07014dfca", //233559 + "00697be658e05561febdee1aafe368b821ca33fbb89b7027365e3d77b5dfede5", //234172 + "e909465788b32047c472d73e882d79a92b0d550f90be008f76e1edaee6d742ea", //234187 + "f56c6873748a327d0b92b8108f8ec8505a2843a541b1926022883678fb24f9dc", //234188 + "abf08be07d8f5b3a433ddcca7ef539e79a3571632efd6d0294ec0492442a0204", //234213 + "3b854b996cc982fba8c06e76cf507ae7eed52ab92663f4c0d7d10b3ed879c3b0", //234367 + "fa9e474c2cda3cb4127881a40eb3f682feaba3f3328307d518589024a6032cc4", //234635 + "ca746fa13e0113c4c0969937ea2c66de036d20274efad4ce114f6b699f1bc0f3", //234662 + "43ce88438de4973f21b1388ffe66e68fda592da38c6ef939be10bb1b86387041", //234697 + "0aeb748de82f209cd5ff7d3a06f65543904c4c17387c9d87c65fd44b14ad8f8c", //234899 + "bbd3a3d9b14730991e1066bd7c626ca270acac4127131afe25f877a5a886eb25", //235252 + "fa9943525f2e6c32cbc243294b08187e314d83a2870830180380c3c12a9fd33c", //235253 + "a01671c8775328a41304e31a6693bbd35e9acbab28ab117f729eaba9cb769461", //235265 + "2ef49d2d27946ad7c5d5e4ab5c089696762ff04e855f8ab48e83bdf0cc68726d", //235295 + "c85dcffb16d5a45bd239021ad33443414d60224760f11d535ae2063e5709efee", //235296 + // all vouts banned + "c4ea1462c207547cd6fb6a4155ca6d042b22170d29801a465db5c09fec55b19d", //246748 + "305dc96d8bc23a69d3db955e03a6a87c1832673470c32fe25473a46cc473c7d1", //247204 +}; + +int32_t komodo_bannedset(int32_t *indallvoutsp,bits256 *array,int32_t max) +{ + int32_t i; + if ( sizeof(banned_txids)/sizeof(*banned_txids) > max ) + { + printf("komodo_bannedset: buffer too small %ld vs %d\n",(long)sizeof(banned_txids)/sizeof(*banned_txids),max); + exit(-1); + } + for (i=0; isymbol,lastcoin) == 0 ) @@ -325,14 +173,29 @@ cJSON *LP_snapshot(struct iguana_info *coin,int32_t height) } } portable_mutex_lock(&coin->txmutex); + portable_mutex_lock(&coin->addrmutex); HASH_ITER(hh,coin->addresses,ap,atmp) { ap->balance = 0; } + isKMD = (strcmp(coin->symbol,"KMD") == 0) ? 1 : 0; HASH_ITER(hh,coin->transactions,tx,tmp) { if ( tx->height < height ) { + if ( isKMD != 0 ) + { + for (j=0; jtxid) == 0 ) + break; + if ( j < numbanned ) + { + for (i=0; inumvouts; i++) + banned_balance += tx->outpoints[i].value; + //char str[256]; printf("skip banned %s bannedtotal: %.8f\n",bits256_str(str,tx->txid),dstr(banned_balance)); + continue; + } + } for (i=0; inumvouts; i++) { if ( (ht=tx->outpoints[i].spendheight) > 0 && ht < height ) @@ -347,6 +210,7 @@ cJSON *LP_snapshot(struct iguana_info *coin,int32_t height) } } HASH_SORT(coin->addresses,sort_balance); + portable_mutex_unlock(&coin->addrmutex); portable_mutex_unlock(&coin->txmutex); printf("%s balance %.8f at height.%d\n",coin->symbol,dstr(balance),height); array = cJSON_CreateArray(); @@ -362,12 +226,64 @@ cJSON *LP_snapshot(struct iguana_info *coin,int32_t height) } } jadd(retjson,"balances",array); + jaddstr(retjson,"coin",coin->symbol); + jaddnum(retjson,"height",height); jaddnum(retjson,"numaddresses",n); jaddnum(retjson,"total",dstr(balance)); jaddnum(retjson,"noaddr_total",dstr(noaddr_balance)); return(retjson); } +char *LP_snapshot_balance(struct iguana_info *coin,int32_t height,cJSON *argjson) +{ + cJSON *snapjson,*retjson,*balances,*array,*addrs,*child,*item,*item2; char *coinaddr,*refaddr; int32_t i,n,j,m; uint64_t total=0,value,balance = 0; + retjson = cJSON_CreateObject(); + array = cJSON_CreateArray(); + if ( (snapjson= LP_snapshot(coin,height)) != 0 ) + { + total = jdouble(snapjson,"total") * SATOSHIDEN; + if ( (addrs= jarray(&m,argjson,"addresses")) != 0 ) + { + if ( (balances= jarray(&n,snapjson,"balances")) != 0 ) + { + for (i=0; ichild) != 0 ) + { + value = (uint64_t)(child->valuedouble * SATOSHIDEN); + if ( (refaddr= get_cJSON_fieldname(child)) != 0 ) + { + //printf("check %s %.8f against %d\n",refaddr,dstr(value),m); + for (j=0; jsymbol); + jaddnum(retjson,"height",height); + jaddnum(retjson,"balance",dstr(balance)); + jaddnum(retjson,"total",dstr(total)); + return(jprint(retjson,1)); +} + char *LP_dividends(struct iguana_info *coin,int32_t height,cJSON *argjson) { cJSON *array,*retjson,*item,*child,*exclude=0; int32_t i,j,emitted=0,dusted=0,n,execflag=0,flag,iter,numexcluded=0; char buf[1024],*field,*prefix="",*suffix=""; uint64_t dustsum=0,excluded=0,total=0,dividend=0,value,val,emit=0,dust=0; double ratio = 1.; @@ -475,54 +391,7 @@ char *LP_dividends(struct iguana_info *coin,int32_t height,cJSON *argjson) return(clonestr("{\"error\":\"symbol not found\"}")); } -int64_t basilisk_txvalue(char *symbol,bits256 txid,int32_t vout) -{ - char destaddr[64]; uint64_t value,interest = 0; struct iguana_info *coin; - if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) - return(0); - //char str[65]; printf("%s txvalue.(%s)\n",symbol,bits256_str(str,txid)); - value = LP_txinterestvalue(&interest,destaddr,coin,txid,vout); - return(value + interest); -} - -uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout) -{ - struct LP_transaction *tx; char _coinaddr[64]; uint64_t interest = 0,value = 0; struct iguana_info *coin; - if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) - return(0); - if ( coinaddr != 0 ) - coinaddr[0] = 0; - if ( (tx= LP_transactionfind(coin,txid)) != 0 ) - { - if ( vout < tx->numvouts ) - { - if ( bits256_nonz(tx->outpoints[vout].spendtxid) != 0 ) - { - //char str[65]; printf("%s/v%d is spent\n",bits256_str(str,txid),vout); - return(0); - } - else - { - if ( coinaddr != 0 ) - value = LP_txinterestvalue(&tx->outpoints[vout].interest,coinaddr,coin,txid,vout); - //printf("return value %.8f + interest %.8f\n",dstr(tx->outpoints[vout].value),dstr(tx->outpoints[vout].interest)); - return(tx->outpoints[vout].value + tx->outpoints[vout].interest); - } - } else printf("vout.%d >= tx->numvouts.%d\n",vout,tx->numvouts); - } - if ( tx == 0 ) - { - LP_transactioninit(coin,txid,0); - LP_transactioninit(coin,txid,1); - } - if ( coinaddr == 0 ) - coinaddr = _coinaddr; - value = LP_txinterestvalue(&interest,coinaddr,coin,txid,vout); - //printf("coinaddr.(%s) value %.8f interest %.8f\n",coinaddr,dstr(value),dstr(interest)); - return(value + interest); -} - -int32_t LP_spendsearch(bits256 *spendtxidp,int32_t *indp,char *symbol,bits256 searchtxid,int32_t searchvout) +int32_t LP_spendsearch(char *coinaddr,bits256 *spendtxidp,int32_t *indp,char *symbol,bits256 searchtxid,int32_t searchvout) { struct LP_transaction *tx; struct iguana_info *coin; *indp = -1; @@ -535,6 +404,7 @@ int32_t LP_spendsearch(bits256 *spendtxidp,int32_t *indp,char *symbol,bits256 se { *spendtxidp = tx->outpoints[searchvout].spendtxid; *indp = tx->outpoints[searchvout].spendvini; + LP_swap_getcoinaddr(symbol,coinaddr,*spendtxidp,*indp); return(tx->outpoints[searchvout].spendheight); } } @@ -543,10 +413,10 @@ int32_t LP_spendsearch(bits256 *spendtxidp,int32_t *indp,char *symbol,bits256 se int32_t LP_mempoolscan(char *symbol,bits256 searchtxid) { - int32_t i,n; cJSON *array; bits256 txid; struct iguana_info *coin; struct LP_transaction *tx; - if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) + int32_t i,n; cJSON *array,*txobj; bits256 txid; 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 ) + if ( (array= LP_getmempool(symbol,0)) != 0 ) { if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) { @@ -555,8 +425,10 @@ int32_t LP_mempoolscan(char *symbol,bits256 searchtxid) txid = jbits256i(array,i); if ( (tx= LP_transactionfind(coin,txid)) == 0 ) { - LP_transactioninit(coin,txid,0); - LP_transactioninit(coin,txid,1); + txobj = LP_transactioninit(coin,txid,0,0); + txobj = LP_transactioninit(coin,txid,1,txobj); + if ( txobj != 0 ) + free_json(txobj); } if ( bits256_cmp(txid,searchtxid) == 0 ) { @@ -570,55 +442,85 @@ int32_t LP_mempoolscan(char *symbol,bits256 searchtxid) return(-1); } -int32_t LP_numconfirms(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx,int32_t mempool) +int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t duration) { - struct iguana_info *coin; int32_t numconfirms = 100; -//#ifndef BASILISK_DISABLEWAITTX - cJSON *txobj; - if ( (coin= LP_coinfind(rawtx->coin->symbol)) == 0 || coin->inactive != 0 ) - return(-1); - numconfirms = -1; - if ( (txobj= LP_gettx(rawtx->coin->symbol,rawtx->I.signedtxid)) != 0 ) + struct iguana_info *coin; cJSON *array,*item; uint32_t expiration,i,n; int32_t numconfirms = -1; + if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) { - numconfirms = jint(txobj,"confirmations"); - free_json(txobj); + printf("LP_waitmempool missing coin.%p or inactive\n",coin); + return(-1); } - else if ( mempool != 0 && LP_mempoolscan(rawtx->coin->symbol,rawtx->I.signedtxid) >= 0 ) - numconfirms = 0; -//#endif - return(numconfirms); -} - -int32_t LP_waitmempool(char *symbol,bits256 txid,int32_t duration) -{ - uint32_t expiration = (uint32_t)time(NULL) + duration; - while ( time(NULL) < expiration ) + expiration = (uint32_t)time(NULL) + duration; + while ( 1 ) { - if ( LP_mempoolscan(symbol,txid) >= 0 ) - return(0); - usleep(500000); + if ( LP_gettx_presence(symbol,txid) != 0 ) + numconfirms = 0; + else + { + if ( coin->electrum == 0 ) + { + if ( LP_mempoolscan(symbol,txid) >= 0 ) + numconfirms = 0; + } + else + { + if ( (array= electrum_address_getmempool(symbol,coin->electrum,&array,coinaddr)) != 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; isymbol,coinaddr,1); + 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 ) + free_json(array); + if ( coin->height >= up->U.height ) + numconfirms = (coin->height - up->U.height + 1); + } + } + } + if ( time(NULL) > expiration || numconfirms >= 0 ) + break; + sleep(10); } - return(-1); + //if ( numconfirms <= 0 ) + // numconfirms = LP_numconfirms(symbol,coinaddr,txid,vout,1); // no, no recursion occurs! + return(numconfirms); } -int32_t LP_mempool_vinscan(bits256 *spendtxidp,int32_t *spendvinp,char *symbol,bits256 searchtxid,int32_t searchvout,bits256 searchtxid2,int32_t searchvout2) +int32_t LP_mempool_vinscan(bits256 *spendtxidp,int32_t *spendvinp,char *symbol,char *coinaddr,bits256 searchtxid,int32_t searchvout,bits256 searchtxid2,int32_t searchvout2) { - struct iguana_info *coin; int32_t selector; cJSON *array; + struct iguana_info *coin; int32_t selector; cJSON *array; char addr[64]; if ( symbol == 0 || symbol[0] == 0 || bits256_nonz(searchtxid) == 0 || bits256_nonz(searchtxid2) == 0 ) return(-1); if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) return(-1); if ( time(NULL) > coin->lastmempool+LP_MEMPOOL_TIMEINCR ) { - if ( (array= LP_getmempool(symbol)) != 0 ) + if ( (array= LP_getmempool(symbol,coinaddr)) != 0 ) { free_json(array); coin->lastmempool = (uint32_t)time(NULL); } } - if ( (selector= LP_spendsearch(spendtxidp,spendvinp,symbol,searchtxid,searchvout)) >= 0 ) + if ( (selector= LP_spendsearch(addr,spendtxidp,spendvinp,symbol,searchtxid,searchvout)) >= 0 ) return(selector); - else if ( (selector= LP_spendsearch(spendtxidp,spendvinp,symbol,searchtxid2,searchvout2)) >= 0 ) + else if ( (selector= LP_spendsearch(addr,spendtxidp,spendvinp,symbol,searchtxid2,searchvout2)) >= 0 ) return(selector); return(-1); } diff --git a/iguana/exchanges/LP_secp.c b/iguana/exchanges/LP_secp.c index 7d4409911..9c7032e23 100644 --- a/iguana/exchanges/LP_secp.c +++ b/iguana/exchanges/LP_secp.c @@ -179,7 +179,7 @@ int32_t bitcoin_verify(void *ctx,uint8_t *sig,int32_t siglen,bits256 txhash2,uin secp256k1_ecdsa_signature_parse_der(ctx,&SIG,sig,siglen); if ( secp256k1_ecdsa_verify(ctx,&SIG,txhash2.bytes,&PUB) != 0 ) retval = 0; - } + } else printf("error parsing pubkey\n"); ENDSECP_ENSURE_CTX } return(retval); diff --git a/iguana/exchanges/LP_signatures.c b/iguana/exchanges/LP_signatures.c new file mode 100644 index 000000000..6e99495cb --- /dev/null +++ b/iguana/exchanges/LP_signatures.c @@ -0,0 +1,730 @@ + +/****************************************************************************** + * 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_signatures.c +// marketmaker +// + +struct basilisk_request *LP_requestinit(struct basilisk_request *rp,bits256 srchash,bits256 desthash,char *src,uint64_t srcsatoshis,char *dest,uint64_t destsatoshis,uint32_t timestamp,uint32_t quotetime,int32_t DEXselector) +{ + struct basilisk_request R; + memset(rp,0,sizeof(*rp)); + rp->srchash = srchash; + rp->srcamount = srcsatoshis; + rp->timestamp = timestamp; + rp->DEXselector = DEXselector; + safecopy(rp->src,src,sizeof(rp->src)); + safecopy(rp->dest,dest,sizeof(rp->dest)); + R = *rp; + rp->requestid = basilisk_requestid(rp); + rp->quotetime = quotetime; + 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)); + return(rp); +} + +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 ) + jaddstr(retjson,"address",qp->coinaddr); + if ( qp->timestamp != 0 ) + jaddnum(retjson,"timestamp",qp->timestamp); + if ( bits256_nonz(qp->txid) != 0 ) + { + jaddbits256(retjson,"txid",qp->txid); + jaddnum(retjson,"vout",qp->vout); + } + if ( bits256_nonz(qp->srchash) != 0 ) + jaddbits256(retjson,"srchash",qp->srchash); + if ( qp->txfee != 0 ) + jadd64bits(retjson,"txfee",qp->txfee); + if ( qp->quotetime != 0 ) + jaddnum(retjson,"quotetime",qp->quotetime); + if ( qp->satoshis != 0 ) + jadd64bits(retjson,"satoshis",qp->satoshis); + if ( bits256_nonz(qp->desthash) != 0 ) + jaddbits256(retjson,"desthash",qp->desthash); + if ( bits256_nonz(qp->txid2) != 0 ) + { + jaddbits256(retjson,"txid2",qp->txid2); + jaddnum(retjson,"vout2",qp->vout2); + } + if ( bits256_nonz(qp->desttxid) != 0 ) + { + if ( qp->destaddr[0] != 0 ) + jaddstr(retjson,"destaddr",qp->destaddr); + jaddbits256(retjson,"desttxid",qp->desttxid); + jaddnum(retjson,"destvout",qp->destvout); + } + if ( bits256_nonz(qp->feetxid) != 0 ) + { + jaddbits256(retjson,"feetxid",qp->feetxid); + jaddnum(retjson,"feevout",qp->feevout); + } + if ( qp->desttxfee != 0 ) + jadd64bits(retjson,"desttxfee",qp->desttxfee); + if ( qp->destsatoshis != 0 ) + { + jadd64bits(retjson,"destsatoshis",qp->destsatoshis); + if ( qp->satoshis != 0 ) + { + price = (double)qp->destsatoshis / (qp->satoshis - qp->txfee); + jaddnum(retjson,"price",price); + } + } + if ( qp->R.requestid != 0 ) + jaddnum(retjson,"requestid",qp->R.requestid); + if ( qp->R.quoteid != 0 ) + jaddnum(retjson,"quoteid",qp->R.quoteid); + return(retjson); +} + +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"); + qp->txid2 = jbits256(argjson,"txid2"); + qp->vout = jint(argjson,"vout"); + qp->vout2 = jint(argjson,"vout2"); + qp->feevout = jint(argjson,"feevout"); + qp->srchash = jbits256(argjson,"srchash"); + qp->desttxid = jbits256(argjson,"desttxid"); + qp->feetxid = jbits256(argjson,"feetxid"); + qp->destvout = jint(argjson,"destvout"); + qp->desthash = jbits256(argjson,"desthash"); + qp->satoshis = j64bits(argjson,"satoshis"); + qp->destsatoshis = j64bits(argjson,"destsatoshis"); + qp->txfee = j64bits(argjson,"txfee"); + qp->desttxfee = j64bits(argjson,"desttxfee"); + qp->R.requestid = juint(argjson,"requestid"); + qp->R.quoteid = juint(argjson,"quoteid"); + if ( qp->R.requestid == 0 ) + { + 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); + if ( qp->R.quoteid != 0 && qp->R.quoteid != qid ) + printf("quoteid.%u -> %u\n",qp->R.quoteid,qid); + qp->R.quoteid = qid; + } + return(0); +} + +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)); +} + +int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char *destcoin,double price,uint64_t satoshis,uint64_t destsatoshis) +{ + memset(qp,0,sizeof(*qp)); + if ( qp->timestamp == 0 ) + qp->timestamp = (uint32_t)time(NULL); + safecopy(qp->destcoin,destcoin,sizeof(qp->destcoin)); + LP_txfees(&qp->txfee,&qp->desttxfee,utxo->coin,qp->destcoin); + qp->satoshis = satoshis;//(destsatoshis / price) + 0.49; + qp->destsatoshis = destsatoshis; + /*if ( qp->txfee >= qp->satoshis || qp->txfee >= utxo->deposit.value || utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis) ) //utxo->iambob == 0 || + { + printf("quoteinit error.(%d %d %d %d) %.8f vs %.8f\n",utxo->iambob == 0,qp->txfee >= qp->satoshis,qp->txfee >= utxo->deposit.value,utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis),dstr(utxo->deposit.value),dstr(LP_DEPOSITSATOSHIS(qp->satoshis))); + return(-1); + }*/ + qp->txid = utxo->payment.txid; + qp->vout = utxo->payment.vout; + qp->txid2 = utxo->deposit.txid; + qp->vout2 = utxo->deposit.vout; + if ( qp->desttxfee >= qp->destsatoshis ) + { + printf("quoteinit desttxfee %.8f < %.8f destsatoshis\n",dstr(qp->desttxfee),dstr(qp->destsatoshis)); + return(-2); + } + safecopy(qp->srccoin,utxo->coin,sizeof(qp->srccoin)); + safecopy(qp->coinaddr,utxo->coinaddr,sizeof(qp->coinaddr)); + qp->srchash = utxo->pubkey; + return(0); +} + +int32_t LP_quotedestinfo(struct LP_quoteinfo *qp,bits256 desttxid,int32_t destvout,bits256 feetxid,int32_t feevout,bits256 desthash,char *destaddr) +{ + qp->desttxid = desttxid; + qp->destvout = destvout; + qp->desthash = desthash; + qp->feetxid = feetxid; + qp->feevout = feevout; + safecopy(qp->destaddr,destaddr,sizeof(qp->destaddr)); + return(0); +} + +char *LP_quotereceived(cJSON *argjson) +{ + 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 ) + { + ptr->Q = Q; + printf(">>>>>>>>>> received quote %s/%s %.8f\n",Q.srccoin,Q.destcoin,price); + return(clonestr("{\"result\":\"updated\"}")); + } else return(clonestr("{\"error\":\"nullptr\"}")); +} + +int32_t LP_bitcoinsig_add(cJSON *item,bits256 priv,uint8_t *pubsecp,bits256 sighash) +{ + static void *ctx; int32_t i,j,siglen; uint8_t pub33[33],sig[65]; char sigstr[256]; + if ( ctx == 0 ) + ctx = bitcoin_ctx(); + for (j=0; j<100; j++) + { + if ( (siglen= bitcoin_sign(ctx,"sigadd",sig,sighash,priv,1)) > 0 && siglen == 65 ) + { + memset(pub33,0,33); + if ( bitcoin_recoververify(ctx,"test",sig,sighash,pub33,0) == 0 && memcmp(pub33,pubsecp,33) == 0 ) + { + init_hexbytes_noT(sigstr,sig,siglen); + jaddstr(item,"sig",sigstr); + return(siglen); + } + if ( 0 ) + { + for (i=0; i<33; i++) + printf("%02x",pubsecp[i]); + printf(" pubsecp -> "); + for (i=0; i<33; i++) + printf("%02x",pub33[i]); + printf(" mismatched recovered pubkey.%d of %d\n",j,100); + } + } + } + return(-1); +} + +bits256 LP_price_sighash(uint32_t timestamp,uint8_t *pubsecp,bits256 pubkey,char *base,char *rel,uint64_t price64) +{ + uint8_t buf[sizeof(pubkey) + 33 + sizeof(uint64_t)*3 + sizeof(timestamp)]; uint64_t basebits,relbits; bits256 sighash; + basebits = stringbits(base); + relbits = stringbits(rel); + memcpy(buf,pubkey.bytes,sizeof(pubkey)); + memcpy(&buf[sizeof(pubkey)],pubsecp,33); + memcpy(&buf[sizeof(pubkey)+33],&price64,sizeof(price64)); + memcpy(&buf[sizeof(pubkey)+33+sizeof(price64)],&basebits,sizeof(basebits)); + memcpy(&buf[sizeof(pubkey)+33+sizeof(price64)+sizeof(basebits)],&relbits,sizeof(relbits)); + memcpy(&buf[sizeof(pubkey)+33+sizeof(price64)+sizeof(basebits)+sizeof(relbits)],×tamp,sizeof(timestamp)); + vcalc_sha256(0,sighash.bytes,buf,sizeof(buf)); + return(sighash); +} + +bits256 LP_pubkey_sighash(uint32_t timestamp,bits256 pubkey,uint8_t *rmd160,uint8_t *pubsecp) +{ + uint8_t buf[sizeof(pubkey) + 20 + 33 + sizeof(timestamp)]; bits256 sighash; + memcpy(buf,pubkey.bytes,sizeof(pubkey)); + memcpy(&buf[sizeof(pubkey)],rmd160,20); + memcpy(&buf[sizeof(pubkey)+20],pubsecp,33); + memcpy(&buf[sizeof(pubkey)+20+33],×tamp,sizeof(timestamp)); + vcalc_sha256(0,sighash.bytes,buf,sizeof(buf)); + return(sighash); +} + +bits256 LP_utxos_sighash(uint32_t timestamp,uint8_t *pubsecp,bits256 pubkey,bits256 utxoshash) +{ + uint8_t buf[sizeof(pubkey)+sizeof(utxoshash)+33+sizeof(timestamp)]; bits256 sighash; + memcpy(buf,pubkey.bytes,sizeof(pubkey)); + memcpy(&buf[sizeof(pubkey)],pubsecp,33); + memcpy(&buf[sizeof(pubkey)+33],×tamp,sizeof(timestamp)); + memcpy(&buf[sizeof(pubkey)+33+sizeof(timestamp)],utxoshash.bytes,sizeof(utxoshash)); + vcalc_sha256(0,sighash.bytes,buf,sizeof(buf)); + return(sighash); +} + +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; + if ( ctx == 0 ) + ctx = bitcoin_ctx(); + pubp = LP_pubkeyfind(pubkey); + if ( (pubp == 0 || pubp->numerrors < LP_MAXPUBKEY_ERRORS) && sigstr != 0 && pubsecpstr != 0 && strlen(sigstr) == 65*2 && strlen(pubsecpstr) == 33 *2 ) + { + decode_hex(sig,65,sigstr); + decode_hex(pubsecp,33,pubsecpstr); + sighash = LP_utxos_sighash(timestamp,pubsecp,pubkey,utxoshash); + retval = bitcoin_recoververify(ctx,"utxos",sig,sighash,pub33,0); + if ( memcmp(pub33,pubsecp,33) != 0 || retval != 0 ) + { + static uint32_t counter; + if ( counter++ <= LP_MAXPUBKEY_ERRORS ) + { + if ( pubp != 0 ) + pubp->numerrors++; + 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; + } + return(retval); +} + +bits256 LP_utxoshash_calc(cJSON *array) +{ + int32_t i,j,n; bits256 utxoshash,txid; cJSON *item; + memset(utxoshash.bytes,0,sizeof(utxoshash)); + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; ismartaddr); + if ( cJSON_GetArraySize(array) == 0 ) + free_json(array); + else + { + memset(zero.bytes,0,sizeof(zero)); + jaddstr(reqjson,"method","postutxos"); + jaddstr(reqjson,"coin",symbol); + jaddstr(reqjson,"coinaddr",coinaddr); + jadd(reqjson,"utxos",array); + timestamp = (uint32_t)time(NULL); + jaddnum(reqjson,"timetamp",timestamp); + init_hexbytes_noT(pubsecpstr,G.LP_pubsecp,33); + jaddstr(reqjson,"pubsecp",pubsecpstr); + jaddbits256(reqjson,"pubkey",G.LP_mypub25519); + utxoshash = LP_utxoshash_calc(array); + //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(0,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; +printf("LP_postutxos_recv deprecated\n"); + 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\"}")); + } //else printf("valid utxos sig %s\n",bits256_str(str,pubp->pubkey)); + } + 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; + if ( ctx == 0 ) + ctx = bitcoin_ctx(); + pubp = LP_pubkeyfind(pubkey); + if ( (pubp == 0 || pubp->numerrors < LP_MAXPUBKEY_ERRORS) && sigstr != 0 && pubsecpstr != 0 && strlen(sigstr) == 65*2 && strlen(pubsecpstr) == 33 *2 ) + { + decode_hex(sig,65,sigstr); + decode_hex(pubsecp,33,pubsecpstr); + sighash = LP_price_sighash(timestamp,pubsecp,pubkey,base,rel,price64); + retval = bitcoin_recoververify(ctx,"price",sig,sighash,pub33,0); + if ( memcmp(pub33,pubsecp,33) != 0 || retval != 0 ) + { + if ( pubp != 0 ) + pubp->numerrors++; + printf("LP_price_sigcheck failure\n"); + retval = -1; + } + else + { + retval = 0; + //printf("valid price sig %s/%s %.8f\n",base,rel,dstr(price64)); + } + } + return(retval); +} + +int32_t LP_price_sigadd(cJSON *item,uint32_t timestamp,bits256 priv,uint8_t *pubsecp,bits256 pubkey,char *base,char *rel,uint64_t price64) +{ + bits256 sighash; + sighash = LP_price_sighash(timestamp,pubsecp,pubkey,base,rel,price64); + return(LP_bitcoinsig_add(item,priv,pubsecp,sighash)); +} + +char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *rel,double price) +{ + struct iguana_info *basecoin,*relcoin; struct LP_address *ap; char pubsecpstr[67]; uint32_t numutxos,timestamp; uint64_t price64,balance,minsize,maxsize; bits256 zero; cJSON *reqjson; + reqjson = cJSON_CreateObject(); + // LP_addsig + if ( (basecoin= LP_coinfind(base)) != 0 && (relcoin= LP_coinfind(rel)) != 0 && basecoin->electrum == 0 )//&& relcoin->electrum == 0 ) + { + memset(zero.bytes,0,sizeof(zero)); + jaddbits256(reqjson,"pubkey",G.LP_mypub25519); + jaddstr(reqjson,"base",base); + jaddstr(reqjson,"rel",rel); + price64 = price * SATOSHIDEN + 0.0000000049; + jaddnum(reqjson,"price",price); + jadd64bits(reqjson,"price64",price64); + jaddstr(reqjson,"method","postprice"); + timestamp = (uint32_t)time(NULL); + jaddnum(reqjson,"timestamp",timestamp); + init_hexbytes_noT(pubsecpstr,G.LP_pubsecp,33); + jaddstr(reqjson,"pubsecp",pubsecpstr); + if ( (ap= LP_address(basecoin,basecoin->smartaddr)) != 0 ) + { + if ( (numutxos= LP_address_minmax(&balance,&minsize,&maxsize,ap)) != 0 ) + { + //printf("%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(0,base,rel,zero,jprint(reqjson,1)); + return(clonestr("{\"result\":\"success\"}")); + } else return(clonestr("{\"error\":\"electrum node cant post bob asks\"}")); +} + +char *LP_postprice_recv(cJSON *argjson) +{ + bits256 pubkey; double price; char *base,*rel; + //printf("PRICE POSTED.(%s)\n",jprint(argjson,0)); + if ( (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 && (price= jdouble(argjson,"price")) > SMALLVAL ) + { + pubkey = jbits256(argjson,"pubkey"); + if ( bits256_nonz(pubkey) != 0 ) + { + 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,jstr(argjson,"utxocoin"),jint(argjson,"n"),jdouble(argjson,"bal")*SATOSHIDEN,jdouble(argjson,"min")*SATOSHIDEN,jdouble(argjson,"max")*SATOSHIDEN); + return(clonestr("{\"result\":\"success\"}")); + } else return(clonestr("{\"error\":\"sig failure\"}")); + } + } + return(clonestr("{\"error\":\"missing fields in posted price\"}")); +} + +int32_t _LP_pubkey_sigcheck(uint8_t *sig,int32_t siglen,uint32_t timestamp,bits256 pub,uint8_t *rmd160,uint8_t *pubsecp) +{ + static void *ctx; uint8_t pub33[33]; bits256 sighash; + if ( ctx == 0 ) + ctx = bitcoin_ctx(); + sighash = LP_pubkey_sighash(timestamp,pub,rmd160,pubsecp); + return(bitcoin_recoververify(ctx,"pubkey",sig,sighash,pub33,0)); +} + +int32_t LP_pubkey_sigadd(cJSON *item,uint32_t timestamp,bits256 priv,bits256 pub,uint8_t *rmd160,uint8_t *pubsecp) +{ + bits256 sighash; + sighash = LP_pubkey_sighash(timestamp,pub,rmd160,pubsecp); + return(LP_bitcoinsig_add(item,priv,pubsecp,sighash)); +} + +int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *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) ) + { + decode_hex(rmd160,sizeof(rmd160),hexstr); + memset(zeroes,0,sizeof(zeroes)); + if ( memcmp(zeroes,rmd160,sizeof(rmd160)) != 0 ) + { + //if ( memcmp(rmd160,pubp->rmd160,20) != 0 ) + { + if ( (pubsecpstr= jstr(item,"pubsecp")) != 0 && is_hexstr(pubsecpstr,0) == 66 ) + { + decode_hex(pubsecp,sizeof(pubsecp),pubsecpstr); + calc_rmd160_sha256(checkrmd160,pubsecp,33); + if ( memcmp(checkrmd160,rmd160,20) == 0 ) + { + if ( (sigstr= jstr(item,"sig")) != 0 && (len= is_hexstr(sigstr,0)) == 65*2 ) + { + siglen = len >> 1; + decode_hex(sig,siglen,sigstr); + if ( _LP_pubkey_sigcheck(sig,siglen,juint(item,"timestamp"),pubp->pubkey,rmd160,pubsecp) == 0 ) + { + if ( memcmp(rmd160,pubp->rmd160,20) != 0 ) + { + //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 = juint(item,"timestamp"); + retval = 0; + } else pubp->numerrors++; + } + } + else if ( 0 ) + { + for (i=0; i<20; i++) + printf("%02x",rmd160[i]); + printf(" rmd160 vs "); + for (i=0; i<20; i++) + printf("%02x",checkrmd160[i]); + printf(" for %s\n",pubsecpstr); + } + } + } + } + } + return(retval); +} + +void LP_notify_pubkeys(void *ctx,int32_t pubsock) +{ + 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); + jaddbits256(reqjson,"pub",G.LP_mypub25519); + init_hexbytes_noT(secpstr,G.LP_pubsecp,33); + jaddstr(reqjson,"pubsecp",secpstr); + 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); + 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; 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\"}")); +} + +void LP_smartutxos_push(struct iguana_info *coin) +{ + 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); + if ( (array= LP_address_utxos(coin,coin->smartaddr,1)) != 0 ) + { + memset(zero.bytes,0,sizeof(zero)); + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + //printf("PUSH %s %s\n",coin->symbol,coin->smartaddr); + for (i=0; isymbol); + jaddstr(req,"coinaddr",coin->smartaddr); + jaddbits256(req,"txid",txid); + jaddnum(req,"vout",vout); + jaddnum(req,"ht",height); + jadd64bits(req,"value",value); + //printf("ADDR_UNSPENTS[] <- %s\n",jprint(req,0)); + LP_reserved_msg(0,"","",zero,jprint(req,1)); + } + } + free_json(array); + } +} + +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"); + value = j64bits(argjson,"value"); + coinaddr = jstr(argjson,"coinaddr"); + if ( (symbol= jstr(argjson,"coin")) != 0 && coinaddr != 0 && (coin= LP_coinfind(symbol)) != 0 ) + { + //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((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\"}")); +} + +void LP_listunspent_query(char *symbol,char *coinaddr) +{ + bits256 zero; cJSON *reqjson = cJSON_CreateObject(); + memset(zero.bytes,0,sizeof(zero)); + jaddstr(reqjson,"method","addr_unspents"); + jaddstr(reqjson,"coin",symbol); + jaddstr(reqjson,"address",coinaddr); + LP_reserved_msg(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; + if ( strcmp(method,"request") == 0 ) + { + if ( LP_allocated(qp->desttxid,qp->destvout) == 0 && LP_allocated(qp->feetxid,qp->feevout) == 0 ) + { + LP_unavailableset(qp->desttxid,qp->destvout,qp->timestamp+LP_AUTOTRADE_TIMEOUT,qp->srchash); + LP_unavailableset(qp->feetxid,qp->feevout,qp->timestamp+LP_AUTOTRADE_TIMEOUT,qp->srchash); + } + else + { + printf("couldnt find my txid to make request\n"); + return; + } + } + reqjson = LP_quotejson(qp); + if ( bits256_nonz(qp->desthash) != 0 ) + flag = 1; + jaddbits256(reqjson,"pubkey",qp->srchash); + jaddstr(reqjson,"method",method); + jaddnum(reqjson,"timestamp",time(NULL)); + msg = jprint(reqjson,1); + msg2 = clonestr(msg); + printf("QUERY.(%s)\n",msg); + memset(&zero,0,sizeof(zero)); + portable_mutex_lock(&LP_reservedmutex); + if ( num_Reserved_msgs[1] < sizeof(Reserved_msgs[1])/sizeof(*Reserved_msgs[1])-2 ) + Reserved_msgs[1][num_Reserved_msgs[1]++] = msg; + if ( num_Reserved_msgs[0] < sizeof(Reserved_msgs[0])/sizeof(*Reserved_msgs[0])-2 ) + Reserved_msgs[0][num_Reserved_msgs[0]++] = msg2; + //LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,zero,msg2); + portable_mutex_unlock(&LP_reservedmutex); +} + diff --git a/iguana/exchanges/LP_socket.c b/iguana/exchanges/LP_socket.c new file mode 100644 index 000000000..f1a895b38 --- /dev/null +++ b/iguana/exchanges/LP_socket.c @@ -0,0 +1,1098 @@ +/****************************************************************************** + * 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. * + * * + ******************************************************************************/ + +/** + * - we need to include WinSock2.h header to correctly use windows structure + * as the application is still using 32bit structure from mingw so, we need to + * add the include based on checking + * @author - fadedreamz@gmail.com + * @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) +#define WIN32_LEAN_AND_MEAN +#include +#endif + +int32_t LP_socket(int32_t bindflag,char *hostname,uint16_t port) +{ + int32_t opt,sock,result; char ipaddr[64],checkipaddr[64]; struct timeval timeout; + struct sockaddr_in saddr; socklen_t addrlen,slen; + addrlen = sizeof(saddr); + struct hostent *hostent; + + /** + * gethostbyname() is deprecated and cause crash on x64 windows + * the solution is to implement similar functionality by using getaddrinfo() + * it is standard posix function and is correctly supported in win32/win64/linux + * @author - fadedreamz@gmail.com + */ +#if defined(_M_X64) + struct addrinfo *addrresult = NULL; + struct addrinfo *returnptr = NULL; + struct addrinfo hints; + struct sockaddr_in * sockaddr_ipv4; + int retVal; + int found = 0; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; +#endif + + if ( parse_ipaddr(ipaddr,hostname) != 0 ) + port = parse_ipaddr(ipaddr,hostname); + +#if defined(_M_X64) + retVal = getaddrinfo(ipaddr, NULL, &hints, &addrresult); + for (returnptr = addrresult; returnptr != NULL && found == 0; returnptr = returnptr->ai_next) { + switch (returnptr->ai_family) { + case AF_INET: + sockaddr_ipv4 = (struct sockaddr_in *) returnptr->ai_addr; + // we want to break from the loop after founding the first ipv4 address + found = 1; + break; + } + } + + // if we iterate through the loop and didn't find anything, + // that means we failed in the dns lookup + if (found == 0) { + printf("getaddrinfo(%s) returned error\n", hostname); + freeaddrinfo(addrresult); + return(-1); + } +#else + hostent = gethostbyname(ipaddr); + if ( hostent == NULL ) + { + printf("gethostbyname(%s) returned error: %d port.%d ipaddr.(%s)\n",hostname,errno,port,ipaddr); + return(-1); + } +#endif + saddr.sin_family = AF_INET; + saddr.sin_port = htons(port); + //#ifdef _WIN32 + // saddr.sin_addr.s_addr = (uint32_t)calc_ipbits("127.0.0.1"); + //#else + +#if defined(_M_X64) + saddr.sin_addr.s_addr = sockaddr_ipv4->sin_addr.s_addr; + // graceful cleanup + sockaddr_ipv4 = NULL; + freeaddrinfo(addrresult); +#else + memcpy(&saddr.sin_addr.s_addr,hostent->h_addr_list[0],hostent->h_length); +#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); + //#endif + if ( (sock= socket(AF_INET,SOCK_STREAM,0)) < 0 ) + { + if ( errno != ETIMEDOUT ) + printf("socket() failed: %s errno.%d", strerror(errno),errno); + return(-1); + } + opt = 1; + slen = sizeof(opt); + //printf("set keepalive.%d\n",setsockopt(sock,SOL_SOCKET,SO_KEEPALIVE,(void *)&opt,slen)); +#ifndef _WIN32 + if ( 1 )//&& bindflag != 0 ) + { + opt = 0; + getsockopt(sock,SOL_SOCKET,SO_KEEPALIVE,(void *)&opt,&slen); + opt = 1; + //printf("keepalive.%d\n",opt); + } + setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void *)&opt,sizeof(opt)); +#ifdef __APPLE__ + setsockopt(sock,SOL_SOCKET,SO_NOSIGPIPE,&opt,sizeof(opt)); +#endif +#endif + if ( bindflag == 0 ) + { + //printf("call connect sock.%d\n",sock); + result = connect(sock,(struct sockaddr *)&saddr,addrlen); + //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)); + if ( result != 0 ) + { + if ( errno != ECONNRESET && errno != ENOTCONN && errno != ECONNREFUSED && errno != ETIMEDOUT && errno != EHOSTUNREACH ) + { + //printf("%s(%s) port.%d failed: %s sock.%d. errno.%d\n",bindflag!=0?"bind":"connect",hostname,port,strerror(errno),sock,errno); + } + if ( sock >= 0 ) + closesocket(sock); + return(-1); + } + timeout.tv_sec = 10; + timeout.tv_usec = 0; + setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(void *)&timeout,sizeof(timeout)); + } + else + { + while ( (result= bind(sock,(struct sockaddr*)&saddr,addrlen)) != 0 ) + { + if ( errno == EADDRINUSE ) + { + sleep(1); + printf("ERROR BINDING PORT.%d. this is normal tcp timeout, unless another process is using port\n",port); + fflush(stdout); + sleep(3); + printf("%s(%s) port.%d try again: %s sock.%d. errno.%d\n",bindflag!=0?"bind":"connect",hostname,port,strerror(errno),sock,errno); + if ( bindflag == 1 ) + { + closesocket(sock); + return(-1); + } + sleep(13); + //continue; + } + if ( errno != ECONNRESET && errno != ENOTCONN && errno != ECONNREFUSED && errno != ETIMEDOUT && errno != EHOSTUNREACH ) + { + printf("%s(%s) port.%d failed: %s sock.%d. errno.%d\n",bindflag!=0?"bind":"connect",hostname,port,strerror(errno),sock,errno); + closesocket(sock); + return(-1); + } + } + if ( listen(sock,64) != 0 ) + { + printf("listen(%s) port.%d failed: %s sock.%d. errno.%d\n",hostname,port,strerror(errno),sock,errno); + if ( sock >= 0 ) + closesocket(sock); + return(-1); + } + } +#ifdef __APPLE__ + //timeout.tv_sec = 0; + //timeout.tv_usec = 30000; + //setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(void *)&timeout,sizeof(timeout)); + timeout.tv_sec = 0; + timeout.tv_usec = 10000; + setsockopt(sock,SOL_SOCKET,SO_SNDTIMEO,(void *)&timeout,sizeof(timeout)); +#endif + return(sock); +} + +int32_t LP_socketsend(int32_t sock,uint8_t *serialized,int32_t len) +{ + int32_t numsent,remains,flags = 0; +#ifndef _WIN32 + flags = MSG_NOSIGNAL; +#endif + remains = len; + while ( sock >= 0 && remains > 0 ) + { + if ( (numsent= (int32_t)send(sock,serialized,remains,flags)) < 0 ) + { + if ( errno == EAGAIN || errno == EWOULDBLOCK ) + { + sleep(1); + continue; + } + printf("(%s): numsent.%d vs remains.%d len.%d errno.%d (%s) usock.%d\n",serialized,numsent,remains,len,errno,strerror(errno),sock); + return(-errno); + } + else if ( remains > 0 ) + { + remains -= numsent; + serialized += numsent; + if ( remains > 0 ) + printf("%d LP_socket sent.%d remains.%d of len.%d\n",sock,numsent,remains,len); + } + //printf("numsent.%d vs remains.%d len.%d sock.%d\n",numsent,remains,len,sock); + } + return(len); +} + +int32_t LP_socketrecv(int32_t sock,uint8_t *recvbuf,int32_t maxlen) +{ + int32_t recvlen = -1; + while ( sock >= 0 ) + { + if ( (recvlen= (int32_t)recv(sock,recvbuf,maxlen,0)) < 0 ) + { + if ( errno == EAGAIN ) + { + //printf("%s recv errno.%d %s len.%d remains.%d\n",ipaddr,errno,strerror(errno),len,remains); + //printf("EAGAIN for len %d, remains.%d\n",len,remains); + sleep(1); + } else return(-errno); + } else break; + } + return(recvlen); +} + +struct electrum_info *Electrums[8192]; +int32_t Num_electrums; + +struct electrum_info *electrum_server(char *symbol,struct electrum_info *ep) +{ + struct electrum_info *rbuf[128],*recent_ep; uint32_t recent,mostrecent = 0; int32_t i,n = 0; + portable_mutex_lock(&LP_electrummutex); + if ( ep == 0 ) + { + //printf("find random electrum.%s from %d\n",symbol,Num_electrums); + memset(rbuf,0,sizeof(rbuf)); + recent_ep = 0; + recent = (uint32_t)time(NULL) - 300; + for (i=0; isymbol) == 0 && ep->sock >= 0 ) + { + if ( ep->lasttime > recent ) + { + rbuf[n++] = ep; + if ( n == sizeof(rbuf)/sizeof(*rbuf) ) + break; + } + else if ( ep->lasttime > mostrecent ) + { + mostrecent = ep->lasttime; + recent_ep = ep; + } + } + } + ep = recent_ep; + if ( n > 0 ) + { + i = (LP_rand() % n); + ep = rbuf[i]; + } + } + else if ( Num_electrums < sizeof(Electrums)/sizeof(*Electrums) ) + Electrums[Num_electrums++] = ep; + else printf("Electrum server pointer buf overflow %d\n",Num_electrums); + portable_mutex_unlock(&LP_electrummutex); + return(ep); +} + +int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep,char *coinaddr,cJSON *array,int32_t electrumflag) +{ + int32_t i,v,n,ht,flag = 0; char str[65]; uint64_t value; bits256 txid; cJSON *item,*retjson,*txobj; struct LP_transaction *tx; + if ( array != 0 && coin != 0 && (n= cJSON_GetArraySize(array)) > 0 ) + { + //printf("PROCESS %s/%s %s num.%d\n",coin->symbol,ep!=0?ep->symbol:"nanolistunspent",coinaddr,n); + for (i=0; isymbol,coinaddr,txid,v)) != 0 ) + free_json(retjson); + else + { + //printf("external unspent has no gettxout\n"); + flag += LP_address_utxoadd((uint32_t)time(NULL),"electrum process",coin,coinaddr,txid,v,value,0,1); + } + } + else + { + txid = jbits256(item,"tx_hash"); + v = jint(item,"tx_pos"); + value = j64bits(item,"value"); + ht = jint(item,"height"); + } + if ( bits256_nonz(txid) == 0 ) + 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 ( tx != 0 ) + { + if (tx->height <= 0 ) + { + tx->height = ht; + 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 ) + { + if ( tx->outpoints[v].value == 0 && value != tx->outpoints[v].value ) + { + printf("%s %s >>>>>>>>>> set %s/v%d <- %.8f vs %.8f\n",coin->symbol,coinaddr,bits256_str(str,txid),v,dstr(value),dstr(tx->outpoints[v].value)); + tx->outpoints[v].value = value; + } + } + if ( tx->height > 0 ) + { + //printf("from electrum_process_array\n"); + 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"); + } + } + 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); +} + +cJSON *electrum_submit(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *method,char *params,int32_t timeout) +{ + // queue id and string and callback + char stratumreq[16384]; uint32_t expiration; struct stritem *sitem; + if ( ep == 0 ) + 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 = 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(15000); + portable_mutex_unlock(&ep->mutex); + if ( *retjsonp == 0 || jobj(*retjsonp,"error") != 0 ) + { + if ( ++ep->numerrors >= LP_ELECTRUM_MAXERRORS ) + electrum_kickstart(ep); + } else if ( ep->numerrors > 0 ) + ep->numerrors--; + if ( ep->prev == 0 ) + { + if ( *retjsonp == 0 ) + { + //printf("unexpected %s timeout with null retjson: %s %s\n",ep->symbol,method,params); + *retjsonp = cJSON_Parse("{\"error\":\"timeout\"}"); + } + return(*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); + } + return(0); +} + +cJSON *electrum_noargs(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *method,int32_t timeout) +{ + cJSON *retjson; + if ( retjsonp == 0 ) + retjsonp = &retjson; + return(electrum_submit(symbol,ep,retjsonp,method,"[]",timeout)); +} + +cJSON *electrum_strarg(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *method,char *arg,int32_t timeout) +{ + char params[16384]; cJSON *retjson; + if ( strlen(arg) < sizeof(params) ) + { + if ( retjsonp == 0 ) + retjsonp = &retjson; + sprintf(params,"[\"%s\"]",arg); + return(electrum_submit(symbol,ep,retjsonp,method,params,timeout)); + } else return(0); +} + +cJSON *electrum_intarg(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *method,int32_t arg,int32_t timeout) +{ + char params[64]; cJSON *retjson; + if ( retjsonp == 0 ) + retjsonp = &retjson; + sprintf(params,"[\"%d\"]",arg); + return(electrum_submit(symbol,ep,retjsonp,method,params,timeout)); +} + +cJSON *electrum_hasharg(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *method,bits256 arg,int32_t timeout) +{ + char params[128],str[65]; cJSON *retjson; + if ( retjsonp == 0 ) + retjsonp = &retjson; + sprintf(params,"[\"%s\"]",bits256_str(str,arg)); + return(electrum_submit(symbol,ep,retjsonp,method,params,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)); } +cJSON *electrum_features(char *symbol,struct electrum_info *ep,cJSON **retjsonp) { return(electrum_noargs(symbol,ep,retjsonp,"server.features",ELECTRUM_TIMEOUT)); } +cJSON *electrum_headers_subscribe(char *symbol,struct electrum_info *ep,cJSON **retjsonp) { return(electrum_noargs(symbol,ep,retjsonp,"blockchain.headers.subscribe",ELECTRUM_TIMEOUT)); } + +cJSON *electrum_script_getbalance(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *script) { return(electrum_strarg(symbol,ep,retjsonp,"blockchain.scripthash.get_balance",script,ELECTRUM_TIMEOUT)); } +cJSON *electrum_script_gethistory(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *script) { return(electrum_strarg(symbol,ep,retjsonp,"blockchain.scripthash.get_history",script,ELECTRUM_TIMEOUT)); } +cJSON *electrum_script_getmempool(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *script) { return(electrum_strarg(symbol,ep,retjsonp,"blockchain.scripthash.get_mempool",script,ELECTRUM_TIMEOUT)); } +cJSON *electrum_script_listunspent(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *script) { return(electrum_strarg(symbol,ep,retjsonp,"blockchain.scripthash.listunspent",script,ELECTRUM_TIMEOUT)); } +cJSON *electrum_script_subscribe(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *script) { return(electrum_strarg(symbol,ep,retjsonp,"blockchain.scripthash.subscribe",script,ELECTRUM_TIMEOUT)); } + +cJSON *electrum_address_subscribe(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr) +{ + cJSON *retjson; + if ( (retjson= electrum_strarg(symbol,ep,retjsonp,"blockchain.address.subscribe",addr,ELECTRUM_TIMEOUT)) != 0 ) + { + //printf("subscribe.(%s)\n",jprint(retjson,0)); + } + return(retjson); +} + +cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr) +{ + char str[65]; struct LP_transaction *tx; cJSON *retjson,*txobj,*item; int32_t i,n,height; bits256 txid; struct iguana_info *coin = LP_coinfind(symbol); + retjson = electrum_strarg(symbol,ep,retjsonp,"blockchain.address.get_history",addr,ELECTRUM_TIMEOUT); + //printf("history.(%s)\n",jprint(retjson,0)); + if ( retjson != 0 && (n= cJSON_GetArraySize(retjson)) > 0 ) + { + for (i=0; i 0 ) + { + if ( (tx= LP_transactionfind(coin,txid)) != 0 ) + { + if ( tx->height > 0 && tx->height != height ) + printf("update %s height.%d <- %d\n",bits256_str(str,txid),tx->height,height); + tx->height = height; + LP_address_utxoadd((uint32_t)time(NULL),"electrum history",coin,addr,txid,0,0,height,-1); + } + } + } + } + } + return(retjson); +} + +int32_t LP_txheight_check(struct iguana_info *coin,char *coinaddr,struct LP_address_utxo *up) +{ + cJSON *retjson; + if ( coin->electrum != 0 ) + { + if ( (retjson= electrum_address_gethistory(coin->symbol,coin->electrum,&retjson,coinaddr)) != 0 ) + free_json(retjson); + } + return(0); +} + +cJSON *electrum_address_getmempool(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr) +{ + cJSON *retjson; struct iguana_info *coin = LP_coinfind(symbol); + retjson = electrum_strarg(symbol,ep,retjsonp,"blockchain.address.get_mempool",addr,ELECTRUM_TIMEOUT); + //printf("MEMPOOL.(%s)\n",jprint(retjson,0)); + electrum_process_array(coin,ep,addr,retjson,1); + return(retjson); +} + +cJSON *electrum_address_listunspent(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr,int32_t electrumflag) +{ + 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); + if ( (ap= LP_address(coin,addr)) != 0 ) + { + if ( ap->unspenttime == 0 ) + usecache = 0; + else if ( ap->unspentheight < height ) + usecache = 0; + else if ( G.LP_pendingswaps != 0 && time(NULL) > ap->unspenttime+30 ) + usecache = 0; + } + if ( usecache == 0 || electrumflag > 1 ) + { + if ( (retjson= electrum_strarg(symbol,ep,retjsonp,"blockchain.address.listunspent",addr,ELECTRUM_TIMEOUT)) != 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) != 0 ) + { + //LP_postutxos(coin->symbol,addr); + updatedflag = 1; + } + if ( strcmp(addr,coin->smartaddr) == 0 ) + { + retstr = jprint(retjson,0); + LP_unspents_cache(coin->symbol,coin->smartaddr,retstr,1); + free(retstr); + } + if ( ap != 0 ) + { + ap->unspenttime = (uint32_t)time(NULL); + ap->unspentheight = height; + } + } + else + { + free_json(retjson); + retjson = 0; + } + } + } + if ( retjson == 0 ) + { + if ( strcmp(addr,coin->smartaddr) == 0 && (retstr= LP_unspents_filestr(symbol,coin->smartaddr)) != 0 ) + { + retjson = cJSON_Parse(retstr); + free(retstr); + } else retjson = LP_address_utxos(coin,addr,1); + } + return(retjson); +} + +cJSON *electrum_address_getbalance(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr) +{ + return(electrum_strarg(symbol,ep,retjsonp,"blockchain.address.get_balance",addr,ELECTRUM_TIMEOUT)); +} + +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_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) +{ + return(electrum_intarg(symbol,ep,retjsonp,"blockchain.block.get_header",n,ELECTRUM_TIMEOUT)); +} + +cJSON *LP_cache_transaction(struct iguana_info *coin,bits256 txid,uint8_t *serialized,int32_t len) +{ + 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); +} + +cJSON *_electrum_transaction(char *symbol,struct electrum_info *ep,cJSON **retjsonp,bits256 txid) +{ + char *hexstr,str[65]; int32_t len; cJSON *hexjson,*txobj=0; struct iguana_info *coin; uint8_t *serialized; struct LP_transaction *tx; + //printf("electrum_transaction %s %s\n",symbol,bits256_str(str,txid)); + if ( bits256_nonz(txid) != 0 && (coin= LP_coinfind(symbol)) != 0 ) + { + if ( (tx= LP_transactionfind(coin,txid)) != 0 && tx->serialized != 0 ) + { + //char str[65]; printf("%s cache hit -> TRANSACTION.(%s)\n",symbol,bits256_str(str,txid)); + if ( (txobj= LP_transaction_fromdata(coin,txid,tx->serialized,tx->len)) != 0 ) + { + *retjsonp = txobj; + return(txobj); + } + } + if ( bits256_cmp(txid,coin->cachedtxid) == 0 ) + { + if ( (txobj= LP_transaction_fromdata(coin,txid,coin->cachedtxiddata,coin->cachedtxidlen)) != 0 ) + { + *retjsonp = txobj; + return(txobj); + } + } + hexjson = electrum_hasharg(symbol,ep,&hexjson,"blockchain.transaction.get",txid,ELECTRUM_TIMEOUT); + hexstr = jprint(hexjson,0); + if ( strlen(hexstr) > 100000 ) + { + static uint32_t counter; + if ( counter++ < 3 ) + 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\"}"); + return(*retjsonp); + } + if ( hexstr[0] == '"' && hexstr[strlen(hexstr)-1] == '"' ) + hexstr[strlen(hexstr)-1] = 0; + if ( (len= is_hexstr(hexstr+1,0)) > 2 ) + { + len = (int32_t)strlen(hexstr+1) >> 1; + serialized = malloc(len); + if ( coin->cachedtxiddata != 0 ) + free(coin->cachedtxiddata); + coin->cachedtxiddata = malloc(len); + coin->cachedtxidlen = len; + decode_hex(serialized,len,hexstr+1); + memcpy(coin->cachedtxiddata,serialized,len); + free(hexstr); + //printf("DATA.(%s) from (%s)\n",hexstr+1,jprint(hexjson,0)); + *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)); + free(hexstr); + free_json(hexjson); + } + *retjsonp = 0; + return(*retjsonp); +} + +cJSON *electrum_transaction(char *symbol,struct electrum_info *ep,cJSON **retjsonp,bits256 txid,char *SPVcheck) +{ + cJSON *retjson,*array; struct LP_transaction *tx; struct iguana_info *coin; + coin = LP_coinfind(symbol); + if ( ep != 0 ) + portable_mutex_lock(&ep->txmutex); + retjson = _electrum_transaction(symbol,ep,retjsonp,txid); + if ( ep != 0 && coin != 0 && SPVcheck != 0 && SPVcheck[0] != 0 && (tx= LP_transactionfind(coin,txid)) != 0 ) + { + if ( tx->height <= 0 ) + { + if ( (array= electrum_address_listunspent(symbol,ep,&array,SPVcheck,2)) != 0 ) + { + printf("SPVcheck.%s got %d unspents\n",SPVcheck,cJSON_GetArraySize(array)); + free_json(array); + } + } + if ( tx->height > 0 ) + tx->SPV = LP_merkleproof(coin,SPVcheck,ep,txid,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); + } + if ( ep != 0 ) + portable_mutex_unlock(&ep->txmutex); + return(retjson); +} + +cJSON *electrum_getmerkle(char *symbol,struct electrum_info *ep,cJSON **retjsonp,bits256 txid,int32_t height) +{ + char params[128],str[65]; + sprintf(params,"[\"%s\", %d]",bits256_str(str,txid),height); + if ( bits256_nonz(txid) == 0 ) + return(cJSON_Parse("{\"error\":\"null txid\"}")); + return(electrum_submit(symbol,ep,retjsonp,"blockchain.transaction.get_merkle",params,ELECTRUM_TIMEOUT)); +} + +void electrum_test() +{ + cJSON *retjson; bits256 hash; 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); + } + printf("found electrum server\n"); + if ( (retjson= electrum_version(symbol,ep,0)) != 0 ) + printf("electrum_version %s\n",jprint(retjson,1)); + if ( (retjson= electrum_banner(symbol,ep,0)) != 0 ) + printf("electrum_banner %s\n",jprint(retjson,1)); + if ( (retjson= electrum_donation(symbol,ep,0)) != 0 ) + printf("electrum_donation %s\n",jprint(retjson,1)); + if ( (retjson= electrum_features(symbol,ep,0)) != 0 ) + printf("electrum_features %s\n",jprint(retjson,1)); + if ( (retjson= electrum_estimatefee(symbol,ep,0,6)) != 0 ) + printf("electrum_estimatefee %s\n",jprint(retjson,1)); + decode_hex(hash.bytes,sizeof(hash),"0000000000000000005087f8845f9ed0282559017e3c6344106de15e46c07acd"); + if ( (retjson= electrum_getheader(symbol,ep,0,3)) != 0 ) + printf("electrum_getheader %s\n",jprint(retjson,1)); + //if ( (retjson= electrum_getchunk(symbol,ep,0,3)) != 0 ) + // printf("electrum_getchunk %s\n",jprint(retjson,1)); + 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)) != 0 ) + printf("electrum_transaction %s\n",jprint(retjson,1)); + addr = "14NeevLME8UAANiTCVNgvDrynUPk1VcQKb"; + if ( (retjson= electrum_address_gethistory(symbol,ep,0,addr)) != 0 ) + printf("electrum_address_gethistory %s\n",jprint(retjson,1)); + if ( (retjson= electrum_address_getmempool(symbol,ep,0,addr)) != 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 ) + 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)); + if ( (retjson= electrum_sendrawtransaction(symbol,ep,0,"0100000001b7e6d69a0fd650926bd5fbe63cc8578d976c25dbdda8dd61db5e05b0de4041fe000000006b483045022100de3ae8f43a2a026bb46f6b09b890861f8aadcb16821f0b01126d70fa9ae134e4022000925a842073484f1056c7fc97399f2bbddb9beb9e49aca76835cdf6e9c91ef3012103cf5ce3233e6d6e22291ebef454edff2b37a714aed685ce94a7eb4f83d8e4254dffffffff014c4eaa0b000000001976a914b598062b55362952720718e7da584a46a27bedee88ac00000000")) != 0 ) + printf("electrum_sendrawtransaction %s\n",jprint(retjson,1)); + + if ( 0 ) + { + script = "76a914b598062b55362952720718e7da584a46a27bedee88ac"; + if ( (retjson= electrum_script_gethistory(symbol,ep,0,script)) != 0 ) + printf("electrum_script_gethistory %s\n",jprint(retjson,1)); + if ( (retjson= electrum_script_getmempool(symbol,ep,0,script)) != 0 ) + printf("electrum_script_getmempool %s\n",jprint(retjson,1)); + if ( (retjson= electrum_script_getbalance(symbol,ep,0,script)) != 0 ) + printf("electrum_script_getbalance %s\n",jprint(retjson,1)); + if ( (retjson= electrum_script_listunspent(symbol,ep,0,script)) != 0 ) + printf("electrum_script_listunspent %s\n",jprint(retjson,1)); + if ( (retjson= electrum_script_subscribe(symbol,ep,0,script)) != 0 ) + printf("electrum_script_subscribe %s\n",jprint(retjson,1)); + } + if ( (retjson= electrum_headers_subscribe(symbol,ep,0)) != 0 ) + printf("electrum_headers %s\n",jprint(retjson,1)); + if ( (retjson= electrum_peers(symbol,ep,0)) != 0 ) + printf("electrum_peers %s\n",jprint(retjson,1)); + if ( (retjson= electrum_address_subscribe(symbol,ep,0,addr)) != 0 ) + printf("electrum_address_subscribe %s\n",jprint(retjson,1)); +} + +struct electrum_info *LP_electrum_info(int32_t *alreadyp,char *symbol,char *ipaddr,uint16_t port,int32_t bufsize) +{ + struct electrum_info *ep=0; int32_t i,sock; struct stritem *sitem; char name[512],*str = "init string"; + *alreadyp = 0; + portable_mutex_lock(&LP_electrummutex); + for (i=0; isymbol,ep->ipaddr,ep->port,symbol,ipaddr,port); + if ( strcmp(ep->ipaddr,ipaddr) == 0 && ep->port == port && strcmp(ep->symbol,symbol) == 0 ) + { + *alreadyp = 1; + printf("%s.(%s:%u) already an electrum server\n",symbol,ipaddr,port); + break; + } + ep = 0; + } + portable_mutex_unlock(&LP_electrummutex); + if ( ep == 0 ) + { + if ( (sock= LP_socket(0,ipaddr,port)) < 0 ) + { + printf("error connecting to %s:%u\n",ipaddr,port); + return(0); + } + ep = calloc(1,sizeof(*ep) + bufsize); + portable_mutex_init(&ep->mutex); + portable_mutex_init(&ep->txmutex); + ep->sock = sock; + safecopy(ep->symbol,symbol,sizeof(ep->symbol)); + safecopy(ep->ipaddr,ipaddr,sizeof(ep->ipaddr)); + ep->port = port; + ep->bufsize = bufsize; + ep->coin = LP_coinfind(symbol); + ep->lasttime = (uint32_t)time(NULL); + sprintf(name,"%s_%s_%u_electrum_sendQ",symbol,ipaddr,port); + queue_enqueue(name,&ep->sendQ,queueitem(str)); + if ( (sitem= queue_dequeue(&ep->sendQ)) == 0 && strcmp(sitem->str,str) != 0 ) + printf("error with string sendQ sitem.%p (%s)\n",sitem,sitem==0?0:sitem->str); + sprintf(name,"%s_%s_%u_electrum_pendingQ",symbol,ipaddr,port); + queue_enqueue(name,&ep->pendingQ,queueitem(str)); + if ( (sitem= queue_dequeue(&ep->pendingQ)) == 0 && strcmp(sitem->str,str) != 0 ) + printf("error with string pendingQ sitem.%p (%s)\n",sitem,sitem==0?0:sitem->str); + electrum_server(symbol,ep); + } + return(ep); +} + +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\n",ep->symbol,strlen(str),jint(strjson,"id")); + resultjson = jobj(strjson,"result"); + //printf("strjson.(%s)\n",jprint(strjson,0)); + if ( (method= jstr(strjson,"method")) != 0 ) + { + if ( strcmp(method,"blockchain.headers.subscribe") == 0 ) + { + //printf("%p headers.(%s)\n",strjson,jprint(strjson,0)); + if ( (paramsjson= jarray(&n,strjson,"params")) != 0 ) + { + for (i=0; icoin,resultjson); + }*/ + } + if ( resultjson != 0 ) + { + if ( (height= jint(resultjson,"block_height")) > 0 && ep->heightp != 0 && ep->heighttimep != 0 ) + { + if ( height > *(ep->heightp) ) + *(ep->heightp) = height; + *(ep->heighttimep) = (uint32_t)time(NULL); + if ( (coin= LP_coinfind(ep->symbol)) != 0 ) + coin->updaterate = (uint32_t)time(NULL); + //printf("%s ELECTRUM >>>>>>>>> set height.%d\n",ep->symbol,height); + } + } + idnum = juint(strjson,"id"); + portable_mutex_lock(&ep->pendingQ.mutex); + if ( ep->pendingQ.list != 0 ) + { + DL_FOREACH_SAFE(ep->pendingQ.list,item,tmp) + { + stritem = (struct stritem *)item; + if ( item->type == idnum ) + { + DL_DELETE(ep->pendingQ.list,item); + 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; + } + if ( stritem->expiration < ep->lasttime ) + { + DL_DELETE(ep->pendingQ.list,item); + if ( 0 ) + { + printf("expired %s (%s)\n",ep->symbol,stritem->str); + errjson = cJSON_CreateObject(); + jaddnum(errjson,"id",item->type); + jaddstr(errjson,"error","timeout"); + *((cJSON **)stritem->retptrp) = errjson; + } + free(item); + } + } + } + portable_mutex_unlock(&ep->pendingQ.mutex); + if ( strjson != 0 ) + free_json(strjson); + } + return(item != 0); +} + +void LP_dedicatedloop(void *arg) +{ + struct pollfd fds; int32_t i,len,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; + 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 ) + { + flag = 0; + memset(&fds,0,sizeof(fds)); + fds.fd = ep->sock; + fds.events |= (POLLOUT | POLLIN); + if ( poll(&fds,1,timeout) > 0 && (fds.revents & POLLOUT) != 0 && ep->pending == 0 && (sitem= queue_dequeue(&ep->sendQ)) != 0 ) + { + ep->pending = (uint32_t)time(NULL); + if ( LP_socketsend(ep->sock,(uint8_t *)sitem->str,(int32_t)strlen(sitem->str)) <= 0 ) + { + printf("%s:%u is dead\n",ep->ipaddr,ep->port); + closesocket(ep->sock); + 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; + queue_enqueue("pendingQ",&ep->pendingQ,&sitem->DL); + flag++; + } + if ( flag == 0 ) + { + if ( (fds.revents & POLLIN) != 0 ) + { + if ( (len= LP_socketrecv(ep->sock,ep->buf,ep->bufsize)) > 0 ) + { + ep->pending = 0; + LP_recvfunc(ep,(char *)ep->buf,len); + flag++; + } + } + if ( flag == 0 ) + usleep(100000); + } + } + if ( coin->electrum == ep ) + { + coin->electrum = ep->prev; + printf("set %s electrum to %p\n",coin->symbol,coin->electrum); + } else printf("backup electrum server closing\n"); + printf(">>>>>>>>>> electrum close %s:%u\n",ep->ipaddr,ep->port); + if ( Num_electrums > 0 ) + { + portable_mutex_lock(&LP_electrummutex); + for (i=0; isock = -1; + //free(ep); +} + +cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port) +{ + struct electrum_info *ep; int32_t kickval,already; cJSON *retjson; + if ( ipaddr == 0 || ipaddr[0] == 0 || port == 0 ) + { + coin->electrum = 0; + coin->inactive = (uint32_t)time(NULL); + //printf("would have disabled %s electrum here\n",coin->symbol); + return(cJSON_Parse("{\"result\":\"success\",\"status\":\"electrum mode disabled, now in native coin mode\"}")); + } + retjson = cJSON_CreateObject(); + jaddstr(retjson,"ipaddr",ipaddr); + jaddnum(retjson,"port",port); + if ( (ep= LP_electrum_info(&already,coin->symbol,ipaddr,port,IGUANA_MAXPACKETSIZE)) == 0 ) + { + jaddstr(retjson,"error","couldnt connect to electrum server"); + return(retjson); + } + if ( already == 0 ) + { + if ( ep != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_dedicatedloop,(void *)ep) != 0 ) + { + printf("error launching LP_dedicatedloop %s.(%s:%u)\n",coin->symbol,ep->ipaddr,ep->port); + jaddstr(retjson,"error","couldnt launch electrum thread"); + } + else + { + //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); +} + diff --git a/iguana/exchanges/LP_statemachine.c b/iguana/exchanges/LP_statemachine.c index dcb67c8a9..54d9ddc95 100644 --- a/iguana/exchanges/LP_statemachine.c +++ b/iguana/exchanges/LP_statemachine.c @@ -17,6 +17,25 @@ // LP_statemachine.c // marketmaker // + +else +{ + CTransaction tx; uint256 hashBlock; int32_t numvouts,len; uint8_t *ptr; + if ( GetTransaction(NOTARIZED_DESTTXID,tx,hashBlock,true) == 0 ) + { + fprintf(stderr,"error finding") + return(-1); + } + if ( (numvouts= tx.vout.size()) > 0 ) + { + ptr = (uint8_t *)tx.vout[numvouts - 1].scriptPubKey.data(); + len = tx.vout[numvouts - 1].scriptPubKey.size(); + retval = komodo_verifynotarizedscript(height,ptr,len,NOTARIZED_HASH); + printf("direct verify ht.%d -> %d\n",height,retval); + return(retval); + } +} + /*struct LP_cacheinfo *ptr,*tmp; HASH_ITER(hh,LP_cacheinfos,ptr,tmp) { @@ -113,6 +132,434 @@ FILE *basilisk_swap_save(struct basilisk_swap *swap,bits256 privkey,struct basil }*/ return(fp); } +//printf("VOUT.(%s)\n",jprint(vout,0)); +/*if ( (skey= jobj(vout,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 ) + { + item = jitem(addresses,0); + //printf("item.(%s)\n",jprint(item,0)); + if ( (addr= jstr(item,0)) != 0 ) + { + safecopy(coinaddr,addr,64); + //printf("extracted.(%s)\n",coinaddr); + } + }*/ + +/*if ( IAMLP != 0 && time(NULL) > lasthello+600 ) + { + char *hellostr,*retstr; cJSON *retjson; int32_t allgood,sock = LP_bindsock; + allgood = 0; + if ( (retstr= issue_hello(myport)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( (hellostr= jstr(retjson,"status")) != 0 && strcmp(hellostr,"got hello") == 0 ) + allgood = 1; + else printf("strange return.(%s)\n",jprint(retjson,0)); + free_json(retjson); + } else printf("couldnt parse hello return.(%s)\n",retstr); + free(retstr); + } else printf("issue_hello NULL return\n"); + lasthello = (uint32_t)time(NULL); + if ( allgood == 0 ) + { + printf("RPC port got stuck, would have close bindsocket\n"); + if ( 0 ) + { + LP_bindsock = -1; + closesocket(sock); + LP_bindsock_reset++; + sleep(10); + printf("launch new rpcloop\n"); + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)stats_rpcloop,(void *)&myport) != 0 ) + { + printf("error launching stats rpcloop for port.%u\n",myport); + exit(-1); + } + } + } + }*/ +/* + now = (uint32_t)time(NULL); + numpeers = LP_numpeers(); + needpings = 0; + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + if ( peer->errors >= LP_MAXPEER_ERRORS ) + { + if ( (LP_rand() % 10000) == 0 ) + { + peer->errors--; + if ( peer->errors < LP_MAXPEER_ERRORS ) + peer->diduquery = 0; + } + if ( IAMLP == 0 ) + continue; + } + if ( now > peer->lastpeers+LP_ORDERBOOK_DURATION*.777 || (LP_rand() % 100000) == 0 ) + { + if ( strcmp(peer->ipaddr,myipaddr) != 0 ) + { + nonz++; + //issue_LP_getpeers(peer->ipaddr,peer->port); + //LP_peersquery(mypeer,pubsock,peer->ipaddr,peer->port,myipaddr,myport); + //if ( peer->diduquery == 0 ) + // LP_peer_pricesquery(peer); + //LP_utxos_sync(peer); + needpings++; + } + peer->lastpeers = now; + } + if ( peer->needping != 0 ) + { + peer->diduquery = now; + nonz++; + if ( (retstr= issue_LP_notify(peer->ipaddr,peer->port,"127.0.0.1",0,numpeers,G.LP_sessionid,G.LP_myrmd160str,G.LP_mypub25519)) != 0 ) + free(retstr); + peer->needping = 0; + needpings++; + } + }*/ + +#ifdef oldway +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 numpeers,i,n=0; + if ( (array= cJSON_Parse(retstr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; i numpeers) ) + 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 issue_LP_getpeers(char *destip,uint16_t destport) +{ + cJSON *reqjson = cJSON_CreateObject(); + jaddstr(reqjson,"method","getpeers"); + LP_peer_request(destip,destport,reqjson); + /*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);*/ +} + +void LP_peer_request(char *destip,uint16_t destport,cJSON *argjson) +{ + struct LP_peerinfo *peer; uint8_t *msg; int32_t msglen; uint32_t crc32; + peer = LP_peerfind((uint32_t)calc_ipbits(destip),destport); + msg = (void *)jprint(argjson,0); + msglen = (int32_t)strlen((char *)msg) + 1; + crc32 = calc_crc32(0,&msg[2],msglen - 2); + LP_queuesend(crc32,peer->pushsock,"","",msg,msglen); + free_json(argjson); +}void LP_peersquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *myipaddr,uint16_t myport) +{ + 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 ) + { + //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"); + } + } +} +void issue_LP_notify(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers,uint32_t sessionid,char *rmd160str,bits256 pub) +{ + cJSON *reqjson = cJSON_CreateObject(); + jaddstr(reqjson,"method","notify"); + jaddstr(reqjson,"coin",symbol); + jaddstr(reqjson,"coinaddr",coinaddr); + jaddbits256(reqjson,"txid",txid); + jaddnum(reqjson,"vout",vout); + jaddnum(reqjson,"ht",height); + jadd64bits(reqjson,"value",value); + LP_peer_request(destip,destport,reqjson); + /*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_hello(uint16_t port) +{ + char url[512]; + sprintf(url,"http://127.0.0.1:%u/api/stats/hello",port); + //printf("getutxo.(%s)\n",url); + return(issue_curlt(url,600)); // might be starting a trade +} + + +void issue_LP_uitem(char *destip,uint16_t destport,char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t height,uint64_t value) +{ + cJSON *reqjson = cJSON_CreateObject(); + jaddstr(reqjson,"method","uitem"); + jaddstr(reqjson,"coin",symbol); + jaddstr(reqjson,"coinaddr",coinaddr); + jaddbits256(reqjson,"txid",txid); + jaddnum(reqjson,"vout",vout); + jaddnum(reqjson,"ht",height); + jadd64bits(reqjson,"value",value); + LP_peer_request(destip,destport,reqjson); + /*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);*/ +} + +/*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; itimestamp = (uint32_t)time(NULL); + ptr->item = item; + item->cjsonid = LP_rand(); + ptr->cjsonid = item->cjsonid; + portable_mutex_lock(&LP_cJSONmutex); + DL_APPEND(LP_cJSONlist,ptr); + portable_mutex_unlock(&LP_cJSONmutex); + } + + void cJSON_unregister(cJSON *item) + { + static uint32_t lasttime; + int32_t n; char *tmpstr; uint64_t total = 0; struct cJSON_list *ptr,*tmp; uint32_t now; + if ( (now= (uint32_t)time(NULL)) > lasttime+6 ) + { + n = 0; + DL_FOREACH_SAFE(LP_cJSONlist,ptr,tmp) + { + if ( ptr->item != 0 && ptr->item->child != 0 && ptr->cjsonid != 0 ) + { + if ( (tmpstr= jprint(ptr->item,0)) != 0 ) + { + total += strlen(tmpstr); + free(tmpstr); + } + } + n++; + } + printf("total %d cJSON pending\n",n); + lasttime = (uint32_t)time(NULL); + } + DL_FOREACH_SAFE(LP_cJSONlist,ptr,tmp) + { + if ( ptr->cjsonid == item->cjsonid ) + break; + else if ( now > ptr->timestamp+60 && item->cjsonid != 0 ) + { + portable_mutex_lock(&LP_cJSONmutex); + DL_DELETE(LP_cJSONlist,ptr); + portable_mutex_unlock(&LP_cJSONmutex); + printf("free expired\n"); + cJSON_Delete(ptr->item); + free(ptr); + } + ptr = 0; + } + if ( ptr != 0 ) + { + portable_mutex_lock(&LP_cJSONmutex); + DL_DELETE(LP_cJSONlist,ptr); + free(ptr); + portable_mutex_unlock(&LP_cJSONmutex); + } //else printf("cJSON_unregister of unknown %p %u\n",item,item->cjsonid); + }*/ +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)); +} +/*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"); + }*/ + +void issue_LP_listunspent(char *destip,uint16_t destport,char *symbol,char *coinaddr) +{ + cJSON *reqjson = cJSON_CreateObject(); + jaddstr(reqjson,"method","listunspent"); + jaddstr(reqjson,"coin",symbol); + jaddstr(reqjson,"address",coinaddr); + LP_peer_request(destip,destport,reqjson); + /*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);*/ +} + + +int32_t LP_utxos_sync(struct LP_peerinfo *peer) +{ + int32_t i,j,n=0,m,v,posted=0; bits256 txid; cJSON *array,*item,*item2,*array2; uint64_t total,total2; struct iguana_info *coin,*ctmp; char *retstr,*retstr2; + if ( strcmp(peer->ipaddr,LP_myipaddr) == 0 ) + return(0); + HASH_ITER(hh,LP_coins,coin,ctmp) + { + if ( IAMLP == 0 && coin->inactive != 0 ) + continue; + if ( coin->smartaddr[0] == 0 ) + continue; + total = 0; + if ( (j= LP_listunspent_both(coin->symbol,coin->smartaddr,0)) == 0 ) + continue; + if ( (array= LP_address_utxos(coin,coin->smartaddr,1)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; i 0 && total > 0 && (retstr= issue_LP_listunspent(peer->ipaddr,peer->port,coin->symbol,coin->smartaddr)) != 0 ) + { + //printf("UTXO sync.%d %s n.%d total %.8f -> %s (%s)\n",j,coin->symbol,n,dstr(total),peer->ipaddr,retstr); + total2 = 0; + if ( (array2= cJSON_Parse(retstr)) != 0 ) + { + if ( (m= cJSON_GetArraySize(array2)) > 0 ) + { + for (i=0; iipaddr,coin->symbol,jprint(item,0)); + issue_LP_uitem(peer->ipaddr,peer->port,coin->symbol,coin->smartaddr,txid,v,jint(item,"height"),j64bits(item,"value")); + posted++; + } + } + if ( 0 && posted != 0 ) + printf(">>>>>>>> %s compare %s %s (%.8f n%d) (%.8f m%d)\n",peer->ipaddr,coin->symbol,coin->smartaddr,dstr(total),n,dstr(total2),m); + } //else printf("%s matches %s\n",peer->ipaddr,coin->symbol); + free_json(array2); + } else printf("parse error (%s)\n",retstr); + free(retstr); + } + else if ( n != 0 && total != 0 ) + { + //printf("no response from %s for %s %s\n",peer->ipaddr,coin->symbol,coin->smartaddr); + for (i=0; iipaddr,peer->port,coin->symbol,coin->smartaddr,txid,v,jint(item,"height"),j64bits(item,"value")); + } + } + free_json(array); + } + } + return(posted); +} /*char *issue_LP_notifyutxo(char *destip,uint16_t destport,struct LP_utxoinfo *utxo) { char url[4096],str[65],str2[65],str3[65],*retstr; struct _LP_utxoinfo u; uint64_t val,val2; @@ -258,24 +705,6 @@ void basilisk_swap_saveupdate(struct basilisk_swap *swap) } } -/*int32_t basilisk_swap_loadtx(struct basilisk_rawtx *rawtx,FILE *fp,char *bobcoinstr,char *alicecoinstr) - { - if ( fread(rawtx,1,sizeof(*rawtx),fp) == sizeof(*rawtx) ) - { - rawtx->coin = 0; - rawtx->vins = 0; - if ( strcmp(rawtx->I.coinstr,bobcoinstr) == 0 || strcmp(rawtx->I.coinstr,alicecoinstr) == 0 ) - { - rawtx->coin = LP_coinfind(rawtx->I.coinstr); - if ( rawtx->vinstr[0] != 0 ) - rawtx->vins = cJSON_Parse(rawtx->vinstr); - printf("loaded.%s len.%d\n",rawtx->name,rawtx->I.datalen); - return(0); - } - } - return(-1); - }*/ - void basilisk_swap_sendabort(struct basilisk_swap *swap) { uint32_t msgbits = 0; uint8_t buf[sizeof(msgbits) + sizeof(swap->I.req.quoteid) + sizeof(bits256)*2]; int32_t sentbytes,offset=0; @@ -446,7 +875,6 @@ void iguana_ensure_privkey(struct iguana_info *coin,bits256 privkey) } } } -#endif int32_t basilisk_rawtx_return(struct basilisk_rawtx *rawtx,cJSON *item,int32_t lockinputs,struct vin_info *V) @@ -484,6 +912,7 @@ int32_t basilisk_rawtx_return(struct basilisk_rawtx *rawtx,cJSON *item,int32_t l } return(retval); } +#endif cJSON *LP_createvins(struct basilisk_rawtx *dest,struct vin_info *V,struct basilisk_rawtx *rawtx,uint8_t *userdata,int32_t userdatalen,uint32_t sequenceid) { @@ -526,7 +955,7 @@ int32_t _basilisk_rawtx_gen(char *str,uint32_t swapstarted,uint8_t *pubkey33,int { char scriptstr[1024],wifstr[256],coinaddr[64],*signedtx,*rawtxbytes; uint32_t basilisktag; int32_t retval = -1; cJSON *vins,*privkeys,*addresses,*valsobj; struct vin_info *V; init_hexbytes_noT(scriptstr,script,scriptlen); - basilisktag = (uint32_t)rand(); + basilisktag = (uint32_t)LP_rand(); valsobj = cJSON_CreateObject(); jaddstr(valsobj,"coin",rawtx->coin->symbol); jaddstr(valsobj,"spendscript",scriptstr); @@ -766,7 +1195,7 @@ int32_t basilisk_swapiteration(struct basilisk_swap *swap,uint8_t *data,int32_t basilisk_swap_saveupdate(swap); if ( swap->connected == 0 ) basilisk_psockinit(swap,swap->I.iambob != 0); - //if ( (rand() % 30) == 0 ) + //if ( (LP_rand() % 30) == 0 ) printf("E r%u/q%u swapstate.%x otherstate.%x remaining %d\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits,swap->I.otherstatebits,(int32_t)(swap->I.expiration-time(NULL))); if ( swap->I.iambob != 0 ) { @@ -940,7 +1369,7 @@ int32_t basilisk_swapiteration(struct basilisk_swap *swap,uint8_t *data,int32_t } } } - if ( (rand() % 30) == 0 ) + if ( (LP_rand() % 30) == 0 ) printf("finished swapstate.%x other.%x\n",swap->I.statebits,swap->I.otherstatebits); if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits ) sleep(DEX_SLEEP + (swap->I.iambob == 0)*1); @@ -1336,7 +1765,7 @@ void basilisk_swaploop(void *_utxo) else tradebot_pendingadd(swapjson(swap),swap->I.req.dest,dstr(swap->I.req.destamount),swap->I.req.src,dstr(swap->I.req.srcamount)); } printf("%s swap finished statebits %x\n",swap->I.iambob!=0?"BOB":"ALICE",swap->I.statebits); - //basilisk_swap_purge(swap); + basilisk_swap_purge(swap); free(data); } #endif @@ -1385,6 +1814,41 @@ int32_t bitcoin_coinptrs(bits256 pubkey,struct iguana_info **bobcoinp,struct igu } portable_mutex_unlock(&myinfo->DEX_swapmutex); }*/ +/*if ( bits256_nonz(Q.srchash) == 0 || bits256_cmp(Q.srchash,G.LP_mypub25519) == 0 || strcmp(butxo->coinaddr,coin->smartaddr) != 0 || bits256_nonz(butxo->payment.txid) == 0 || bits256_nonz(butxo->deposit.txid) == 0 ) + { + qprice = (double)Q.destsatoshis / Q.satoshis; + strcpy(Q.gui,G.gui); + strcpy(Q.coinaddr,coin->smartaddr); + strcpy(butxo->coinaddr,coin->smartaddr); + Q.srchash = G.LP_mypub25519; + memset(&Q.txid,0,sizeof(Q.txid)); + memset(&Q.txid2,0,sizeof(Q.txid2)); + Q.vout = Q.vout2 = -1; + recalc = 1; + } + else if ( (qprice= LP_quote_validate(autxo,butxo,&Q,1)) < SMALLVAL ) + recalc = 1; + else if ( price < qprice ) + { + char tmp[64]; + if ( bits256_nonz(Q.txid) != 0 ) + LP_utxos_remove(Q.txid,Q.vout); + else recalc = 1; + if ( bits256_nonz(Q.txid2) != 0 ) + LP_utxos_remove(Q.txid2,Q.vout2); + else recalc = 1; + //printf("price %.8f qprice %.8f\n",price,qprice); + if ( recalc == 0 ) + { + value = LP_txvalue(tmp,Q.srccoin,Q.txid,Q.vout); + value2 = LP_txvalue(tmp,Q.srccoin,Q.txid2,Q.vout2); + //printf("call LP_utxoadd.(%s) %.8f %.8f\n",Q.coinaddr,dstr(value),dstr(value2)); + if ( (butxo= LP_utxoadd(1,coin->symbol,Q.txid,Q.vout,value,Q.txid2,Q.vout2,value2,Q.coinaddr,Q.srchash,G.gui,0,Q.satoshis)) == 0 ) + recalc = 1; + else if ( bits256_cmp(Q.txid,butxo->payment.txid) != 0 || Q.vout != butxo->payment.vout || bits256_cmp(Q.txid2,butxo->deposit.txid) != 0 || Q.vout2 != butxo->deposit.vout ) + recalc = 1; + } + } else return(retval);*/ /*int32_t LP_priceping(int32_t pubsock,struct LP_utxoinfo *utxo,char *rel,double origprice) { @@ -1414,6 +1878,27 @@ int32_t bitcoin_coinptrs(bits256 pubkey,struct iguana_info **bobcoinp,struct igu } return(-1); }*/ +/*if ( (butxo= LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2)) == 0 ) + { + value = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid,Q.vout); + value2 = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid2,Q.vout2); + if ( value == 0 || value2 == 0 ) + { + printf("zero value %.8f or value2 %.8f\n",dstr(value),dstr(value2)); + return(clonestr("{\"error\":\"spent txid or txid2 for bob?\"}")); + } + if ( (butxo= LP_utxoadd(1,Q.srccoin,Q.txid,Q.vout,value,Q.txid2,Q.vout2,value2,Q.coinaddr,Q.srchash,LP_gui,0)) == 0 ) + { + printf("cant find or create butxo\n"); + return(clonestr("{\"error\":\"cant find or create butxo\"}")); + } + if ( value < Q.satoshis ) + { + printf("butxo value %.8f less satoshis %.8f\n",dstr(value),dstr(Q.satoshis)); + return(clonestr("{\"error\":\"butxo value less than satoshis\"}")); + } + }*/ + /*if ( addflag != 0 && LP_utxofind(1,Q.txid,Q.vout) == 0 ) { LP_utxoadd(1,-1,Q.srccoin,Q.txid,Q.vout,Q.value,Q.txid2,Q.vout2,Q.value2,"",Q.srcaddr,Q.srchash,0.); @@ -1473,63 +1958,672 @@ if ( (array= LP_tradecandidates(base)) != 0 ) printf("metrics, best %f\n",bestmetric); */ -/*cJSON *LP_tradecandidates(char *base) - { - struct LP_peerinfo *peer,*tmp; struct LP_quoteinfo Q; char *utxostr,coinstr[16]; cJSON *array,*retarray=0,*item; int32_t i,n,totaladded,added; - totaladded = 0; - HASH_ITER(hh,LP_peerinfos,peer,tmp) - { - printf("%s:%u %s\n",peer->ipaddr,peer->port,base); - n = added = 0; - if ( (utxostr= issue_LP_clientgetutxos(peer->ipaddr,peer->port,base,100)) != 0 ) - { - printf("%s:%u %s %s\n",peer->ipaddr,peer->port,base,utxostr); - if ( (array= cJSON_Parse(utxostr)) != 0 ) - { - if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) - { - retarray = cJSON_CreateArray(); - for (i=0; inumpeers : 0,maxentries); + else retstr = issue_LP_clientgetutxos(destipaddr,destport,coin,maxentries); + if ( retstr != 0 ) + { + now = (uint32_t)time(NULL); + retval = LP_utxosparse(destipaddr,destport,retstr,now); + //printf("got.(%s)\n",retstr); + free(retstr); + } + return(retval); +} + +char *issue_LP_numutxos(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers,int32_t numutxos) +{ + char url[512],*retstr; + printf("deprecated issue_LP_numutxos\n"); + return(0); + sprintf(url,"http://%s:%u/api/stats/numutxos?ipaddr=%s&port=%u&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,numpeers,numutxos); + retstr = LP_issue_curl("numutxos",destip,port,url); + //printf("%s -> getpeers.(%s)\n",destip,retstr); + return(retstr); +} + +char *issue_LP_getutxos(char *destip,uint16_t destport,char *coin,int32_t lastn,char *ipaddr,uint16_t port,int32_t numpeers,int32_t numutxos) +{ + char url[512]; + printf("deprecated issue_LP_getutxos\n"); + return(0); + sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=%s&port=%u&numpeers=%d&numutxos=%d",destip,destport,coin,lastn,ipaddr,port,numpeers,numutxos); + return(LP_issue_curl("getutxos",destip,destport,url)); + //return(issue_curlt(url,LP_HTTP_TIMEOUT)); +} + +char *issue_LP_clientgetutxos(char *destip,uint16_t destport,char *coin,int32_t lastn) +{ + char url[512];//,*retstr; + printf("deprecated issue_LP_clientgetutxos\n"); + return(0); + sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=127.0.0.1&port=0",destip,destport,coin,lastn); + return(LP_issue_curl("clientgetutxos",destip,destport,url)); + //retstr = issue_curlt(url,LP_HTTP_TIMEOUT); + //printf("%s clientgetutxos.(%s)\n",url,retstr); + //return(retstr); +} +void LP_address_monitor(struct LP_pubkeyinfo *pubp) +{ + struct iguana_info *coin,*tmp; char coinaddr[64]; cJSON *retjson; struct LP_address *ap; + return; + HASH_ITER(hh,LP_coins,coin,tmp) + { + bitcoin_address(coinaddr,coin->taddr,coin->pubtype,pubp->rmd160,sizeof(pubp->rmd160)); + portable_mutex_lock(&coin->addrmutex); + if ( (ap= _LP_address(coin,coinaddr)) != 0 ) + { + ap->monitor = (uint32_t)time(NULL); + } + portable_mutex_unlock(&coin->addrmutex); + if ( coin->electrum != 0 ) + { + if ( (retjson= electrum_address_subscribe(coin->symbol,coin->electrum,&retjson,coinaddr)) != 0 ) + { + printf("%s MONITOR.(%s) -> %s\n",coin->symbol,coinaddr,jprint(retjson,0)); + free_json(retjson); + } + } + } +} + +/*else if ( strcmp(method,"ordermatch") == 0 ) { - jaddi(retarray,jduplicate(item)); - added++; - totaladded++; - } - } else printf("ineligible.(%s)\n",jprint(item,0)); - } - } - } - free_json(array); - } - free(utxostr); + if ( price > SMALLVAL ) + return(LP_ordermatch(base,j64bits(argjson,"txfee"),price,jdouble(argjson,"relvolume"),rel,jbits256(argjson,"txid"),jint(argjson,"vout"),jbits256(argjson,"feetxid"),jint(argjson,"feevout"),j64bits(argjson,"desttxfee"),jint(argjson,"duration"))); + else return(clonestr("{\"error\":\"no price set\"}")); } - if ( n == totaladded && added == 0 ) + else if ( strcmp(method,"trade") == 0 ) { - printf("n.%d totaladded.%d vs added.%d\n",n,totaladded,added); - break; - } - } - return(retarray); + struct LP_quoteinfo Q; + if ( price > SMALLVAL || jobj(argjson,"quote") != 0 ) + { + LP_quoteparse(&Q,jobj(argjson,"quote")); + return(LP_trade(ctx,myipaddr,pubsock,&Q,price,jint(argjson,"timeout"),jint(argjson,"duration"))); + } else return(clonestr("{\"error\":\"no price set or no quote object\"}")); } - - void LP_quotesinit(char *base,char *rel) + else if ( strcmp(method,"autotrade") == 0 ) { - cJSON *array,*item; struct LP_quoteinfo Q; bits256 zero; int32_t i,n,iter; - memset(&zero,0,sizeof(zero)); - for (iter=0; iter<2; iter++) - if ( (array= LP_tradecandidates(iter == 0 ? base : rel)) != 0 ) + if ( price > SMALLVAL ) { - //printf("candidates.(%s)\nn.%d\n",jprint(array,0),cJSON_GetArraySize(array)); - if ( (n= cJSON_GetArraySize(array)) > 0 ) + return(LP_autotrade(ctx,myipaddr,pubsock,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration"))); + } else return(clonestr("{\"error\":\"no price set\"}")); + }*/ +if ( flag != 0 ) +{ + // need to find the requestid/quoteid for aliceid + if ( (retstr= basilisk_swapentries(bot->base,bot->rel,0)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(retjson)) != 0 ) + { + for (flag=j=0; jnumtrades; i++) + { + if ( (tp= bot->trades[i]) != 0 && tp->finished == 0 && tp->requestid == 0 && tp->quoteid == 0 ) + { + if ( tp->aliceid == aliceid ) + { + tp->requestid = juint(item,"requestid"); + tp->quoteid = juint(item,"quoteid"); + printf("found aliceid.%llx to set requestid.%u quoteid.%u\n",(long long)aliceid,tp->requestid,tp->quoteid); + flag = 1; + break; + } + } + } + } + } + free_json(retjson); + } + free(retstr); + } +} +// check for finished pending swap +for (i=0; inumtrades; i++) +{ + if ( (tp= bot->trades[i]) != 0 && tp->finished == 0 && tp->requestid != 0 && tp->quoteid != 0 ) + { + if ( (retstr= basilisk_swapentry(tp->requestid,tp->quoteid)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( (status= jstr(retjson,"status")) != 0 && strcmp(status,"finished") == 0 ) + { + bot->pendbasesum -= tp->basevol, bot->basesum += tp->basevol; + bot->pendrelsum -= tp->relvol, bot->relsum += tp->relvol; + bot->numpending--, bot->completed++; + printf("detected completion aliceid.%llx r.%u q.%u\n",(long long)tp->aliceid,tp->requestid,tp->quoteid); + tp->finished = (uint32_t)time(NULL); + } + free_json(retjson); + } + free(retstr); + } + } +} +} + +int32_t LP_utxopurge(int32_t allutxos) +{ + char str[65]; struct LP_utxoinfo *utxo,*tmp; int32_t iambob,n = 0; + printf("LP_utxopurge mypub.(%s)\n",bits256_str(str,LP_mypub25519)); + portable_mutex_lock(&LP_utxomutex); + for (iambob=0; iambob<=1; iambob++) + { + HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) + { + if ( LP_isavailable(utxo) > 0 ) + { + if ( allutxos != 0 || LP_ismine(utxo) > 0 ) + { + printf("iambob.%d delete.(%s)\n",iambob,bits256_str(str,utxo->payment.txid)); + HASH_DELETE(hh,LP_utxoinfos[iambob],utxo); + //free(utxo); let the LP_utxoinfos2 free the utxo, should be 1:1 + } else n++; + } else n++; + } + HASH_ITER(hh,LP_utxoinfos2[iambob],utxo,tmp) + { + if ( LP_isavailable(utxo) > 0 ) + { + if ( allutxos != 0 || LP_ismine(utxo) > 0 ) + { + printf("iambob.%d delete2.(%s)\n",iambob,bits256_str(str,utxo->payment.txid)); + HASH_DELETE(hh2,LP_utxoinfos2[iambob],utxo); + free(utxo); + } else n++; + } else n++; + } + } + portable_mutex_unlock(&LP_utxomutex); + return(n); +} +/*struct LP_utxoinfo *_LP_butxo_find(struct LP_utxoinfo *butxo) + { + int32_t i; struct LP_utxoinfo *utxo=0; uint32_t now = (uint32_t)time(NULL); + //portable_mutex_lock(&LP_butxomutex); + for (i=0; ipayment.vout == utxo->payment.vout && butxo->deposit.vout == utxo->deposit.vout && bits256_nonz(butxo->payment.txid) != 0 && bits256_nonz(butxo->deposit.txid) != 0 && bits256_cmp(butxo->payment.txid,utxo->payment.txid) == 0 && bits256_cmp(butxo->deposit.txid,utxo->deposit.txid) == 0 ) + break; + if ( utxo->S.swap == 0 && now > utxo->T.swappending ) + memset(utxo,0,sizeof(*utxo)); + utxo = 0; + } + //portable_mutex_unlock(&LP_butxomutex); + return(utxo); + } + + struct LP_utxoinfo *LP_butxo_add(struct LP_utxoinfo *butxo) + { + static struct LP_utxoinfo zeroes; + int32_t i; struct LP_utxoinfo *utxo=0; + portable_mutex_lock(&LP_butxomutex); + if ( (utxo= _LP_butxo_find(butxo)) == 0 ) + { + for (i=0; iS = srcutxo->S; + destutxo->T = srcutxo->T; + } + + void LP_butxo_swapfields(struct LP_utxoinfo *butxo) + { + struct LP_utxoinfo *getutxo=0; + portable_mutex_lock(&LP_butxomutex); + if ( (getutxo= _LP_butxo_find(butxo)) != 0 ) + LP_butxo_swapfields_copy(butxo,getutxo); + portable_mutex_unlock(&LP_butxomutex); + } + + void LP_butxo_swapfields_set(struct LP_utxoinfo *butxo) + { + struct LP_utxoinfo *setutxo; + if ( (setutxo= LP_butxo_add(butxo)) != 0 ) + { + LP_butxo_swapfields_copy(setutxo,butxo); + } + }*/ +/*struct LP_utxoinfo BUTXOS[100]; + + int32_t LP_butxo_findeither(bits256 txid,int32_t vout) + { + struct LP_utxoinfo *utxo; int32_t i,retval = 0; + portable_mutex_lock(&LP_butxomutex); + for (i=0; ipayment.vout && bits256_cmp(txid,utxo->payment.txid)) == 0 || (vout == utxo->deposit.vout && bits256_cmp(txid,utxo->deposit.txid) == 0) ) + { + retval = 1; + break; + } + } + portable_mutex_unlock(&LP_butxomutex); + return(retval); + }*/ + +struct LP_utxoinfo *LP_utxoaddjson(int32_t iambob,int32_t pubsock,cJSON *argjson) +{ + struct LP_utxoinfo *utxo; + if ( jobj(argjson,"iambob") == 0 || iambob != jint(argjson,"iambob") ) + { + printf("LP_utxoaddjson: iambob.%d != arg.%d obj.%p (%s)\n",iambob,jint(argjson,"iambob"),jobj(argjson,"iambob"),jprint(argjson,0)); + return(0); + } + portable_mutex_lock(&LP_UTXOmutex); + utxo = LP_utxoadd(iambob,pubsock,jstr(argjson,"coin"),jbits256(argjson,"txid"),jint(argjson,"vout"),j64bits(argjson,"value"),jbits256(argjson,"txid2"),jint(argjson,"vout2"),j64bits(argjson,"value2"),jstr(argjson,"script"),jstr(argjson,"address"),jbits256(argjson,"pubkey"),jstr(argjson,"gui"),juint(argjson,"session")); + if ( LP_ismine(utxo) > 0 && utxo->T.lasttime == 0 ) + { + utxo->T.lasttime = (uint32_t)time(NULL); + printf("set lasttime!\n"); + } + portable_mutex_unlock(&LP_UTXOmutex); + return(utxo); +} + + +int32_t LP_utxosparse(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; bits256 txid; struct LP_utxoinfo *utxo; + //printf("parse.(%s)\n",retstr); + if ( (array= cJSON_Parse(retstr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; iT.lasttime = now; + } + } + if ( (destpeer= LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport)) != 0 ) + { + destpeer->numutxos = n; + } + } + free_json(array); + } + return(n); +} +void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector) +{ + //cJSON *argjson; struct _LP_utxoinfo u; char *msg; + if ( utxo == 0 ) + return; + utxo->T.spentflag = (uint32_t)time(NULL); + /*if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 ) + LP_mypeer->numutxos--; + if ( LP_mypubsock >= 0 ) + { + argjson = cJSON_CreateObject(); + jaddstr(argjson,"method","checktxid"); + jaddbits256(argjson,"txid",utxo->payment.txid); + jaddnum(argjson,"vout",utxo->payment.vout); + if ( selector != 0 ) + { + if ( bits256_nonz(utxo->deposit.txid) != 0 ) + u = utxo->deposit; + else u = utxo->fee; + jaddbits256(argjson,"checktxid",u.txid); + jaddnum(argjson,"checkvout",u.vout); + } + msg = jprint(argjson,1); + /LP_send(LP_mypubsock,msg,(int32_t)strlen(msg)+1,1); + }*/ +} +char *LP_utxos(int32_t iambob,struct LP_peerinfo *mypeer,char *symbol,int32_t lastn) +{ + int32_t i,n,m; uint64_t val,val2; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray(); + printf("deprecated! LP_utxos\n"); + //n = mypeer != 0 ? mypeer->numutxos : 0; + if ( lastn <= 0 ) + lastn = LP_PROPAGATION_SLACK * 2; + HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) + { + //char str[65]; printf("check %s.%s\n",utxo->coin,bits256_str(str,utxo->payment.txid)); + if ( (symbol == 0 || symbol[0] == 0 || strcmp(symbol,utxo->coin) == 0) && utxo->T.spentflag == 0 ) + { + u = (iambob != 0) ? utxo->deposit : utxo->fee; + if ( LP_iseligible(&val,&val2,utxo->iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,u.txid,u.vout) == 0 ) + { + char str[65]; printf("iambob.%d not eligible (%.8f %.8f) %s %s/v%d\n",iambob,dstr(val),dstr(val2),utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout); + continue; + } else jaddi(utxosjson,LP_utxojson(utxo)); + } + } + if ( (n= cJSON_GetArraySize(utxosjson)) > lastn ) + { + m = n - lastn; + for (i=0; i 0 ) + { + memset(zero.bytes,0,sizeof(zero)); + msg = jprint(LP_utxojson(utxo),1); + LP_broadcast_message(LP_mypubsock,utxo->coin,"",zero,msg); + } +} + +/*char *LP_spentcheck(cJSON *argjson) + { + bits256 txid,checktxid; int32_t vout,checkvout; struct LP_utxoinfo *utxo; int32_t iambob,retval = 0; + txid = jbits256(argjson,"txid"); + vout = jint(argjson,"vout"); + for (iambob=0; iambob<=1; iambob++) + { + if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 && utxo->T.spentflag == 0 ) + { + if ( jobj(argjson,"check") == 0 ) + checktxid = txid, checkvout = vout; + else + { + checktxid = jbits256(argjson,"checktxid"); + checkvout = jint(argjson,"checkvout"); + } + if ( LP_txvalue(0,utxo->coin,checktxid,checkvout) == 0 ) + { + //if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 ) + // LP_mypeer->numutxos--; + utxo->T.spentflag = (uint32_t)time(NULL); + retval++; + printf("indeed txid was spent\n"); + } + } + } + if ( retval > 0 ) + return(clonestr("{\"result\":\"marked as spent\"}")); + return(clonestr("{\"error\":\"cant find txid to check spent status\"}")); + }*/ + + +/*char *LP_pricestr(char *base,char *rel,double origprice) + { + cJSON *retjson; double price = 0.; + if ( base != 0 && base[0] != 0 && rel != 0 && rel[0] != 0 ) + { + price = LP_price(base,rel); + if ( origprice > SMALLVAL && origprice < price ) + price = origprice; + } + if ( LP_pricevalid(price) > 0 ) + { + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jaddstr(retjson,"method","postprice"); + jaddbits256(retjson,"pubkey",G.LP_mypub25519); + jaddstr(retjson,"base",base); + jaddstr(retjson,"rel",rel); + jaddnum(retjson,"price",price); + jadd(retjson,"theoretical",LP_priceinfomatrix(0)); + jadd(retjson,"quotes",LP_priceinfomatrix(1)); + return(jprint(retjson,1)); + } else return(clonestr("{\"error\":\"cant find baserel pair\"}")); + }*/ +void LP_utxo_spentcheck(int32_t pubsock,struct LP_utxoinfo *utxo) +{ + struct _LP_utxoinfo u; struct iguana_info *coin; char str[65]; uint32_t now = (uint32_t)time(NULL); + if ( IAMLP != 0 && (coin= LP_coinfind(utxo->coin)) != 0 && coin->inactive != 0 ) + return; + //printf("%s lag.%d\n",bits256_str(str,utxo->txid),now-utxo->lastspentcheck); + if ( utxo->T.spentflag == 0 && now > utxo->T.lastspentcheck+60 ) + { + u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; + utxo->T.lastspentcheck = now; + if ( LP_txvalue(0,utxo->coin,utxo->payment.txid,utxo->payment.vout) == 0 ) + { + printf("txid.%s %s/v%d %.8f has been spent\n",utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout,dstr(utxo->payment.value)); + LP_spentnotify(utxo,0); + } + else if ( LP_txvalue(0,utxo->coin,u.txid,u.vout) == 0 ) + { + printf("txid2.%s %s/v%d %.8f has been spent\n",utxo->coin,bits256_str(str,u.txid),u.vout,dstr(u.value)); + LP_spentnotify(utxo,1); + } + } +} + +int32_t LP_peer_utxosquery(struct LP_peerinfo *mypeer,uint16_t myport,int32_t pubsock,struct LP_peerinfo *peer,uint32_t now,int32_t interval,int32_t maxentries) +{ + int32_t lastn,n = -1; + if ( peer->lastutxos < now-interval ) + { + //lastn = peer->numutxos - mypeer->numutxos + LP_PROPAGATION_SLACK; + //if ( lastn < LP_PROPAGATION_SLACK * 2 ) + lastn = LP_PROPAGATION_SLACK * 2; + if ( mypeer == 0 || strcmp(peer->ipaddr,mypeer->ipaddr) != 0 ) + { + peer->lastutxos = now; + //printf("query utxos from %s\n",peer->ipaddr); + n = LP_utxosquery(mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,maxentries); + } + } //else printf("LP_peer_utxosquery skip.(%s) %u\n",peer->ipaddr,peer->lastutxos); + return(n); +} +bestitem = LP_quotejson(qp); +if ( LP_pricevalid(price) > 0 ) +{ + if ( price <= maxprice ) + { + LP_query(ctx,myipaddr,mypubsock,"connect",qp); + //price = LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout); + LP_requestinit(&qp->R,qp->srchash,qp->desthash,qp->srccoin,qp->satoshis-2*qp->txfee,qp->destcoin,qp->destsatoshis-2*qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector); + while ( time(NULL) < expiration ) + { + if ( aliceutxo->S.swap != 0 ) + break; + sleep(3); + } + jaddnum(bestitem,"quotedprice",price); + jaddnum(bestitem,"maxprice",maxprice); + if ( (swap= aliceutxo->S.swap) == 0 ) + { + if ( (pubp= LP_pubkeyadd(qp->srchash)) != 0 ) + pubp->numerrors++; + jaddstr(bestitem,"status","couldnt establish connection"); + } + else + { + jaddstr(bestitem,"status","connected"); + jaddnum(bestitem,"requestid",swap->I.req.requestid); + jaddnum(bestitem,"quoteid",swap->I.req.quoteid); + printf("Alice r.%u qp->%u\n",swap->I.req.requestid,swap->I.req.quoteid); + } + } + else + { + jaddnum(bestitem,"quotedprice",price); + jaddnum(bestitem,"maxprice",maxprice); + jaddstr(bestitem,"status","too expensive"); + } +} +else +{ + printf("invalid price %.8f\n",price); + jaddnum(bestitem,"maxprice",maxprice); + jaddstr(bestitem,"status","no response to request"); +} +/*while ( time(NULL) < expiration ) + { + if ( (price= LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout)) > SMALLVAL ) + { + printf("break out of price %.8f %s/%s\n",price,qp->srccoin,qp->destcoin); + break; + } + sleep(1); + }*/ + +if ( aliceutxo->S.swap == 0 ) +LP_availableset(aliceutxo); +return(jprint(bestitem,0)); +} +if ( 0 && (retstr= issue_LP_listunspent(peer->ipaddr,peer->port,coin->symbol,"")) != 0 ) +{ + if ( (array2= cJSON_Parse(retstr)) != 0 ) + { + if ( (m= cJSON_GetArraySize(array2)) > 0 ) + { + for (j=0; j %.8f n.%d\n",coinaddr,dstr(metric>>16),(uint16_t)metric); + if ( (ap= LP_addressfind(coin,coinaddr)) == 0 || _LP_unspents_metric(ap->total,ap->n) != metric ) + { + if ( ap == 0 || ap->n < (metric & 0xffff) ) + { + if ( (retstr2= issue_LP_listunspent(peer->ipaddr,peer->port,coin->symbol,coinaddr)) != 0 ) + { + if ( (array3= cJSON_Parse(retstr2)) != 0 ) + { + LP_unspents_array(coin,coinaddr,array3); + //printf("pulled.(%s)\n",retstr2); + free_json(array3); + } + free(retstr2); + } + } //else printf("wait for %s to pull %d vs %d\n",peer->ipaddr,ap!=0?ap->n:-1,(uint16_t)metric); + } + } + } + } + free_json(array2); + } + //printf("processed.(%s)\n",retstr); + free(retstr); +} +/*if ( time(NULL) > coin->lastmonitor+60 ) + { + //portable_mutex_lock(&coin->addrmutex); + HASH_ITER(hh,coin->addresses,ap,atmp) + { + if ( coin->electrum == 0 ) + { + LP_listunspent_issue(coin->symbol,ap->coinaddr); + DL_FOREACH_SAFE(ap->utxos,up,utmp) + { + if ( up->spendheight <= 0 ) + { + if ( LP_txvalue(0,coin->symbol,up->U.txid,up->U.vout) == 0 ) + up->spendheight = 1; + } + } + } + } + //portable_mutex_unlock(&coin->addrmutex); + coin->lastmonitor = (uint32_t)time(NULL); + }*/ + +/*cJSON *LP_tradecandidates(char *base) + { + struct LP_peerinfo *peer,*tmp; struct LP_quoteinfo Q; char *utxostr,coinstr[16]; cJSON *array,*retarray=0,*item; int32_t i,n,totaladded,added; + totaladded = 0; + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + printf("%s:%u %s\n",peer->ipaddr,peer->port,base); + n = added = 0; + if ( (utxostr= issue_LP_clientgetutxos(peer->ipaddr,peer->port,base,100)) != 0 ) + { + printf("%s:%u %s %s\n",peer->ipaddr,peer->port,base,utxostr); + if ( (array= cJSON_Parse(utxostr)) != 0 ) + { + if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) + { + retarray = cJSON_CreateArray(); + for (i=0; i 0 ) { memset(&Q,0,sizeof(Q)); for (i=0; ivout == vout && bits256_cmp(array[i]->txid,txid) == 0) || (array[i]->vout2 == vout && bits256_cmp(array[i]->txid2,txid) == 0) ) + return(i); + return(-1); + }*/ +//char str[65],str2[65]; printf("check utxo.%s/v%d from %s\n",bits256_str(str,utxo->payment.txid),utxo->payment.vout,bits256_str(str2,utxo->pubkey)); +//if ( strcmp(base,utxo->coin) == 0 && LP_isavailable(utxo) > 0 && pubp != 0 && (price= pubp->matrix[baseid][relid]) > SMALLVAL ) +//if ( polarity > 0 ) +// minsatoshis = utxo->S.satoshis; +//else minsatoshis = utxo->S.satoshis * price; +/*if ( LP_orderbookfind(*arrayp,cachednum,utxo->payment.txid,utxo->payment.vout) < 0 ) + { + if ( LP_iseligible(&val,&val2,utxo->iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,utxo->deposit.txid,utxo->deposit.vout) == 0 ) + continue; + if ( polarity > 0 ) + basesatoshis = utxo->S.satoshis; + else basesatoshis = utxo->S.satoshis * price; + //char str[65]; printf("found utxo not in orderbook %s/v%d %.8f %.8f\n",bits256_str(str,utxo->payment.txid),utxo->payment.vout,dstr(basesatoshis),polarity > 0 ? price : 1./price); + if ( (op= LP_orderbookentry(base,rel,utxo->payment.txid,utxo->payment.vout,utxo->deposit.txid,utxo->deposit.vout,polarity > 0 ? price : 1./price,basesatoshis,utxo->pubkey,now - pubp->timestamp)) != 0 ) + { + *arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1)); + (*arrayp)[num++] = op; + if ( LP_ismine(utxo) > 0 && utxo->T.lasttime == 0 ) + LP_utxo_clientpublish(utxo); + } + }*/ +void LP_price_broadcastloop(void *ctx) +{ + struct LP_priceinfo *basepp,*relpp; double price; int32_t baseind,relind; + sleep(30); + while ( 1 ) + { + for (baseind=0; baseindsymbol[0] == 0 ) + continue; + for (relind=0; relindsymbol[0] == 0 ) + continue; + if ( basepp != 0 && relpp != 0 && (price= relpp->myprices[basepp->ind]) > SMALLVAL) + { + //printf("automated price broadcast %s/%s %.8f\n",relpp->symbol,basepp->symbol,price); + LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,relpp->symbol,basepp->symbol,price); + } + } + } + sleep(LP_ORDERBOOK_DURATION * .9); + } +} +//else if ( strcmp(method,"checktxid") == 0 ) +// retstr = LP_spentcheck(argjson); +//else if ( IAMLP == 0 && LP_isdisabled(base,rel) != 0 ) +// return(clonestr("{\"result\":\"at least one of coins disabled\"}")); +//else if ( IAMLP == 0 && LP_isdisabled(jstr(argjson,"coin"),0) != 0 ) +// retstr = clonestr("{\"result\":\"coin is disabled\"}"); +/*if ( strcmp(method,"broadcast") == 0 ) + { + bits256 zero; char *cipherstr; int32_t cipherlen; uint8_t cipher[LP_ENCRYPTED_MAXSIZE]; + if ( (reqjson= LP_dereference(argjson,"broadcast")) != 0 ) + { + Broadcaststr = jprint(reqjson,0); + if ( (cipherstr= jstr(reqjson,"cipher")) != 0 ) + { + cipherlen = (int32_t)strlen(cipherstr) >> 1; + if ( cipherlen <= sizeof(cipher) ) + { + decode_hex(cipher,cipherlen,cipherstr); + LP_queuesend(calc_crc32(0,&cipher[2],cipherlen-2),LP_mypubsock,base,rel,cipher,cipherlen); + } else retstr = clonestr("{\"error\":\"cipher too big\"}"); + } + else + { + memset(zero.bytes,0,sizeof(zero)); + //printf("broadcast.(%s)\n",Broadcaststr); + LP_reserved_msg(base!=0?base:jstr(argjson,"coin"),rel,zero,jprint(reqjson,0)); + } + retstr = clonestr("{\"result\":\"success\"}"); + } else retstr = clonestr("{\"error\":\"couldnt dereference sendmessage\"}"); + } + else*/ + +/*relvol = bot->totalrelvolume * .1; + p = LP_pricevol_invert(&v,bot->maxprice,relvol); + if ( bot->dispdir > 0 ) + { + printf("simulated trade buy %s/%s maxprice %.8f volume %.8f, %.8f %s -> %s, price %.8f relvol %.8f\n",bot->base,bot->rel,bot->maxprice,bot->totalrelvolume - bot->relsum,relvol,bot->rel,bot->base,bot->maxprice,relvol); + } + else + { + minprice = LP_pricevol_invert(&basevol,bot->maxprice,bot->totalrelvolume - bot->relsum); + printf("simulated trade sell %s/%s minprice %.8f volume %.8f, %.8f %s -> %s price %.8f relvol %.8f\n",bot->rel,bot->base,minprice,basevol,v,bot->base,bot->rel,p,relvol); + } + if ( (LP_rand() % 2) == 0 ) + { + bot->relsum += relvol; + bot->basesum += v; + bot->completed++; + } + else + { + bot->pendrelsum += relvol; + bot->pendbasesum += v; + bot->numpending++; + } + bot->numtrades++; + */ +#ifdef FROM_JS +int32_t sentbytes,sock,peerind,maxind; +if ( (maxind= LP_numpeers()) > 0 ) +peerind = (LP_rand() % maxind) + 1; +else peerind = 1; +sock = LP_peerindsock(&peerind); +if ( sock >= 0 ) +{ + if ( (sentbytes= nn_send(sock,msg,msglen,0)) != msglen ) + printf("LP_send sent %d instead of %d\n",sentbytes,msglen); + else printf("sent %d bytes of %d to sock.%d\n",sentbytes,msglen,sock); + } else printf("couldnt get valid sock\n"); +#else + +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 ( sock0 >= 0 && LP_sockcheck(sock0) > 0 ) + { + if ( (sentbytes= nn_send(sock0,msg,msglen,0)) != msglen ) + printf("_LP_queuesend0 sent %d instead of %d\n",sentbytes,msglen); + else + { + printf("Q sent %u msglen.%d (%s)\n",crc32,msglen,msg); + sock0 = -1; + } + } + if ( sock1 >= 0 && LP_sockcheck(sock1) > 0 ) + { + if ( (sentbytes= nn_send(sock1,msg,msglen,0)) != msglen ) + printf("_LP_queuesend1 sent %d instead of %d\n",sentbytes,msglen); + else + { + printf("Q sent1 %u msglen.%d (%s)\n",crc32,msglen,msg); + sock1 = -1; + } + } + if ( sock0 < 0 && sock1 < 0 ) + return;*/ + } + else + { + if ( (maxind= LP_numpeers()) > 0 ) + peerind = (LP_rand() % maxind) + 1; + else peerind = 1; + sock0 = LP_peerindsock(&peerind); + if ( (maxind= LP_numpeers()) > 0 ) + peerind = (LP_rand() % maxind) + 1; + else peerind = 1; + sock1 = LP_peerindsock(&peerind); + } + if ( sock0 >= 0 ) + _LP_sendqueueadd(crc32,sock0,msg,msglen,needack * peerind); + if ( sock1 >= 0 ) + _LP_sendqueueadd(crc32,sock1,msg,msglen,needack); +} + +if ( 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_price_broadcastloop,(void *)ctx) != 0 ) +{ + printf("error launching LP_swapsloop for port.%u\n",myport); + exit(-1); +} +void LP_queuesend(uint32_t crc32,int32_t pubsock,char *base,char *rel,uint8_t *msg,int32_t msglen) +{ + //struct iguana_info *coin; int32_t flag=0,socks[2]; + portable_mutex_lock(&LP_networkmutex); + if ( pubsock >= 0 ) + { + //socks[0] = socks[1] = -1; + //if ( rel != 0 && rel[0] != 0 && (coin= LP_coinfind(rel)) != 0 && coin->bussock >= 0 ) + // socks[flag++] = coin->bussock; + //if ( base != 0 && base[0] != 0 && (coin= LP_coinfind(base)) != 0 && coin->bussock >= 0 ) + // socks[flag++] = coin->bussock; + //if ( flag == 0 && pubsock >= 0 ) + _LP_queuesend(crc32,pubsock,-1,msg,msglen,0); + //else _LP_queuesend(socks[0],socks[1],msg,msglen,0); + } else _LP_queuesend(crc32,-1,-1,msg,msglen,1); + portable_mutex_unlock(&LP_networkmutex); +} +#ifdef oldway +struct LP_utxoinfo *LP_bestutxo(double *ordermatchpricep,int64_t *bestsatoshisp,int64_t *bestdestsatoshisp,struct LP_utxoinfo *autxo,char *base,double maxprice,int32_t duration,uint64_t txfee,uint64_t desttxfee,uint64_t maxdestsatoshis) +{ + int64_t satoshis,destsatoshis; uint64_t val,val2; bits256 txid,pubkey; char *obookstr; cJSON *orderbook,*asks,*item; struct LP_utxoinfo *butxo,*bestutxo = 0; int32_t i,n,j,vout,numasks; double bestmetric=0.,metric,vol,price,qprice,bestprice = 0.; struct LP_pubkeyinfo *pubp; + *ordermatchpricep = 0.; + *bestsatoshisp = *bestdestsatoshisp = 0; + if ( duration <= 0 ) + duration = LP_ORDERBOOK_DURATION; + if ( maxprice <= 0. || LP_priceinfofind(base) == 0 ) + return(0); + LP_txfees(&txfee,&desttxfee,base,autxo->coin); + if ( (obookstr= LP_orderbook(base,autxo->coin,duration)) != 0 ) + { + if ( (orderbook= cJSON_Parse(obookstr)) != 0 ) + { + if ( (asks= jarray(&numasks,orderbook,"asks")) != 0 ) + { + for (i=0; i 0 && price <= maxprice ) + { + //price *= 1.0001; + //if ( price > maxprice ) + // price = maxprice; + pubkey = jbits256(item,"pubkey"); + if ( bits256_cmp(pubkey,LP_mypub25519) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 && pubp->numerrors < LP_MAXPUBKEY_ERRORS ) + { + if ( bestprice == 0. ) // assumes price ordered asks + bestprice = price; + printf("item.[%d] %s\n",i,jprint(item,0)); + txid = jbits256(item,"txid"); + vout = jint(item,"vout"); + vol = jdouble(item,"volume"); + metric = price / bestprice; + printf("maxdest %.8f metric %f vol %f add pings numutxos.%d min %.8f max %.8f\n",dstr(maxdestsatoshis),metric,vol,jint(item,"numutxos"),jdouble(item,"minvolume"),jdouble(item,"maxvolume")); + // check utxos > 1 for pubkey, SPV validate recv'ed + /*if ( (butxo= LP_utxofind(1,txid,vout)) != 0 && (long long)(vol*SATOSHIDEN) == butxo->S.satoshis && LP_isavailable(butxo) > 0 && LP_ismine(butxo) == 0 && butxo->T.bestflag == 0 ) + { + printf("got butxo? %p\n",butxo); + if ( LP_iseligible(&val,&val2,butxo->iambob,butxo->coin,butxo->payment.txid,butxo->payment.vout,butxo->S.satoshis,butxo->deposit.txid,butxo->deposit.vout) > 0 ) + { + destsatoshis = ((butxo->S.satoshis - txfee) * price); + satoshis = (destsatoshis / price + 0.49) - txfee; + if ( satoshis <= 0 ) + continue; + qprice = (double)destsatoshis / satoshis; + n = (int32_t)((double)destsatoshis / desttxfee); + if ( n < 10 ) + n = 10; + else n = 3; + for (j=0; jS.satoshis,txfee,autxo->payment.value,maxdestsatoshis,desttxfee)) > price+SMALLVAL ) + break; + } + //printf("j.%d/%d qprice %.8f vs price %.8f best.(%.8f %.8f)\n",j,n,qprice,price,dstr(satoshis),dstr(destsatoshis)); + if ( metric < 1.2 && destsatoshis > desttxfee && destsatoshis-desttxfee > (autxo->payment.value / LP_MINCLIENTVOL) && satoshis-txfee > (butxo->S.satoshis / LP_MINVOL) && satoshis <= butxo->payment.value-txfee ) + { + printf("value %.8f price %.8f/%.8f best %.8f destsatoshis %.8f * metric %.8f -> (%f)\n",dstr(autxo->payment.value),price,bestprice,bestmetric,dstr(destsatoshis),metric,dstr(destsatoshis) * metric * metric * metric); + metric = dstr(destsatoshis) * metric * metric * metric; + if ( bestmetric == 0. || metric < bestmetric ) + { + bestutxo = butxo; + *ordermatchpricep = price; + *bestdestsatoshisp = destsatoshis; + *bestsatoshisp = satoshis; + bestmetric = metric; + printf("set best!\n"); + } + } // else printf("skip.(%d %d %d %d %d) metric %f destsatoshis %.8f value %.8f destvalue %.8f txfees %.8f %.8f sats %.8f\n",metric < 1.2,destsatoshis > desttxfee,destsatoshis-desttxfee > (autxo->payment.value / LP_MINCLIENTVOL),satoshis-txfee > (butxo->S.satoshis / LP_MINVOL),satoshis < butxo->payment.value-txfee,metric,dstr(destsatoshis),dstr(butxo->S.satoshis),dstr(autxo->payment.value),dstr(txfee),dstr(desttxfee),dstr(satoshis)); + } + else + { + printf("ineligible.(%.8f %.8f)\n",price,dstr(butxo->S.satoshis)); + //if ( butxo->T.spentflag == 0 ) + // butxo->T.spentflag = (uint32_t)time(NULL); + } + } + else + { + if ( butxo != 0 ) + printf("%llu %llu %d %d %d: ",(long long)(vol*SATOSHIDEN),(long long)butxo->S.satoshis,vol*SATOSHIDEN == butxo->S.satoshis,LP_isavailable(butxo) > 0,LP_ismine(butxo) == 0); + printf("cant find butxo.%p or value mismatch %.8f != %.8f or bestflag.%d\n",butxo,vol,butxo!=0?dstr(butxo->S.satoshis):0,butxo->T.bestflag); + }*/ + } else printf("self trading or blacklisted peer\n"); + } + else + { + if ( i == 0 ) + printf("maxprice %.8f vs %.8f\n",maxprice,price); + break; + } + } + if ( bestutxo == 0 ) + { + int32_t numrestraints; + for (i=numrestraints=0; iT.bestflag = 0; + //pubp->numerrors = 0; + } + } + } + printf("no bob utxo found -> cleared %d restraints\n",numrestraints); + } + } + free_json(orderbook); + } + free(obookstr); + } + printf("bestutxo.%p %.8f %.8f\n",bestutxo,*ordermatchpricep,dstr(*bestdestsatoshisp)); + if ( bestutxo == 0 || *ordermatchpricep == 0. || *bestdestsatoshisp == 0 ) + return(0); + bestutxo->T.bestflag = 1; + int32_t changed; + LP_mypriceset(&changed,autxo->coin,base,1. / *ordermatchpricep); + return(bestutxo); +} +if ( (0) ) +{ + ep = LP_electrum_info(&already,"BTC","88.198.241.196",50001,IGUANA_MAXPACKETSIZE * 10); + if ( ep != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_dedicatedloop,(void *)ep) != 0 ) + { + printf("error launching LP_dedicatedloop (%s:%u)\n",ep->ipaddr,ep->port); + exit(-1); + } else printf("launched.(%s:%u)\n",ep->ipaddr,ep->port); + electrum_test(); + } + +/*static int _LP_metric_eval(const void *a,const void *b) + { + #define aptr (*(struct LP_metricinfo **)a) + #define bptr (*(struct LP_metricinfo **)b) + if ( bptr->metric > aptr->metric ) + return(1); + else if ( bptr->metric < aptr->metric ) + return(-1); + return(0); + #undef aptr + #undef bptr + }*/ + +/*portable_mutex_lock(&ep->pendingQ.mutex); + if ( ep->pendingQ.list != 0 ) + { + printf("list %p\n",ep->pendingQ.list); + DL_FOREACH_SAFE(ep->pendingQ.list,item,tmp) + { + printf("item.%p\n",item); + if ( item->type == 0xffffffff ) + { + printf("%p purge %s",item,((struct stritem *)item)->str); + DL_DELETE(ep->pendingQ.list,item); + free(item); + } + } + } + DL_APPEND(ep->pendingQ.list,&sitem->DL); + portable_mutex_unlock(&ep->pendingQ.mutex);*/ +//printf("%p SENT.(%s) to %s:%u\n",sitem,sitem->str,ep->ipaddr,ep->port); + +char *LP_ordermatch(char *base,int64_t txfee,double maxprice,double maxvolume,char *rel,bits256 txid,int32_t vout,bits256 feetxid,int32_t feevout,int64_t desttxfee,int32_t duration) +{ + struct LP_quoteinfo Q; int64_t bestsatoshis=0,bestdestsatoshis = 0; double ordermatchprice = 0.; struct LP_utxoinfo *autxo,*bestutxo; + txfee = LP_txfeecalc(LP_coinfind(base),txfee); + desttxfee = LP_txfeecalc(LP_coinfind(rel),desttxfee); + if ( (autxo= LP_utxopairfind(0,txid,vout,feetxid,feevout)) == 0 ) + return(clonestr("{\"error\":\"cant find alice utxopair\"}")); + if ( (bestutxo= LP_bestutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,SATOSHIDEN*maxvolume)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) + return(clonestr("{\"error\":\"cant find ordermatch utxo\"}")); + if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestsatoshis,bestdestsatoshis) < 0 ) + return(clonestr("{\"error\":\"cant set ordermatch quote\"}")); + if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,LP_mypub25519,autxo->coinaddr) < 0 ) + return(clonestr("{\"error\":\"cant set ordermatch quote info\"}")); + return(jprint(LP_quotejson(&Q),1)); +} + +char *LP_autotrade(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel,double maxprice,double relvolume,int32_t timeout,int32_t duration) +{ + uint64_t desttxfee,txfee; int64_t bestsatoshis=0,bestdestsatoshis=0; struct LP_utxoinfo *autxo,*butxo,*bestutxo = 0; double qprice,ordermatchprice=0.; struct LP_quoteinfo Q; + if ( duration <= 0 ) + duration = LP_ORDERBOOK_DURATION; + if ( timeout <= 0 ) + timeout = LP_AUTOTRADE_TIMEOUT; + if ( maxprice <= 0. || relvolume <= 0. || LP_priceinfofind(base) == 0 || LP_priceinfofind(rel) == 0 ) + return(clonestr("{\"error\":\"invalid parameter\"}")); + if ( (autxo= LP_utxo_bestfit(rel,SATOSHIDEN * relvolume)) == 0 ) + return(clonestr("{\"error\":\"cant find utxo that is big enough\"}")); + LP_txfees(&txfee,&desttxfee,base,rel); + if ( (bestutxo= LP_bestutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,SATOSHIDEN*relvolume)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) + { + printf("bestutxo.%p ordermatchprice %.8f bestdestsatoshis %.8f\n",bestutxo,ordermatchprice,dstr(bestdestsatoshis)); + return(clonestr("{\"error\":\"cant find ordermatch utxo\"}")); + } + if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestsatoshis,bestdestsatoshis) < 0 ) + return(clonestr("{\"error\":\"cant set ordermatch quote\"}")); + if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,LP_mypub25519,autxo->coinaddr) < 0 ) + return(clonestr("{\"error\":\"cant set ordermatch quote info\"}")); + if ( (qprice= LP_quote_validate(&autxo,&butxo,&Q,0)) <= SMALLVAL ) + { + printf("quote validate error %.0f\n",qprice); + return(clonestr("{\"error\":\"quote validation error\"}")); + } + printf("do quote.(%s)\n",jprint(LP_quotejson(&Q),1)); + return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration)); +} +#endif + diff --git a/iguana/exchanges/LP_stats.c b/iguana/exchanges/LP_stats.c new file mode 100644 index 000000000..40569f027 --- /dev/null +++ b/iguana/exchanges/LP_stats.c @@ -0,0 +1,411 @@ + +/****************************************************************************** + * 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_stats.c +// marketmaker +// + +#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; +int32_t LP_statslog_parsequote(char *method,cJSON *lineobj); + +char *LP_stats_methods[] = { "unknown", "request", "reserved", "connect", "connected", "tradestatus" }; + +uint32_t LP_atomic_locktime(char *base,char *rel) +{ + if ( strcmp(base,"BTC") != 0 && strcmp(rel,"BTC") != 0 ) + return(INSTANTDEX_LOCKTIME); + else return(INSTANTDEX_LOCKTIME * 10); +} + +static uint32_t LP_requests,LP_reserveds,LP_connects,LP_connecteds,LP_tradestatuses,LP_parse_errors,LP_unknowns,LP_duplicates,LP_aliceids; + +void LP_tradecommand_log(cJSON *argjson) +{ + static FILE *logfp; char *jsonstr; + if ( logfp == 0 ) + { + if ( (logfp= fopen(LP_STATSLOG_FNAME,"rb+")) != 0 ) + fseek(logfp,0,SEEK_END); + else logfp = fopen(LP_STATSLOG_FNAME,"wb"); + } + if ( logfp != 0 ) + { + jsonstr = jprint(argjson,0); + fprintf(logfp,"%s\n",jsonstr); + free(jsonstr); + fflush(logfp); + } +} + +void LP_statslog_parseline(cJSON *lineobj) +{ + char *method; cJSON *obj; + if ( (method= jstr(lineobj,"method")) != 0 ) + { + if ( strcmp(method,"request") == 0 ) + LP_requests++; + else if ( strcmp(method,"reserved") == 0 ) + LP_reserveds++; + else if ( strcmp(method,"connect") == 0 ) + { + if ( (obj= jobj(lineobj,"trade")) == 0 ) + obj = lineobj; + LP_statslog_parsequote(method,obj); + LP_connects++; + } + else if ( strcmp(method,"connected") == 0 ) + { + LP_statslog_parsequote(method,lineobj); + LP_connecteds++; + } + else if ( strcmp(method,"tradestatus") == 0 ) + { + LP_statslog_parsequote(method,lineobj); + LP_tradestatuses++; + } + else + { + LP_unknowns++; + printf("parseline unknown method.(%s) (%s)\n",method,jprint(lineobj,0)); + } + } else printf("parseline no method.(%s)\n",jprint(lineobj,0)); +} + +int32_t LP_statslog_parse() +{ + static long lastpos; FILE *fp; char line[8192]; cJSON *lineobj; int32_t n = 0; + if ( (fp= fopen(LP_STATSLOG_FNAME,"rb")) != 0 ) + { + if ( lastpos > 0 ) + { + fseek(fp,0,SEEK_END); + if ( ftell(fp) > lastpos ) + fseek(fp,lastpos,SEEK_SET); + else + { + fclose(fp); + return(0); + } + } + while ( fgets(line,sizeof(line),fp) > 0 ) + { + lastpos = ftell(fp); + if ( (lineobj= cJSON_Parse(line)) != 0 ) + { + n++; + LP_statslog_parseline(lineobj); + //printf("%s\n",jprint(lineobj,0)); + free_json(lineobj); + } + } + fclose(fp); + } + return(n); +} + +struct LP_swapstats *LP_swapstats_find(uint64_t aliceid) +{ + struct LP_swapstats *sp; + HASH_FIND(hh,LP_swapstats,&aliceid,sizeof(aliceid),sp); + return(sp); +} + +struct LP_swapstats *LP_swapstats_add(uint64_t aliceid) +{ + 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); + } + return(LP_swapstats_find(aliceid)); +} + +uint64_t LP_aliceid_calc(bits256 desttxid,int32_t destvout,bits256 feetxid,int32_t feevout) +{ + return((((uint64_t)desttxid.uints[0] << 48) | ((uint64_t)destvout << 32) | ((uint64_t)feetxid.uints[0] << 16) | (uint32_t)feevout)); +} + +void LP_swapstats_line(int32_t *numtrades,uint64_t *basevols,uint64_t *relvols,char *line,struct LP_swapstats *sp) +{ + char tstr[64]; int32_t baseind,relind; + if ( (baseind= LP_priceinfoind(sp->Q.srccoin)) >= 0 ) + basevols[baseind] += sp->Q.satoshis, numtrades[baseind]++; + if ( (relind= LP_priceinfoind(sp->Q.destcoin)) >= 0 ) + relvols[relind] += sp->Q.destsatoshis, numtrades[relind]++; + sprintf(line,"%s (%s).(%s) %-4d %9s %22llu: (%.8f %5s) -> (%.8f %5s) %.8f finished.%u expired.%u",utc_str(tstr,sp->Q.timestamp),sp->alicegui,sp->bobgui,sp->ind,LP_stats_methods[sp->methodind],(long long)sp->aliceid,dstr(sp->Q.satoshis),sp->Q.srccoin,dstr(sp->Q.destsatoshis),sp->Q.destcoin,sp->qprice,sp->finished,sp->expired); +} + +bits256 LP_swapstats_txid(cJSON *argjson,char *name,bits256 oldtxid) +{ + bits256 txid,deadtxid; + decode_hex(deadtxid.bytes,32,"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"); + txid = jbits256(argjson,name); + if ( bits256_nonz(txid) != 0 ) + { + if ( bits256_cmp(deadtxid,txid) == 0 ) + { + if ( bits256_nonz(oldtxid) == 0 ) + return(deadtxid); + else return(oldtxid); + } else return(txid); + } else return(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; + safecopy(gui,sp->Q.gui,sizeof(gui)); + if ( strcmp(LP_stats_methods[sp->methodind],"tradestatus") == 0 ) + { + base = jstr(lineobj,"bob"); + rel = jstr(lineobj,"alice"); + requestid = juint(lineobj,"requestid"); + 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) ) + { + sp->bobdeposit = LP_swapstats_txid(lineobj,"bobdeposit",sp->bobdeposit); + sp->alicepayment = LP_swapstats_txid(lineobj,"alicepayment",sp->alicepayment); + sp->bobpayment = LP_swapstats_txid(lineobj,"bobpayment",sp->bobpayment); + sp->paymentspent = LP_swapstats_txid(lineobj,"paymentspent",sp->paymentspent); + sp->Apaymentspent = LP_swapstats_txid(lineobj,"Apaymentspent",sp->Apaymentspent); + sp->depositspent = LP_swapstats_txid(lineobj,"depositspent",sp->depositspent); + if ( (statusstr= jstr(lineobj,"status")) != 0 && strcmp(statusstr,"finished") == 0 ) + { + if ( (sp->finished= juint(lineobj,"timestamp")) == 0 ) + sp->finished = (uint32_t)time(NULL); + } + 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.%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); + } + + } else sp->Q = *qp; + if ( sp->Q.gui[0] == 0 || strcmp(sp->Q.gui,"nogui") == 0 ) + strcpy(sp->Q.gui,gui); + return(0); +} + +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]; + memset(numtrades,0,sizeof(numtrades)); + memset(basevols,0,sizeof(basevols)); + memset(relvols,0,sizeof(relvols)); + memset(&Q,0,sizeof(Q)); + for (i=methodind=0; imethodind = methodind; + if ( LP_swapstats_update(sp,&Q,lineobj) == 0 ) + flag = 1; + } + if ( flag == 0 ) + { + HASH_ITER(hh,LP_swapstats,sp,tmp) + { + if ( sp->Q.R.requestid == requestid && sp->Q.R.quoteid == quoteid ) + { + sp->methodind = methodind; + if ( LP_swapstats_update(sp,&Q,lineobj) == 0 ) + flag = 1; + else printf("error after delayed match\n"); + break; + } + } + } + if ( flag == 0 ) + printf("unexpected.%d tradestatus.(%s)\n",unexpected++,jprint(lineobj,0)); + return(0); + } + if ( LP_quoteparse(&Q,lineobj) < 0 ) + { + printf("quoteparse_error.(%s)\n",jprint(lineobj,0)); + LP_parse_errors++; + return(-1); + } + else + { + gui = jstr(lineobj,"gui"); + if ( gui == 0 || gui[0] == 0 ) + gui = "nogui"; + base = jstr(lineobj,"base"); + rel = jstr(lineobj,"rel"); + satoshis = j64bits(lineobj,"satoshis"); + if ( base == 0 || rel == 0 || satoshis == 0 ) + { + printf("quoteparse_error.(%s)\n",jprint(lineobj,0)); + LP_parse_errors++; + return(-1); + } + txfee = j64bits(lineobj,"txfee"); + timestamp = juint(lineobj,"timestamp"); + destsatoshis = j64bits(lineobj,"destsatoshis"); + desttxid = jbits256(lineobj,"desttxid"); + destvout = jint(lineobj,"destvout"); + feetxid = jbits256(lineobj,"feetxid"); + feevout = jint(lineobj,"feevout"); + 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); + if ( (sp= LP_swapstats_find(aliceid)) != 0 ) + { + if ( methodind > sp->methodind ) + { + sp->methodind = methodind; + LP_swapstats_update(sp,&Q,lineobj); + } + duplicate = 1; + LP_duplicates++; + } + 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"); + } + if ( sp != 0 ) + { + if ( strcmp(gui,"nogui") != 0 ) + { + if ( jint(lineobj,"iambob") != 0 ) + strcpy(sp->bobgui,gui); + else strcpy(sp->alicegui,gui); + } + } + } + return(duplicate == 0); +} + +char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey) +{ + cJSON *retjson,*array,*item; struct LP_swapstats *sp,*tmp; int32_t i,dispflag,numtrades[LP_MAXPRICEINFOS]; char line[1024]; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS]; + if ( starttime > endtime ) + starttime = endtime; + memset(basevols,0,sizeof(basevols)); + memset(relvols,0,sizeof(relvols)); + memset(numtrades,0,sizeof(numtrades)); + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jaddnum(retjson,"newlines",n); + array = cJSON_CreateArray(); + HASH_ITER(hh,LP_swapstats,sp,tmp) + { + if ( sp->finished == 0 && time(NULL) > sp->Q.timestamp+LP_atomic_locktime(sp->Q.srccoin,sp->Q.destcoin)*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 ( dispflag != 0 ) + { + 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); + } + } + jadd(retjson,"swaps",array); + array = cJSON_CreateArray(); + for (i=0; ivins != 0 ) - free_json(rawtx->vins); + free_json(rawtx->vins), rawtx->vins = 0; //if ( rawtx->txbytes != 0 ) // free(rawtx->txbytes), rawtx->txbytes = 0; } @@ -120,8 +120,22 @@ void basilisk_rawtx_purge(struct basilisk_rawtx *rawtx) void basilisk_swap_finished(struct basilisk_swap *swap) { int32_t i; - if ( swap->utxo != 0 && swap->sentflag == 0 ) + /*if ( swap->utxo != 0 && swap->sentflag == 0 ) + { LP_availableset(swap->utxo); + swap->utxo = 0; + //LP_butxo_swapfields_set(swap->utxo); + }*/ + 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); + } swap->I.finished = (uint32_t)time(NULL); // save to permanent storage basilisk_rawtx_purge(&swap->bobdeposit); @@ -173,21 +187,73 @@ 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; + data[datalen++] = swap->I.bobmaxconfirms; + data[datalen++] = swap->I.otheristrusted; + for (i=0; i<33; i++) + data[datalen++] = swap->persistent_pubkey33[i]; for (i=0; ideck)/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,len = 0; - if ( datalen == sizeof(swap->otherdeck) ) + 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),"eid); + 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++]; + bobmaxconfirms = data[len++]; + if ( aliceconfirms != swap->I.aliceconfirms || bobconfirms != swap->I.bobconfirms ) + { + printf("MISMATCHED required confirms me.(%d %d) vs (%d %d) max.(%d %d) othermax.(%d %d)\n",swap->I.aliceconfirms,swap->I.bobconfirms,aliceconfirms,bobconfirms,swap->I.alicemaxconfirms,swap->I.bobmaxconfirms,alicemaxconfirms,bobmaxconfirms); + if ( alicemaxconfirms > swap->I.alicemaxconfirms ) + alicemaxconfirms = swap->I.alicemaxconfirms; + if ( bobmaxconfirms > swap->I.bobmaxconfirms ) + bobmaxconfirms = swap->I.bobmaxconfirms; + if ( swap->I.aliceconfirms < aliceconfirms ) + swap->I.aliceconfirms = aliceconfirms; + if ( swap->I.bobconfirms < bobconfirms ) + swap->I.bobconfirms = bobconfirms; + if ( swap->I.aliceconfirms > swap->I.alicemaxconfirms || swap->I.bobconfirms > swap->I.bobmaxconfirms ) + { + printf("numconfirms (%d %d) exceeds max (%d %d)\n",swap->I.aliceconfirms,swap->I.bobconfirms,swap->I.alicemaxconfirms,swap->I.bobmaxconfirms); + return(-1); + } + } + if ( (swap->I.otherstrust= data[len++]) != 0 ) + { + if ( swap->I.otheristrusted != 0 ) + { + swap->I.aliceconfirms = swap->I.bobconfirms = 0; + printf("Otherside trusts us, adjust required confirms to: alice.%d bob.%d\n",swap->I.aliceconfirms,swap->I.bobconfirms); + } + } + printf("NUMCONFIRMS for SWAP alice.%d bob.%d, otheristrusted.%d othertrusts.%d\n",swap->I.aliceconfirms,swap->I.bobconfirms,swap->I.otheristrusted,swap->I.otherstrust); + for (i=0; i<33; i++) + if ( (other33[i]= data[len++]) != 0 ) + nonz++; + if ( nonz > 8 ) + memcpy(swap->persistent_other33,other33,33); for (i=0; iotherdeck)/sizeof(swap->otherdeck[0][0]); i++) len += iguana_rwnum(0,&data[len],sizeof(swap->otherdeck[i>>1][i&1]),&swap->otherdeck[i>>1][i&1]); return(0); } - printf("pubkeys verify size mismatch %d != %d\n",datalen,(int32_t)sizeof(swap->otherdeck)); + printf("pubkeys verify size mismatch %d != %d\n",datalen,(int32_t)(sizeof(swap->otherdeck)+38+sizeof(uint32_t)*2)); return(-1); } @@ -216,7 +282,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); @@ -229,13 +295,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 @@ -244,18 +310,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); @@ -510,7 +576,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++) @@ -529,11 +600,11 @@ int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct ba if ( rawtx->I.redeemlen > 0 && rawtx->I.redeemlen < 0x100 ) { memcpy(rawtx->redeemscript,&data[datalen],rawtx->I.redeemlen); - for (i=0; iI.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(swap,rawtx->coin,checkaddr,data,datalen); + //for (i=0; iI.redeemlen; i++) + // printf("%02x",rawtx->redeemscript[i]); + 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); @@ -560,27 +631,30 @@ int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct ba if ( recvlen != datalen+rawtx->I.redeemlen+75 ) printf("RECVLEN %d != %d + %d\n",recvlen,datalen,rawtx->I.redeemlen); txid = bits256_doublesha256(0,data,datalen); - //char str[65]; printf("rawtx.%s txid %s\n",rawtx->name,bits256_str(str,txid)); + 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)) != 0 ) + if ( (txobj= bitcoin_data2json(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) ) { @@ -592,11 +666,11 @@ int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct ba if ( rawtx == &swap->otherfee ) { char str[65]; - LP_swap_coinaddr(swap,rawtx->coin,rawtx->p2shaddr,data,datalen); + 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 ERROR.(%s) txfees.[%.8f %.8f: %.8f] amount.%.8f -> %.8f\n",rawtx->name,jprint(txobj,0),dstr(swap->I.Atxfee),dstr(swap->I.Btxfee),dstr(txfee),dstr(rawtx->I.amount),dstr(rawtx->I.amount)-dstr(txfee)); + } else printf("%s satoshis %.8f ERROR.(%s) txfees.[%.8f %.8f: %.8f] amount.%.8f -> %.8f\n",rawtx->name,dstr(j64bits(vout,"satoshis")),jprint(txobj,0),dstr(swap->I.Atxfee),dstr(swap->I.Btxfee),dstr(txfee),dstr(rawtx->I.amount),dstr(rawtx->I.amount)-dstr(txfee)); } free_json(txobj); } @@ -610,11 +684,14 @@ 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 ) { - //printf("%s rawtxsend.[%d] %s vs %s\n",rawtx->name,rawtx->I.datalen,bits256_str(str,rawtx->I.signedtxid),bits256_str(str2,rawtx->I.actualtxid)); - rawtx->I.actualtxid = rawtx->I.signedtxid; + char str[65],str2[65]; + printf("%s rawtxsend.[%d] %s vs %s\n",rawtx->name,rawtx->I.datalen,bits256_str(str,rawtx->I.signedtxid),bits256_str(str2,rawtx->I.actualtxid)); + if ( bits256_nonz(rawtx->I.signedtxid) != 0 ) + rawtx->I.actualtxid = rawtx->I.signedtxid; + else rawtx->I.signedtxid = rawtx->I.actualtxid; } if ( bits256_nonz(rawtx->I.actualtxid) != 0 && msgbits != 0 ) { @@ -635,9 +712,9 @@ 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.signedtxid,LP_SWAPSTEP_TIMEOUT) < 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 in the mempool?\n",rawtx->name,bits256_str(str,rawtx->I.actualtxid)); + 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; } return(retval); @@ -657,11 +734,11 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3 int32_t LP_swapwait(uint32_t requestid,uint32_t quoteid,int32_t duration,int32_t sleeptime) { - char *retstr; cJSON *retjson=0; uint32_t divisor=8,expiration = (uint32_t)(time(NULL) + duration); + char *retstr; cJSON *retjson=0; uint32_t expiration = (uint32_t)(time(NULL) + duration); printf("wait %d:%d for SWAP.(r%u/q%u) to complete\n",duration,sleeptime,requestid,quoteid); sleep(10); - if ( sleeptime < divisor*60 ) - sleeptime = divisor * 60; + //if ( sleeptime < divisor*60 ) + // sleeptime = divisor * 60; while ( time(NULL) < expiration ) { if ( (retstr= basilisk_swapentry(requestid,quoteid)) != 0 ) @@ -670,14 +747,16 @@ int32_t LP_swapwait(uint32_t requestid,uint32_t quoteid,int32_t duration,int32_t { if ( jstr(retjson,"status") != 0 && strcmp(jstr(retjson,"status"),"finished") == 0 ) break; + else printf("NOT FINISHED.(%s)\n",jprint(retjson,0)); free_json(retjson); retjson = 0; } free(retstr); } - sleep(sleeptime/divisor); - if ( divisor > 1 ) - divisor--; + sleep(sleeptime); + //sleep(sleeptime/divisor); + //if ( divisor > 1 ) + // divisor--; } if ( retjson != 0 ) { @@ -695,7 +774,8 @@ int32_t LP_swapwait(uint32_t requestid,uint32_t quoteid,int32_t duration,int32_t void LP_bobloop(void *_swap) { uint8_t *data; int32_t maxlen,m,n; uint32_t expiration; struct basilisk_swap *swap = _swap; - fprintf(stderr,"start swap iambob\n"); + G.LP_pendingswaps++; + printf("start swap iambob\n"); maxlen = 1024*1024 + sizeof(*swap); data = malloc(maxlen); expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT; @@ -716,52 +796,61 @@ 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); - if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT*3,LP_verify_otherfee) < 0 ) + 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 ) printf("error sending bobdeposit\n"); - else if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT*3,LP_verify_alicepayment) < 0 ) + else if ( LP_waitfor(swap->N.pair,swap,1800,LP_verify_alicepayment) < 0 ) 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 = 1; - while ( (n= LP_numconfirms(swap,&swap->alicepayment,1)) < m ) // sync with alice + else m = swap->I.aliceconfirms; + 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 to be confirmed.%d %s %s\n",n,1,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid)); - sleep(3); + 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->bobreclaim.utxovout = 0; swap->bobreclaim.utxotxid = swap->bobpayment.I.signedtxid; basilisk_bobpayment_reclaim(swap,swap->I.callduration); if ( swap->N.pair >= 0 ) nn_close(swap->N.pair), swap->N.pair = -1; - LP_swapwait(swap->I.req.requestid,swap->I.req.quoteid,4*3600,300); + LP_swap_endcritical = (uint32_t)time(NULL); + LP_swapwait(swap->I.req.requestid,swap->I.req.quoteid,LP_atomic_locktime(swap->I.bobstr,swap->I.alicestr)*2,30); } } } basilisk_swap_finished(swap); free(swap); } else printf("swap timed out\n"); + G.LP_pendingswaps--; } void LP_aliceloop(void *_swap) { uint8_t *data; int32_t maxlen,n,m; uint32_t expiration; struct basilisk_swap *swap = _swap; + G.LP_pendingswaps++; maxlen = 1024*1024 + sizeof(*swap); data = malloc(maxlen); expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT; if ( swap != 0 ) { - fprintf(stderr,"start swap iamalice pair.%d\n",swap->N.pair); + 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 ) 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 ) @@ -773,47 +862,49 @@ 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,LP_SWAPSTEP_TIMEOUT*3,LP_verify_bobdeposit) < 0 ) + 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.alicestr,"BTC") == 0 ) m = 0; - else m = 1; - while ( (n= LP_numconfirms(swap,&swap->alicepayment,1)) < m ) + 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 alicepayment to be confirmed.%d %s %s\n",n,1,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid)); - sleep(LP_SWAPSTEP_TIMEOUT); + 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); } swap->sentflag = 1; - if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT*3,LP_verify_bobpayment) < 0 ) + 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 { - while ( (n= LP_numconfirms(swap,&swap->bobpayment,1)) < swap->I.bobconfirms ) + 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 waiting for bobpayment to be confirmed.%d %s %s\n",n,swap->I.bobconfirms,swap->bobcoin.symbol,bits256_str(str,swap->bobpayment.I.signedtxid)); - sleep(LP_SWAPSTEP_TIMEOUT); + 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 ) + /*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,&swap->alicespend,1)) < swap->I.aliceconfirms ) + 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 waiting for alicespend to be confirmed.%d %s %s\n",n,swap->I.aliceconfirms,swap->bobcoin.symbol,bits256_str(str,swap->alicespend.I.signedtxid)); + 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_swapwait(swap->I.req.requestid,swap->I.req.quoteid,4*3600,300); + LP_swapwait(swap->I.req.requestid,swap->I.req.quoteid,LP_atomic_locktime(swap->I.bobstr,swap->I.alicestr)*2,30); } } } - basilisk_swap_finished(swap); - free(swap); } free(data); if ( swap->N.pair >= 0 ) @@ -821,6 +912,10 @@ void LP_aliceloop(void *_swap) nn_close(swap->N.pair); swap->N.pair = -1; } + basilisk_swap_finished(swap); + printf("finish swap.%p\n",swap); + free(swap); + G.LP_pendingswaps--; } bits256 instantdex_derivekeypair(void *ctx,bits256 *newprivp,uint8_t pubkey[33],bits256 privkey,bits256 orderhash) @@ -852,12 +947,12 @@ int32_t instantdex_pubkeyargs(struct basilisk_swap *swap,int32_t numpubs,bits256 { if ( swap->I.numpubs+2 >= numpubs ) return(numpubs); - //fprintf(stderr,">>>>>> start generating %s\n",buf); + //printf(">>>>>> start generating %s\n",buf); } for (i=n=m=0; ictx,&privkey,pubkey,privkey,hash); - //fprintf(stderr,"i.%d n.%d numpubs.%d %02x vs %02x\n",i,n,numpubs,pubkey[0],firstbyte); + //printf("i.%d n.%d numpubs.%d %02x vs %02x\n",i,n,numpubs,pubkey[0],firstbyte); if ( pubkey[0] != firstbyte ) continue; if ( n < 2 ) @@ -907,8 +1002,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; @@ -919,13 +1014,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 ) { @@ -937,22 +1032,50 @@ void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx * struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 pubkey25519,struct basilisk_swap *swap,int32_t optionduration,uint32_t statebits,struct LP_quoteinfo *qp) { //FILE *fp; char fname[512]; - uint8_t *alicepub33=0,*bobpub33=0; int32_t bobistrusted,aliceistrusted,jumblrflag=-2,x = -1; struct iguana_info *coin; - 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.expiration = swap->I.req.timestamp + swap->I.putduration + swap->I.callduration; OS_randombytes((uint8_t *)&swap->I.choosei,sizeof(swap->I.choosei)); @@ -965,92 +1088,101 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 { swap->I.iambob = 0; swap->I.otherhash = swap->I.req.desthash; - aliceistrusted = 1; - bobistrusted = LP_pubkey_istrusted(swap->I.req.desthash); + swap->I.aliceistrusted = 1; + swap->I.otheristrusted = swap->I.bobistrusted = LP_pubkey_istrusted(swap->I.req.srchash); } else { swap->I.iambob = 1; swap->I.otherhash = swap->I.req.srchash; - bobistrusted = 1; - aliceistrusted = LP_pubkey_istrusted(swap->I.req.desthash); + swap->I.bobistrusted = 1; + swap->I.otheristrusted = swap->I.aliceistrusted = LP_pubkey_istrusted(swap->I.req.desthash); } if ( bits256_nonz(privkey) == 0 || (x= instantdex_pubkeyargs(swap,2 + INSTANTDEX_DECKSIZE,privkey,swap->I.orderhash,0x02+swap->I.iambob)) != 2 + INSTANTDEX_DECKSIZE ) { 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 = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.bobconfirms); + 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 = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.aliceconfirms); + swap->I.bobconfirms = BASILISK_DEFAULT_NUMCONFIRMS; } else { swap->I.bobconfirms = BASILISK_DEFAULT_NUMCONFIRMS; swap->I.aliceconfirms = BASILISK_DEFAULT_NUMCONFIRMS; } - swap->I.bobconfirms *= !bobistrusted; - swap->I.aliceconfirms *= !aliceistrusted; - printf(">>>>>>>>>> jumblrflag.%d <<<<<<<<< use smart address, %.8f bobconfs.%d, %.8f aliceconfs.%d taddr.%d %d\n",jumblrflag,dstr(swap->I.bobsatoshis),swap->I.bobconfirms,dstr(swap->I.alicesatoshis),swap->I.aliceconfirms,swap->bobcoin.taddr,swap->alicecoin.taddr); + if ( bobcoin->isassetchain != 0 ) + swap->I.bobconfirms = 1; + if ( alicecoin->isassetchain != 0 ) + swap->I.aliceconfirms = 1; + 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= alicecoin->maxconfirms) == 0 ) + swap->I.alicemaxconfirms = BASILISK_DEFAULT_MAXCONFIRMS; + if ( swap->I.bobconfirms > swap->I.bobmaxconfirms ) + swap->I.bobconfirms = swap->I.bobmaxconfirms; + if ( swap->I.aliceconfirms > swap->I.alicemaxconfirms ) + swap->I.aliceconfirms = swap->I.alicemaxconfirms; + swap->I.bobconfirms *= !swap->I.bobistrusted; + swap->I.aliceconfirms *= !swap->I.aliceistrusted; + printf(">>>>>>>>>> jumblrflag.%d <<<<<<<<< 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),0,0,jumblrflag); - basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,&swap->alicecoin,0,0,LP_DEXFEE(swap->I.alicesatoshis),0,0,jumblrflag); + basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,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),0,0,jumblrflag); - basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,&swap->alicecoin,0,0,LP_DEXFEE(swap->I.alicesatoshis),0,0,jumblrflag); + basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,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; } - 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); + 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,bobcoin,swap->I.bobconfirms,0,LP_DEPOSITSATOSHIS(swap->I.bobsatoshis) + 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 + 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 + 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->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; - 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)); + else + { + swap->myfee.utxotxid = qp->feetxid, swap->myfee.utxovout = 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 [%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); } @@ -1058,11 +1190,15 @@ struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 { struct basilisk_swap *swap; bits256 pubkey25519; uint8_t pubkey33[33]; swap = calloc(1,sizeof(*swap)); + swap->aliceid = LP_aliceid_calc(qp->desttxid,qp->destvout,qp->feetxid,qp->feevout); swap->I.req.quoteid = rp->quoteid; swap->ctx = bitcoin_ctx(); vcalc_sha256(0,swap->I.orderhash.bytes,(uint8_t *)rp,sizeof(*rp)); swap->I.req = *rp; - printf("basilisk_thread_start request.%u iambob.%d (%s/%s) quoteid.%u\n",rp->requestid,iambob,rp->src,rp->dest,rp->quoteid); + 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("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; diff --git a/iguana/exchanges/LP_tradebots.c b/iguana/exchanges/LP_tradebots.c new file mode 100644 index 000000000..d4a2fdfd5 --- /dev/null +++ b/iguana/exchanges/LP_tradebots.c @@ -0,0 +1,684 @@ + +/****************************************************************************** + * 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_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)) != 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; inumtrades; 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; inumtrades; 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 ) + { + jaddnum(json,"completed",bot->completed); + 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 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; inumtrades; 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; inumtrades; 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; struct LP_tradebot *bot,*tmp; + DL_FOREACH_SAFE(LP_tradebots,bot,tmp) + { + if ( (relcoin= LP_coinfind(bot->rel)) != 0 ) + LP_listunspent_issue(bot->rel,relcoin->smartaddr,1); + 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; int32_t i,n; cJSON *array,*item,*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; ielectrum != 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 ( dstr(abalance) < relvolume && 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); +} + diff --git a/iguana/exchanges/LP_transaction.c b/iguana/exchanges/LP_transaction.c index 2fcb6d89a..d61940855 100644 --- a/iguana/exchanges/LP_transaction.c +++ b/iguana/exchanges/LP_transaction.c @@ -18,20 +18,94 @@ // LP_transaction.c // marketmaker // +bits256 LP_privkeyfind(uint8_t rmd160[20]) +{ + int32_t i; static bits256 zero; + for (i=0; i no privkey\n"); + return(zero); +} + +int32_t LP_privkeyadd(bits256 privkey,uint8_t rmd160[20]) +{ + bits256 tmpkey; + tmpkey = LP_privkeyfind(rmd160); + if ( bits256_nonz(tmpkey) != 0 ) + return(-bits256_cmp(privkey,tmpkey)); + G.LP_privkeys[G.LP_numprivkeys].privkey = privkey; + memcpy(G.LP_privkeys[G.LP_numprivkeys].rmd160,rmd160,20); + //int32_t i; for (i=0; i<20; i++) + // printf("%02x",rmd160[i]); + //char str[65]; printf(" -> add privkey.(%s)\n",bits256_str(str,privkey)); + G.LP_numprivkeys++; + return(G.LP_numprivkeys); +} + +bits256 LP_privkey(char *coinaddr,uint8_t taddr) +{ + bits256 privkey; uint8_t addrtype,rmd160[20]; + bitcoin_addr2rmd160(taddr,&addrtype,rmd160,coinaddr); + privkey = LP_privkeyfind(rmd160); + return(privkey); +} + +bits256 LP_pubkey(bits256 privkey) +{ + bits256 pubkey; + pubkey = curve25519(privkey,curve25519_basepoint9()); + return(pubkey); +} + +int32_t LP_gettx_presence(char *symbol,bits256 expectedtxid) +{ + cJSON *txobj; bits256 txid; int32_t flag = 0; + if ( (txobj= LP_gettx(symbol,expectedtxid)) != 0 ) + { + txid = jbits256(txobj,"txid"); + if ( jobj(txobj,"error") == 0 && bits256_cmp(txid,expectedtxid) == 0 ) + { + //char str[65]; printf("%s already in gettx (%s)\n",bits256_str(str,txid),jprint(txobj,0)); + flag = 1; + } + free_json(txobj); + } + return(flag); +} bits256 LP_broadcast(char *txname,char *symbol,char *txbytes,bits256 expectedtxid) { - char *retstr; bits256 txid; cJSON *retjson,*errorobj; int32_t i,sentflag = 0; + char *retstr,*errstr; bits256 txid; uint8_t *ptr; cJSON *retjson,*errorobj; struct iguana_info *coin; int32_t i,totalretries=0,len,sentflag = 0; + coin = LP_coinfind(symbol); memset(&txid,0,sizeof(txid)); - for (i=0; i<1; i++) + if ( txbytes == 0 || txbytes[0] == 0 ) + return(txid); + if ( bits256_nonz(expectedtxid) == 0 ) + { + len = (int32_t)strlen(txbytes) >> 1; + ptr = malloc(len); + decode_hex(ptr,len,txbytes); + expectedtxid = bits256_doublesha256(0,ptr,len); + free(ptr); + } + for (i=0; i<2; i++) { - if ( (retstr= LP_sendrawtransaction(symbol,txbytes)) != 0 ) + //char str[65]; printf("LP_broadcast.%d (%s) %s i.%d sentflag.%d\n",i,symbol,bits256_str(str,expectedtxid),i,sentflag); + if ( sentflag == 0 && LP_gettx_presence(symbol,expectedtxid) != 0 ) + sentflag = 1; + if ( sentflag == 0 && (retstr= LP_sendrawtransaction(symbol,txbytes)) != 0 ) { if ( is_hexstr(retstr,0) == 64 ) { decode_hex(txid.bytes,32,retstr); if ( bits256_cmp(txid,expectedtxid) == 0 || (bits256_nonz(expectedtxid) == 0 && bits256_nonz(txid) != 0) ) + { sentflag = 1; + expectedtxid = txid; + } } else if ( (retjson= cJSON_Parse(retstr)) != 0 ) { @@ -42,15 +116,28 @@ bits256 LP_broadcast(char *txname,char *symbol,char *txbytes,bits256 expectedtxi txid = expectedtxid; sentflag = 1; } + else if ( (errstr= jstr(retjson,"error")) != 0 && strcmp(errstr,"timeout") == 0 && coin != 0 && coin->electrum != 0 ) + { + if ( totalretries < 4 ) + { + printf("time error with electrum, retry.%d\n",totalretries); + totalretries++; + i--; + } + } + else printf("broadcast error.(%s)\n",retstr); } free_json(retjson); } - char str[65]; printf("sentflag.%d [%s] %s RETSTR.(%s) %s.%s\n",sentflag,txname,txbytes,retstr,symbol,bits256_str(str,txid)); + //char str[65]; printf("sentflag.%d [%s] %s RETSTR.(%s) %s.%s\n",sentflag,txname,txbytes,retstr,symbol,bits256_str(str,txid)); free(retstr); } if ( sentflag != 0 ) break; + sleep(3); } + if ( sentflag != 0 ) + return(expectedtxid); return(txid); } @@ -170,7 +257,10 @@ int32_t iguana_msgtx_Vset(uint8_t *serialized,int32_t maxlen,struct iguana_msgtx int32_t iguana_interpreter(struct iguana_info *coin,cJSON *logarray,int64_t nLockTime,struct vin_info *V,int32_t numvins) { - uint8_t script[IGUANA_MAXSCRIPTSIZE],*activescript,savescript[IGUANA_MAXSCRIPTSIZE]; char str[IGUANA_MAXSCRIPTSIZE*2+1]; int32_t vini,scriptlen,activescriptlen,savelen,errs = 0; cJSON *spendscript,*item=0; + uint8_t *script,*activescript,*savescript; char *str; int32_t vini,scriptlen,activescriptlen,savelen,errs = 0; cJSON *spendscript,*item=0; + script = calloc(1,IGUANA_MAXSCRIPTSIZE); + savescript = calloc(1,IGUANA_MAXSCRIPTSIZE); + str = calloc(1,IGUANA_MAXSCRIPTSIZE*2+1); for (vini=0; vinitx_out; @@ -324,7 +417,9 @@ int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype, script = msgtx->vins[vini].spendscript; scriptlen = msgtx->vins[vini].spendlen; } - sigtxid = bitcoin_sigtxid(taddr,pubtype,p2shtype,isPoS,height,serialized,maxlen,msgtx,vini,script,scriptlen,sighash,vpnstr,suppress_pubkeys); + if ( zcash == LP_IS_BITCOINCASH ) + sighash |= SIGHASH_FORKID; + sigtxid = bitcoin_sigtxid(taddr,pubtype,p2shtype,isPoS,height,serialized,maxlen,msgtx,vini,script,scriptlen,sighash,vpnstr,suppress_pubkeys,zcash); if ( bits256_nonz(sigtxid) != 0 ) { vp = &V[vini]; @@ -380,7 +475,7 @@ int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype, } iguana_msgtx_Vset(serialized,maxlen,msgtx,V); cJSON *txobj = cJSON_CreateObject(); - *signedtx = iguana_rawtxbytes(taddr,pubtype,p2shtype,isPoS,height,txobj,msgtx,suppress_pubkeys); + *signedtx = iguana_rawtxbytes(taddr,pubtype,p2shtype,isPoS,height,txobj,msgtx,suppress_pubkeys,zcash); //printf("SIGNEDTX.(%s)\n",jprint(txobj,1)); *signedtxidp = msgtx->txid; return(complete); @@ -394,9 +489,9 @@ int64_t iguana_lockval(int32_t finalized,int64_t locktime) return(lockval); } -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 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) { - uint8_t *serialized,*serialized2,*serialized3,*serialized4,*extraspace,pubkeys[64][33]; int32_t finalized,i,len,n,z,plen,maxsize,complete = 0,extralen = 65536; char *privkeystr,*signedtx = 0; bits256 privkeys[64],privkey,txid; cJSON *item; cJSON *txobj = 0; + uint8_t *serialized,*serialized2,*serialized3,*serialized4,*extraspace,pubkeys[64][33]; int32_t finalized,i,len,n,z,plen,maxsize,complete = 0,extralen = 100000; char *privkeystr,*signedtx = 0; bits256 privkeys[LP_MAXVINS],privkey,txid; cJSON *item; cJSON *txobj = 0; maxsize = 1000000; memset(privkey.bytes,0,sizeof(privkey)); if ( rawtx != 0 && rawtx[0] != 0 && (len= (int32_t)strlen(rawtx)>>1) < maxsize ) @@ -408,16 +503,16 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_ extraspace = malloc(extralen); memset(msgtx,0,sizeof(*msgtx)); decode_hex(serialized,len,rawtx); - // printf("call hex2json.(%s) vins.(%s)\n",rawtx,jprint(vins,0)); - if ( (txobj= bitcoin_hex2json(taddr,pubtype,p2shtype,isPoS,height,&txid,msgtx,rawtx,extraspace,extralen,serialized4,vins,V->suppress_pubkeys)) != 0 ) + if ( (txobj= bitcoin_hex2json(taddr,pubtype,p2shtype,isPoS,height,&txid,msgtx,rawtx,extraspace,extralen,serialized4,vins,V->suppress_pubkeys,zcash)) != 0 ) { //printf("back from bitcoin_hex2json (%s)\n",jprint(vins,0)); - } else fprintf(stderr,"no txobj from bitcoin_hex2json\n"); + } else printf("no txobj from bitcoin_hex2json\n"); + //printf("call hex2json.(%s) vins.(%s)\n",rawtx,jprint(vins,0)); if ( (numinputs= cJSON_GetArraySize(vins)) > 0 ) { - //printf("numinputs.%d msgtx.%d\n",numinputs,msgtx->tx_in); + //printf("numinputs.%d (%s) msgtx.%d\n",numinputs,jprint(vins,0),msgtx->tx_in); memset(msgtx,0,sizeof(*msgtx)); - if ( iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,0,0,serialized,maxsize,msgtx,&txid,"",extraspace,65536,vins,V->suppress_pubkeys) > 0 && numinputs == msgtx->tx_in ) + if ( iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,0,0,serialized,maxsize,msgtx,&txid,"",extraspace,extralen,vins,V->suppress_pubkeys,zcash) > 0 && numinputs == msgtx->tx_in ) { memset(pubkeys,0,sizeof(pubkeys)); memset(privkeys,0,sizeof(privkeys)); @@ -440,7 +535,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_ { if ( msgtx->vins[i].p2shlen != 0 ) { - char coinaddr[64]; uint32_t userdatalen,sigsize,pubkeysize; uint8_t *userdata; int32_t j,k,hashtype,type,flag; struct vin_info mvin,mainvin; bits256 zero; + char coinaddr[64]; uint32_t userdatalen,hashtype,sigsize,pubkeysize; uint8_t *userdata; int32_t j,k,type,flag; struct vin_info mvin,mainvin; bits256 zero; memset(zero.bytes,0,sizeof(zero)); coinaddr[0] = 0; sigsize = 0; @@ -504,7 +599,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_ } finalized = iguana_vininfo_create(taddr,pubtype,p2shtype,isPoS,serialized2,maxsize,msgtx,vins,numinputs,V); //printf("finalized.%d ignore_cltverr.%d suppress.%d\n",finalized,V[0].ignore_cltverr,V[0].suppress_pubkeys); - if ( (complete= bitcoin_verifyvins(ctx,symbol,taddr,pubtype,p2shtype,isPoS,height,signedtxidp,&signedtx,msgtx,serialized3,maxsize,V,SIGHASH_ALL,1,V->suppress_pubkeys)) > 0 && signedtx != 0 ) + if ( (complete= bitcoin_verifyvins(ctx,symbol,taddr,pubtype,p2shtype,isPoS,height,signedtxidp,&signedtx,msgtx,serialized3,maxsize,V,SIGHASH_ALL,1,V->suppress_pubkeys,zcash)) > 0 && signedtx != 0 ) { /*int32_t tmp; //char str[65]; if ( (tmp= iguana_interpreter(ctx,cJSON_CreateArray(),iguana_lockval(finalized,jint(txobj,"locktime")),V,numinputs)) < 0 ) @@ -514,7 +609,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_ } else printf("interpreter passed\n");*/ } else printf("complete.%d\n",complete); } else printf("rwmsgtx error\n"); - } else fprintf(stderr,"no inputs in vins.(%s)\n",vins!=0?jprint(vins,0):"null"); + } else printf("no inputs in vins.(%s)\n",vins!=0?jprint(vins,0):"null"); free(extraspace); free(serialized), free(serialized2), free(serialized3), free(serialized4); } else return(-1); @@ -524,9 +619,106 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_ return(complete); } -char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privkey,bits256 *privkey2p,uint8_t *redeemscript,int32_t redeemlen,uint8_t *userdata,int32_t userdatalen,bits256 utxotxid,int32_t vout,char *destaddr,uint8_t *pubkey33,int32_t finalseqid,uint32_t expiration,int64_t *destamountp,uint64_t satoshis,char *changeaddr,char *vinaddr,int32_t suppress_pubkeys) +char *iguana_validaterawtx(void *ctx,struct iguana_info *coin,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,char *rawtx,int32_t mempool,int32_t suppress_pubkeys,int32_t zcash) +{ + bits256 signedtxid; struct iguana_msgvin vin; cJSON *log,*vins,*vouts,*txobj,*retjson; char *signedtx; int32_t plen,height,finalized = 1,i,len,maxsize,numinputs,numoutputs,complete; struct vin_info *V; uint8_t *serialized,*serialized2; uint32_t sigsize,pubkeysize,p2shsize,suffixlen; int64_t inputsum,outputsum; struct iguana_msgvout vout; + char *symbol; uint8_t wiftaddr,taddr,pubtype,p2shtype,isPoS; + height = coin->longestchain; + symbol = coin->symbol; + wiftaddr = coin->wiftaddr; + taddr = coin->taddr; + pubtype = coin->pubtype; + p2shtype = coin->p2shtype; + isPoS = coin->isPoS; + retjson = cJSON_CreateObject(); + inputsum = outputsum = numinputs = numoutputs = 0; + if ( rawtx != 0 && rawtx[0] != 0 ) + { + if ( (strlen(rawtx) & 1) != 0 ) + return(clonestr("{\"error\":\"rawtx hex has odd length\"}")); + memset(msgtx,0,sizeof(*msgtx)); + if ( (txobj= bitcoin_hex2json(taddr,pubtype,p2shtype,isPoS,height,&msgtx->txid,msgtx,rawtx,extraspace,extralen,0,0,suppress_pubkeys,zcash)) != 0 ) + { + maxsize = (int32_t)strlen(rawtx); + serialized = malloc(maxsize); + serialized2 = malloc(maxsize); + V = calloc(numinputs,sizeof(*V)); + if ( (vouts= jarray(&numoutputs,txobj,"vout")) > 0 ) + { + for (i=0; i 0 ) + outputsum += vout.value; + } + } + if ( (vins= jarray(&numinputs,txobj,"vin")) > 0 ) + { + len = 0; + for (i=0; ivins[i].spendscript = V[i].spendscript; + if ( (msgtx->vins[i].spendlen= V[i].spendlen) == 35 ) + { + if ( (plen= bitcoin_pubkeylen(msgtx->vins[i].spendscript+1)) > 0 ) + { + memcpy(V[i].signers[0].pubkey,msgtx->vins[i].spendscript+1,plen); + V[i].suppress_pubkeys = 1; + } + } + V[i].hashtype = iguana_vinscriptparse(taddr,pubtype,p2shtype,&V[i],&sigsize,&pubkeysize,&p2shsize,&suffixlen,msgtx->vins[i].vinscript,msgtx->vins[i].scriptlen); + if ( (V[i].signers[0].siglen= sigsize) > 0 ) + memcpy(V[i].signers[0].sig,msgtx->vins[i].vinscript+1,sigsize); + V[i].userdatalen = suffixlen; + memcpy(V[i].spendscript,msgtx->vins[i].spendscript,msgtx->vins[i].spendlen); + V[i].spendlen = msgtx->vins[i].spendlen; + if ( msgtx->vins[i].sequence < IGUANA_SEQUENCEID_FINAL ) + finalized = 0; + if ( V[i].M == 0 ) + V[i].M = 1; + if ( V[i].N < V[i].M ) + V[i].N = V[i].M; + printf("V %dof%d %.8f (%s) spendscript.[%d] scriptlen.%d\n",V[i].M,V[i].N,dstr(V[i].amount),V[i].coinaddr,V[i].spendlen,V[i].spendlen); + } + complete = bitcoin_verifyvins(ctx,symbol,taddr,pubtype,p2shtype,isPoS,height,&signedtxid,&signedtx,msgtx,serialized2,maxsize,V,SIGHASH_ALL,1,V->suppress_pubkeys,LP_IS_BITCOINCASH); + msgtx->txid = signedtxid; + log = cJSON_CreateArray(); + if ( iguana_interpreter(ctx,log,0,V,numinputs) < 0 ) + jaddstr(retjson,"error","interpreter rejects tx"); + else complete = 1; + jadd(retjson,"interpreter",log); + jaddnum(retjson,"complete",complete); + free(serialized), free(serialized2); + if ( signedtx != 0 ) + free(signedtx); + free(V); + } + } + //char str[65]; printf("got txid.(%s)\n",bits256_str(str,txid)); + } + msgtx->inputsum = inputsum; + msgtx->numinputs = numinputs; + msgtx->outputsum = outputsum; + msgtx->numoutputs = numoutputs; + msgtx->txfee = (inputsum - outputsum); + return(jprint(retjson,1)); +} + +void test_validate(char *signedtx) { - char *rawtxbytes=0,*signedtx=0,tmpaddr[64],hexstr[999],wifstr[128],txdestaddr[64],_destaddr[64]; uint8_t spendscript[512],addrtype,rmd160[20]; cJSON *txobj,*vins,*item,*privkeys; int32_t completed,spendlen,ignore_cltverr=1; struct vin_info V[2]; uint32_t timestamp,locktime = 0,sequenceid = 0xffffffff * finalseqid; bits256 txid; uint64_t value,change = 0; struct iguana_msgtx msgtx; + char *retstr; uint8_t extraspace[8192]; int32_t mempool=0; struct iguana_msgtx msgtx; struct iguana_info *coin = LP_coinfind("BTC"); + retstr = iguana_validaterawtx(bitcoin_ctx(),coin,&msgtx,extraspace,sizeof(extraspace),signedtx,mempool,0,coin->zcash); + printf("validate test.(%s)\n",retstr); +} + +char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privkey,bits256 *privkey2p,uint8_t *redeemscript,int32_t redeemlen,uint8_t *userdata,int32_t userdatalen,bits256 utxotxid,int32_t utxovout,char *destaddr,uint8_t *pubkey33,int32_t finalseqid,uint32_t expiration,int64_t *destamountp,uint64_t satoshis,char *changeaddr,char *vinaddr,int32_t suppress_pubkeys,int32_t zcash) +{ + char *rawtxbytes=0,*signedtx=0,str[65],tmpaddr[64],hexstr[999],wifstr[128],_destaddr[64]; uint8_t spendscript[512],addrtype,rmd160[20]; cJSON *txobj,*vins,*obj,*vouts,*item,*privkeys; int32_t completed,spendlen,n,ignore_cltverr=1; struct vin_info V[8]; uint32_t timestamp,locktime = 0,sequenceid = 0xffffffff * finalseqid; bits256 txid; uint64_t value=0,change = 0; struct iguana_msgtx msgtx; struct iguana_info *coin; + LP_mark_spent(symbol,utxotxid,utxovout); + if ( txfee > 0 && txfee < 10000 ) + txfee = 10000; *destamountp = 0; memset(signedtxidp,0,sizeof(*signedtxidp)); if ( finalseqid == 0 ) @@ -534,24 +726,40 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch //printf("bobtxspend.%s redeem.[%d]\n",symbol,redeemlen); if ( redeemlen < 0 ) return(0); -#ifndef BASILISK_DISABLESENDTX - if ( (value= LP_txvalue(txdestaddr,symbol,utxotxid,vout)) == 0 ) + value = 0; + if ( (coin= LP_coinfind(symbol)) != 0 ) { - char str[65]; - printf("basilisk_swap_bobtxspend.%s %s utxo.(%s) already spent or doesnt exist\n",name,symbol,bits256_str(str,utxotxid)); - return(0); - } -#else - value = satoshis; +#ifndef BASILISK_DISABLESENDTX + if ( (txobj= LP_gettx(symbol,utxotxid)) != 0 ) + { + if ( (vouts= jarray(&n,txobj,"vout")) != 0 && utxovout < n ) + { + obj = jitem(vouts,utxovout); + value = LP_value_extract(obj,1); + //printf("value in vout.%d %.8f (%s)\n",vout,dstr(value),jprint(txobj,0)); + } + free_json(txobj); + } else printf("cant gettx\n"); + if ( value == 0 ) + { + printf("basilisk_swap_bobtxspend.%s %s utxo.(%s).v%d already spent or doesnt exist\n",name,symbol,bits256_str(str,utxotxid),utxovout); + return(0); + } #endif + } if ( satoshis != 0 ) { if ( value < satoshis+txfee ) { - if ( satoshis > value-txfee/2 ) + if ( (value-satoshis) > 3*txfee/4 ) + { + satoshis = value - 3*txfee/4; + printf("reduce satoshis %.8f by txfee %.8f to value %.8f\n",dstr(satoshis),dstr(txfee),dstr(value)); + } + else if ( value == satoshis && (double)txfee/value < 0.25 ) { satoshis = value - txfee; - printf("reduce satoshis by txfee %.8f to %.8f\n",dstr(txfee),dstr(satoshis)); + printf("txfee allocation from value %.8f identical to satoshis: %.8f txfee %.8f\n",dstr(value),dstr(satoshis),dstr(txfee)); } else { @@ -609,7 +817,7 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch jaddstr(item,"userdata",hexstr); } jaddbits256(item,"txid",utxotxid); - jaddnum(item,"vout",vout); + jaddnum(item,"vout",utxovout); bitcoin_address(tmpaddr,taddr,pubtype,pubkey33,33); bitcoin_addr2rmd160(taddr,&addrtype,rmd160,tmpaddr); if ( redeemlen != 0 ) @@ -657,7 +865,7 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch completed = 0; memset(signedtxidp,0,sizeof(*signedtxidp)); //printf("locktime.%u sequenceid.%x rawtx.(%s) vins.(%s)\n",locktime,sequenceid,rawtxbytes,jprint(vins,0)); - if ( (completed= iguana_signrawtransaction(ctx,symbol,wiftaddr,taddr,pubtype,p2shtype,isPoS,1000000,&msgtx,&signedtx,signedtxidp,V,1,rawtxbytes,vins,privkeys)) < 0 ) + if ( (completed= iguana_signrawtransaction(ctx,symbol,wiftaddr,taddr,pubtype,p2shtype,isPoS,1000000,&msgtx,&signedtx,signedtxidp,V,1,rawtxbytes,vins,privkeys,zcash)) < 0 ) //if ( (signedtx= LP_signrawtx(symbol,signedtxidp,&completed,vins,rawtxbytes,privkeys,V)) == 0 ) printf("couldnt sign transaction.%s %s\n",name,bits256_str(str,*signedtxidp)); else if ( completed == 0 ) @@ -673,9 +881,484 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch return(signedtx); } +int32_t LP_vin_select(int32_t *aboveip,int64_t *abovep,int32_t *belowip,int64_t *belowp,struct LP_address_utxo **utxos,int32_t numunspents,uint64_t value,int32_t maxmode) +{ + int32_t i,abovei,belowi; int64_t above,below,gap,atx_value; + abovei = belowi = -1; + for (above=below=i=0; iU.value) <= 0 ) + { + //printf("illegal value.%d\n",i); + continue; + } + if ( atx_value == value ) + { + *aboveip = *belowip = i; + *abovep = *belowp = 0; + return(i); + } + else if ( atx_value > value ) + { + gap = (atx_value - value); + if ( above == 0 || gap < above ) + { + above = gap; + abovei = i; + } + } else gap = (value - atx_value); + if ( below == 0 || gap < below ) + { + below = gap; + belowi = i; + } + } + *aboveip = abovei; + *abovep = above; + *belowip = belowi; + *belowp = below; + //printf("above.%d below.%d\n",abovei,belowi); + return(abovei >= 0 && above < (below>>1) ? abovei : belowi); +} + +cJSON *LP_inputjson(bits256 txid,int32_t vout,char *spendscriptstr) +{ + cJSON *sobj,*item = cJSON_CreateObject(); + jaddbits256(item,"txid",txid); + jaddnum(item,"vout",vout); + sobj = cJSON_CreateObject(); + jaddstr(sobj,"hex",spendscriptstr); + jadd(item,"scriptPubKey",sobj); + //printf("vin.%s\n",jprint(item,0)); + return(item); +} + +uint64_t _komodo_interestnew(uint64_t nValue,uint32_t nLockTime,uint32_t tiptime) +{ + int32_t minutes; uint64_t interest = 0; + if ( (minutes= (tiptime - nLockTime) / 60) >= 60 ) + { + if ( minutes > 365 * 24 * 60 ) + minutes = 365 * 24 * 60; + minutes -= 59; + interest = ((nValue / 10512000) * minutes); + } + return(interest); +} + +int64_t LP_komodo_interest(bits256 txid,int64_t value) +{ + uint32_t nLockTime; uint32_t tiptime; int64_t interest = 0; + if ( value >= 10*SATOSHIDEN ) + { + if ( (nLockTime= LP_locktime("KMD",txid)) >= 500000000 ) + { + tiptime = (uint32_t)time(NULL) - 777; + interest = _komodo_interestnew(value,nLockTime,tiptime); + } + } + return(interest); +} + +int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_t amount,struct vin_info *V,struct LP_address_utxo **utxos,int32_t numunspents,int32_t suppress_pubkeys,int32_t ignore_cltverr,bits256 privkey,cJSON *privkeys,cJSON *vins,uint8_t *script,int32_t scriptlen,bits256 utxotxid,int32_t utxovout,int32_t dustcombine) +{ + char wifstr[128],spendscriptstr[128],str[65]; int32_t i,j,maxiters,n,numpre,ind,abovei,belowi,maxmode=0; struct vin_info *vp; cJSON *txobj; struct LP_address_utxo *up,*min0,*min1,*preselected[3]; int64_t value,interest,interestsum,above,below,remains = amount,total = 0; + *totalp = 0; + interestsum = 0; + init_hexbytes_noT(spendscriptstr,script,scriptlen); + bitcoin_priv2wif(coin->wiftaddr,wifstr,privkey,coin->wiftype); + n = 0; + min0 = min1 = 0; + memset(preselected,0,sizeof(preselected)); + for (j=numpre=0; jU.vout && bits256_cmp(utxotxid,up->U.txid) == 0 ) + { + preselected[numpre++] = up; + printf("found utxotxid in slot.%d\n",j); + utxos[j] = 0; + continue; + } + if ( up->spendheight <= 0 && up->U.height > 0 && up->U.value != 0 ) + { + if ( (txobj= LP_gettxout(coin->symbol,coin->smartaddr,up->U.txid,up->U.vout)) == 0 ) + { + up->spendheight = 1; + utxos[j] = 0; + } + else + { + if ( LP_inventory_prevent(1,coin->symbol,up->U.txid,up->U.vout) == 0 ) + { + if ( min1 == 0 || up->U.value < min1->U.value ) + { + if ( min0 == 0 || up->U.value < min0->U.value ) + { + min1 = min0; + min0 = up; + } else min1 = up; + } + } else utxos[j] = 0; + if ( 0 && utxos[j] != 0 ) + printf("gettxout j.%d %s/v%d (%s)\n",j,bits256_str(str,up->U.txid),up->U.vout,jprint(txobj,0)); + free_json(txobj); + } + } else utxos[j] = 0; + } + if ( bits256_nonz(utxotxid) != 0 && numpre == 0 ) + { + up = LP_address_utxofind(coin,coin->smartaddr,utxotxid,utxovout); + //printf("have utxotxid but wasnt found up.%p\n",up); + if ( up == 0 ) + { + value = LP_txvalue(0,coin->symbol,utxotxid,utxovout); + LP_address_utxoadd((uint32_t)time(NULL),"withdraw",coin,coin->smartaddr,utxotxid,utxovout,value,1,-1); + //printf("added after not finding\n"); + } + if ( (up= LP_address_utxofind(coin,coin->smartaddr,utxotxid,utxovout)) != 0 ) + preselected[numpre++] = up; + else + { + printf("couldnt add address_utxo after not finding\n"); + return(0); + } + } + if ( dustcombine >= 1 && min0 != 0 && min0->U.value < LP_DUSTCOMBINE_THRESHOLD && (coin->electrum == 0 || min0->SPV > 0) ) + { + for (j=0; j= 2 && min1 != 0 && min1->U.value < LP_DUSTCOMBINE_THRESHOLD && (coin->electrum == 0 || min1->SPV > 0) ) + { + for (j=0; jU.txid),up->U.vout,dstr(up->U.value)); + } + else + { + below = above = 0; + abovei = belowi = -1; + if ( LP_vin_select(&abovei,&above,&belowi,&below,utxos,numunspents,remains,maxmode) < 0 ) + { + printf("error finding unspent i.%d of %d, %.8f vs %.8f\n",i,numunspents,dstr(remains),dstr(amount)); + return(0); + } + if ( belowi < 0 || abovei >= 0 ) + ind = abovei; + else ind = belowi; + if ( ind < 0 ) + { + printf("error finding unspent i.%d of %d, %.8f vs %.8f, abovei.%d belowi.%d ind.%d\n",i,numunspents,dstr(remains),dstr(amount),abovei,belowi,ind); + return(0); + } + up = utxos[ind]; + utxos[ind] = utxos[--numunspents]; + utxos[numunspents] = 0; + for (j=0; jsymbol,coin->smartaddr,up->U.txid,up->U.vout) < 0 ) + continue; + } + + up->spendheight = 1; + total += up->U.value; + remains -= up->U.value; + interest = 0; + if ( up->U.height < 7777777 && strcmp(coin->symbol,"KMD") == 0 ) + { + if ( 0 && (interest= LP_komodo_interest(up->U.txid,up->U.value)) > 0 ) + { + interestsum += interest; + char str[65]; printf("%s/%d %.8f interest %.8f -> sum %.8f\n",bits256_str(str,up->U.txid),up->U.vout,dstr(up->U.value),dstr(interest),dstr(interestsum)); + } + } + //printf("numunspents.%d vini.%d value %.8f, total %.8f remains %.8f interest %.8f sum %.8f %s/v%d\n",numunspents,n,dstr(up->U.value),dstr(total),dstr(remains),dstr(interest),dstr(interestsum),bits256_str(str,up->U.txid),up->U.vout); + vp = &V[n++]; + vp->N = vp->M = 1; + vp->signers[0].privkey = privkey; + jaddistr(privkeys,wifstr); + bitcoin_pubkey33(ctx,vp->signers[0].pubkey,privkey); + vp->suppress_pubkeys = suppress_pubkeys; + vp->ignore_cltverr = ignore_cltverr; + jaddi(vins,LP_inputjson(up->U.txid,up->U.vout,spendscriptstr)); + LP_unavailableset(up->U.txid,up->U.vout,(uint32_t)time(NULL)+600,G.LP_mypub25519); + if ( remains <= 0 && i >= numpre-1 ) + break; + if ( numunspents < 0 ) + { + printf("total %.8f not enough for amount %.8f\n",dstr(total),dstr(amount)); + return(0); + } + } + *totalp = total + interestsum; + return(n); +} + +char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_info *coin,struct vin_info *V,int32_t max,bits256 privkey,cJSON *outputs,cJSON *vins,cJSON *privkeys,int64_t txfee,bits256 utxotxid,int32_t utxovout,uint32_t locktime) +{ + static void *ctx; + cJSON *txobj,*item; uint8_t addrtype,rmd160[20],script[64],spendscript[256]; char *coinaddr,*rawtxbytes; bits256 txid; uint32_t timestamp; int64_t change=0,adjust=0,total,value,amount = 0; int32_t i,dustcombine,scriptlen,spendlen,suppress_pubkeys,ignore_cltverr,numvouts=0,numvins=0,numutxos=0; struct LP_address_utxo *utxos[LP_MAXVINS]; struct LP_address *ap; + if ( ctx == 0 ) + ctx = bitcoin_ctx(); + *numvinsp = 0; + *txobjp = 0; + if ( sizeof(utxos)/sizeof(*utxos) != max ) + { + printf("LP_createrawtransaction: internal error %d != max.%d\n",(int32_t)(sizeof(utxos)/sizeof(*utxos)),max); + return(0); + } + if ( coin == 0 || outputs == 0 || (numvouts= cJSON_GetArraySize(outputs)) <= 0 ) + { + printf("LP_createrawtransaction: illegal coin.%p outputs.%p or arraysize.%d, error\n",coin,outputs,numvouts); + return(0); + } + if ( coin->numutxos < LP_MINDESIRED_UTXOS ) + dustcombine = 0; + else if ( coin->numutxos >= LP_MAXDESIRED_UTXOS ) + dustcombine = 2; + else dustcombine = 1; + amount = txfee; + for (i=0; isymbol,coinaddr) <= 0 ) + { + printf("LP_createrawtransaction %s i.%d of %d is invalid\n",coinaddr,i,numvouts); + return(0); + } + if ( (value= SATOSHIDEN * jdouble(item,coinaddr)) <= 0 ) + { + printf("cant get value %s i.%d of %d %s\n",coinaddr,i,numvouts,jprint(outputs,0)); + return(0); + } + amount += value; + printf("vout.%d %.8f -> total %.8f\n",i,dstr(value),dstr(amount)); + } + else + { + printf("cant get fieldname.%d of %d %s\n",i,numvouts,jprint(outputs,0)); + return(0); + } + } + //if ( bits256_nonz(utxotxid) == 0 ) + { + if ( (ap= LP_address_utxo_reset(coin)) == 0 ) + return(0); + } + //else if ( (ap= LP_address(coin,coin->smartaddr)) == 0 ) + // return(0); + memset(utxos,0,sizeof(utxos)); + if ( (numutxos= LP_address_utxo_ptrs(coin,0,utxos,max,ap,coin->smartaddr)) <= 0 ) + { + if ( bits256_nonz(utxotxid) == 0 ) + { + printf("LP_createrawtransaction: address_utxo_ptrs %d, error\n",numutxos); + return(0); + } + } + //char str[65]; + //for (i=0; iU.txid),utxos[i]->U.vout,dstr(utxos[i]->U.value)); + + ignore_cltverr = 0; + suppress_pubkeys = 1; + scriptlen = bitcoin_standardspend(script,0,G.LP_myrmd160); + numvins = LP_vins_select(ctx,coin,&total,amount,V,utxos,numutxos,suppress_pubkeys,ignore_cltverr,privkey,privkeys,vins,script,scriptlen,utxotxid,utxovout,dustcombine); + if ( numvins <= 0 || total < amount ) + { + printf("change %.8f = total %.8f - amount %.8f, adjust %.8f numvouts.%d, txfee %.8f\n",dstr(change),dstr(total),dstr(amount),dstr(adjust),numvouts,dstr(txfee)); + printf("not enough inputs %.8f < for amount %.8f txfee %.8f\n",dstr(total),dstr(amount),dstr(txfee)); + return(0); + } + change = (total - amount); + timestamp = (uint32_t)time(NULL); + if ( locktime == 0 && strcmp("KMD",coin->symbol) == 0 ) + locktime = timestamp - 777; + txobj = bitcoin_txcreate(coin->symbol,coin->isPoS,locktime,1,timestamp); + jdelete(txobj,"vin"); + jadd(txobj,"vin",jduplicate(vins)); + if ( change < 6000 ) + { + adjust = change / numvouts; + change = 0; + } + printf("change %.8f = total %.8f - amount %.8f, adjust %.8f numvouts.%d\n",dstr(change),dstr(total),dstr(amount),dstr(adjust),numvouts); + for (i=0; itaddr,&addrtype,rmd160,coinaddr); + if ( addrtype == coin->pubtype ) + spendlen = bitcoin_standardspend(spendscript,0,rmd160); + else spendlen = bitcoin_p2shspend(spendscript,0,rmd160); + txobj = bitcoin_txoutput(txobj,spendscript,spendlen,value + adjust); + } + else + { + printf("cant get fieldname.%d of %d %s\n",i,numvouts,jprint(outputs,0)); + return(0); + } + } + if ( change != 0 ) + txobj = bitcoin_txoutput(txobj,script,scriptlen,change); + if ( (rawtxbytes= bitcoin_json2hex(coin->isPoS,&txid,txobj,V)) != 0 ) + { + } else printf("error making rawtx suppress.%d\n",suppress_pubkeys); + *txobjp = txobj; + return(rawtxbytes); +} + +char *LP_withdraw(struct iguana_info *coin,cJSON *argjson) +{ + static void *ctx; + int32_t iter,utxovout,autofee,completed=0,maxV,numvins,numvouts,datalen,suppress_pubkeys; bits256 privkey; char changeaddr[64],vinaddr[64],str[65],*signedtx=0,*rawtx=0; struct vin_info *V; uint32_t locktime; cJSON *retjson,*outputs,*vins=0,*txobj=0,*privkeys=0; struct iguana_msgtx msgtx; bits256 utxotxid,signedtxid; uint64_t txfee,newtxfee=10000; + if ( ctx == 0 ) + ctx = bitcoin_ctx(); + if ( (outputs= jarray(&numvouts,argjson,"outputs")) == 0 ) + { + printf("no outputs in argjson (%s)\n",jprint(argjson,0)); + return(clonestr("{\"error\":\"no outputs specified\"}")); + } + utxotxid = jbits256(argjson,"utxotxid"); + utxovout = jint(argjson,"utxovout"); + locktime = juint(argjson,"locktime"); + txfee = juint(argjson,"txfee"); + autofee = (strcmp(coin->symbol,"BTC") == 0); + if ( txfee == 0 ) + { + autofee = 1; + txfee = coin->txfee; + if ( txfee > 0 && txfee < 10000 ) + txfee = 10000; + } else autofee = 0; + suppress_pubkeys = 0; + memset(signedtxid.bytes,0,sizeof(signedtxid)); + safecopy(changeaddr,coin->smartaddr,sizeof(changeaddr)); + safecopy(vinaddr,coin->smartaddr,sizeof(vinaddr)); + privkey = LP_privkey(vinaddr,coin->taddr); + maxV = LP_MAXVINS; + V = malloc(maxV * sizeof(*V)); + for (iter=0; iter<2; iter++) + { + privkeys = cJSON_CreateArray(); + vins = cJSON_CreateArray(); + memset(V,0,sizeof(*V) * maxV); + if ( (rawtx= LP_createrawtransaction(&txobj,&numvins,coin,V,maxV,privkey,outputs,vins,privkeys,iter == 0 ? txfee : newtxfee,utxotxid,utxovout,locktime)) != 0 ) + { + completed = 0; + memset(&msgtx,0,sizeof(msgtx)); + memset(signedtxid.bytes,0,sizeof(signedtxid)); + if ( (completed= iguana_signrawtransaction(ctx,coin->symbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->longestchain,&msgtx,&signedtx,&signedtxid,V,numvins,rawtx,vins,privkeys,coin->zcash)) < 0 ) + printf("couldnt sign withdraw %s\n",bits256_str(str,signedtxid)); + else if ( completed == 0 ) + { + printf("incomplete signing withdraw (%s)\n",jprint(vins,0)); + if ( signedtx != 0 ) + free(signedtx), signedtx = 0; + } else printf("LP_withdraw %s -> %s\n",jprint(argjson,0),bits256_str(str,signedtxid)); + if ( signedtx == 0 ) + break; + datalen = (int32_t)strlen(signedtx) / 2; + if ( strcmp(coin->symbol,"BTC") == 0 ) + { + newtxfee = LP_txfeecalc(coin,0,datalen); + printf("txfee %.8f -> newtxfee %.8f\n",dstr(txfee),dstr(newtxfee)); + } else break; + } else break; + free_json(vins), vins = 0; + free_json(txobj), txobj = 0; + free_json(privkeys), privkeys = 0; + if ( rawtx != 0 ) + free(rawtx), rawtx = 0; + } + free(V); + if ( vins != 0 ) + free_json(vins); + if ( privkeys != 0 ) + free_json(privkeys); + retjson = cJSON_CreateObject(); + if ( rawtx != 0 ) + jaddstr(retjson,"rawtx",rawtx); + if ( signedtx != 0 ) + jaddstr(retjson,"hex",signedtx); + if ( txobj != 0 ) + jadd(retjson,"tx",txobj); + jaddbits256(retjson,"txid",signedtxid); + jadd(retjson,"complete",completed!=0?jtrue():jfalse()); + return(jprint(retjson,1)); +} + int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pubkey33,int32_t iambob,int32_t lockinputs,struct basilisk_rawtx *rawtx,uint32_t locktime,uint8_t *script,int32_t scriptlen,int64_t txfee,int32_t minconf,int32_t delay,bits256 privkey,uint8_t *changermd160,char *vinaddr) { - int32_t retval=-1,len,iter; char *signedtx,*changeaddr = 0,_changeaddr[64]; struct iguana_info *coin; int64_t newtxfee=0,destamount; + struct iguana_info *coin; int32_t len,retval=-1; char *retstr,*hexstr; cJSON *argjson,*outputs,*item,*retjson,*obj; + if ( (coin= LP_coinfind(rawtx->symbol)) == 0 ) + return(-1); + if ( strcmp(coin->smartaddr,vinaddr) != 0 ) + { + printf("???????????????????????? basilisk_rawtx_gen mismatched %s %s vinaddr.%s != (%s)\n",rawtx->symbol,coin->symbol,vinaddr,coin->smartaddr); + return(-1); + } + argjson = cJSON_CreateObject(); + jaddbits256(argjson,"utxotxid",rawtx->utxotxid); + jaddnum(argjson,"utxovout",rawtx->utxovout); + jaddnum(argjson,"locktime",locktime); + jadd64bits(argjson,"txfee",txfee); + outputs = cJSON_CreateArray(); + item = cJSON_CreateObject(); + jaddnum(item,rawtx->I.destaddr,dstr(rawtx->I.amount)); + jaddi(outputs,item); + jadd(argjson,"outputs",outputs); + if ( (retstr= LP_withdraw(coin,argjson)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( (obj= jobj(retjson,"complete")) != 0 && is_cJSON_True(obj) != 0 && (hexstr= jstr(retjson,"hex")) != 0 && (len= is_hexstr(hexstr,0)) > 16 ) + { + rawtx->I.datalen = len >> 1; + decode_hex(rawtx->txbytes,rawtx->I.datalen,hexstr); + rawtx->I.completed = 1; + rawtx->I.signedtxid = jbits256(retjson,"txid"); + retval = 0; + } + free_json(retjson); + } + free(retstr); + } + free_json(argjson); + return(retval); +#ifdef old + int32_t retval=-1,iter; char *signedtx,*changeaddr = 0,_changeaddr[64]; struct iguana_info *coin; int64_t newtxfee=0,destamount; char str2[65]; printf("%s rawtxgen.(%s/v%d)\n",rawtx->name,bits256_str(str2,rawtx->utxotxid),rawtx->utxovout); if ( (coin= rawtx->coin) == 0 ) return(-1); @@ -690,7 +1373,7 @@ int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pub txfee = LP_MIN_TXFEE; for (iter=0; iter<2; iter++) { - if ( (signedtx= basilisk_swap_bobtxspend(&rawtx->I.signedtxid,iter == 0 ? txfee : newtxfee,str,coin->symbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,ctx,privkey,0,0,0,0,0,rawtx->utxotxid,rawtx->utxovout,rawtx->I.destaddr,pubkey33,1,0,&destamount,rawtx->I.amount,changeaddr,vinaddr,rawtx->I.suppress_pubkeys)) != 0 ) + if ( (signedtx= basilisk_swap_bobtxspend(&rawtx->I.signedtxid,iter == 0 ? txfee : newtxfee,str,coin->symbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,ctx,privkey,0,0,0,0,0,rawtx->utxotxid,rawtx->utxovout,rawtx->I.destaddr,pubkey33,1,0,&destamount,rawtx->I.amount,changeaddr,vinaddr,rawtx->I.suppress_pubkeys,coin->zcash)) != 0 ) { rawtx->I.datalen = (int32_t)strlen(signedtx) >> 1; if ( rawtx->I.datalen <= sizeof(rawtx->txbytes) ) @@ -702,17 +1385,17 @@ int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pub free(signedtx); if ( strcmp(coin->symbol,"BTC") != 0 ) return(retval); - len = rawtx->I.datalen; - newtxfee = LP_txfeecalc(coin->symbol,0); + newtxfee = LP_txfeecalc(coin,0,rawtx->I.datalen); printf("txfee %.8f -> newtxfee %.8f\n",dstr(txfee),dstr(newtxfee)); } else break; if ( strcmp(str,"myfee") == 0 ) break; } return(retval); +#endif } -int32_t basilisk_rawtx_sign(char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,struct basilisk_swap *swap,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr,uint8_t *changermd160,char *vinaddr) +int32_t basilisk_rawtx_sign(char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,struct basilisk_swap *swap,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr,uint8_t *changermd160,char *vinaddr,int32_t zcash) { char *signedtx,*changeaddr = 0,_changeaddr[64]; int64_t txfee,newtxfee=0,destamount; uint32_t timestamp,locktime=0,sequenceid = 0xffffffff; int32_t iter,retval = -1; double estimatedrate; //char str2[65]; printf("%s rawtxsign.(%s/v%d)\n",dest->name,bits256_str(str2,dest->utxotxid),dest->utxovout); @@ -730,7 +1413,7 @@ int32_t basilisk_rawtx_sign(char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t } for (iter=0; iter<2; iter++) { - if ( (signedtx= basilisk_swap_bobtxspend(&dest->I.signedtxid,iter == 0 ? txfee : newtxfee,rawtx->name,symbol,wiftaddr,taddr,pubtype,p2shtype,isPoS,wiftype,swap->ctx,privkey,privkey2,rawtx->redeemscript,rawtx->I.redeemlen,userdata,userdatalen,dest->utxotxid,dest->utxovout,dest->I.destaddr,rawtx->I.pubkey33,1,0,&destamount,rawtx->I.amount,changeaddr,vinaddr,dest->I.suppress_pubkeys)) != 0 ) + if ( (signedtx= basilisk_swap_bobtxspend(&dest->I.signedtxid,iter == 0 ? txfee : newtxfee,rawtx->name,symbol,wiftaddr,taddr,pubtype,p2shtype,isPoS,wiftype,swap->ctx,privkey,privkey2,rawtx->redeemscript,rawtx->I.redeemlen,userdata,userdatalen,dest->utxotxid,dest->utxovout,dest->I.destaddr,rawtx->I.pubkey33,1,0,&destamount,rawtx->I.amount,changeaddr,vinaddr,dest->I.suppress_pubkeys,zcash)) != 0 ) { dest->I.datalen = (int32_t)strlen(signedtx) >> 1; if ( dest->I.datalen <= sizeof(dest->txbytes) ) @@ -742,7 +1425,7 @@ int32_t basilisk_rawtx_sign(char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t free(signedtx); if ( strcmp(symbol,"BTC") != 0 ) return(retval); - estimatedrate = LP_getestimatedrate(symbol); + estimatedrate = LP_getestimatedrate(LP_coinfind(symbol)); newtxfee = estimatedrate * dest->I.datalen; } else break; } @@ -766,7 +1449,7 @@ int32_t basilisk_alicescript(uint8_t *redeemscript,int32_t *redeemlenp,uint8_t * return(n); } -char *basilisk_swap_Aspend(char *name,char *symbol,uint64_t Atxfee,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privAm,bits256 privBn,bits256 utxotxid,int32_t vout,uint8_t pubkey33[33],uint32_t expiration,int64_t *destamountp,char *vinaddr) +char *basilisk_swap_Aspend(char *name,char *symbol,uint64_t Atxfee,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privAm,bits256 privBn,bits256 utxotxid,int32_t utxovout,uint8_t pubkey33[33],uint32_t expiration,int64_t *destamountp,char *vinaddr,int32_t zcash) { char msigaddr[64],*signedtx = 0; int32_t spendlen,redeemlen; uint8_t tmp33[33],redeemscript[512],spendscript[128]; bits256 pubAm,pubBn,signedtxid; uint64_t txfee; if ( bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 ) @@ -777,51 +1460,24 @@ char *basilisk_swap_Aspend(char *name,char *symbol,uint64_t Atxfee,uint8_t wifta //printf("pubAm.(%s)\n",bits256_str(str,pubAm)); //printf("pubBn.(%s)\n",bits256_str(str,pubBn)); spendlen = basilisk_alicescript(redeemscript,&redeemlen,spendscript,0,msigaddr,taddr,p2shtype,pubAm,pubBn); - //char str[65]; printf("%s utxo.(%s) redeemlen.%d spendlen.%d\n",msigaddr,bits256_str(str,utxotxid),redeemlen,spendlen); - /*rev = privAm; - for (i=0; i<32; i++) - privAm.bytes[i] = rev.bytes[31 - i]; - rev = privBn; - for (i=0; i<32; i++) - privBn.bytes[i] = rev.bytes[31 - i];*/ if ( (txfee= Atxfee) == 0 ) { - if ( (txfee= LP_getestimatedrate(symbol) * LP_AVETXSIZE) < LP_MIN_TXFEE ) + if ( (txfee= LP_getestimatedrate(LP_coinfind(symbol)) * LP_AVETXSIZE) < LP_MIN_TXFEE ) txfee = LP_MIN_TXFEE; } - //txfee = LP_txfee(symbol); - signedtx = basilisk_swap_bobtxspend(&signedtxid,txfee,name,symbol,wiftaddr,taddr,pubtype,p2shtype,isPoS,wiftype,ctx,privAm,&privBn,redeemscript,redeemlen,0,0,utxotxid,vout,0,pubkey33,1,expiration,destamountp,0,0,vinaddr,1); + signedtx = basilisk_swap_bobtxspend(&signedtxid,txfee,name,symbol,wiftaddr,taddr,pubtype,p2shtype,isPoS,wiftype,ctx,privAm,&privBn,redeemscript,redeemlen,0,0,utxotxid,utxovout,0,pubkey33,1,expiration,destamountp,0,0,vinaddr,1,zcash); + LP_mark_spent(symbol,utxotxid,utxovout); } return(signedtx); } -int32_t LP_swap_txdestaddr(char *destaddr,bits256 txid,int32_t vout,cJSON *txobj) -{ - int32_t n,m,retval = -1; cJSON *vouts,*item,*addresses,*skey; char *addr; - if ( (vouts= jarray(&n,txobj,"vout")) != 0 && vout < n ) - { - item = jitem(vouts,vout); - if ( (skey= jobj(item,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 ) - { - item = jitem(addresses,0); - if ( (addr= jstr(item,0)) != 0 ) - { - safecopy(destaddr,addr,64); - retval = 0; - } - //printf("item.(%s) -> dest.(%s)\n",jprint(item,0),destaddr); - } - } - return(retval); -} - int32_t LP_swap_getcoinaddr(char *symbol,char *coinaddr,bits256 txid,int32_t vout) { cJSON *retjson; coinaddr[0] = 0; if ( (retjson= LP_gettx(symbol,txid)) != 0 ) { - LP_swap_txdestaddr(coinaddr,txid,vout,retjson); + LP_txdestaddr(coinaddr,txid,vout,retjson); free_json(retjson); } return(coinaddr[0] != 0); @@ -904,104 +1560,25 @@ bits256 _LP_swap_spendtxid(char *symbol,char *destaddr,char *coinaddr,bits256 ut bits256 LP_swap_spendtxid(char *symbol,char *destaddr,bits256 utxotxid,int32_t vout) { - bits256 spendtxid,txid; char *catstr,*addr; cJSON *array,*item,*item2,*txobj,*vins; int32_t i,n,m,spendvin; char coinaddr[64],str[65]; + bits256 spendtxid; int32_t spendvin; char coinaddr[64],str[65]; cJSON *retjson; struct iguana_info *coin; // listtransactions or listspents destaddr[0] = 0; coinaddr[0] = 0; memset(&spendtxid,0,sizeof(spendtxid)); - if ( LP_spendsearch(&spendtxid,&spendvin,symbol,utxotxid,vout) > 0 ) - printf("spend of %s/v%d detected\n",bits256_str(str,utxotxid),vout); - return(spendtxid); - //char str[65]; printf("swap %s spendtxid.(%s)\n",symbol,bits256_str(str,utxotxid)); - if ( (0) && strcmp("BTC",symbol) == 0 ) + if ( LP_spendsearch(destaddr,&spendtxid,&spendvin,symbol,utxotxid,vout) > 0 ) { - //[{"type":"sent","confirmations":379,"height":275311,"timestamp":1492084664,"txid":"8703c5517bc57db38134058370a14e99b8e662b99ccefa2061dea311bbd02b8b","vout":0,"amount":117.50945263,"spendtxid":"cf2509e076fbb9b22514923df916b7aacb1391dce9c7e1460b74947077b12510","vin":0,"paid":{"type":"paid","txid":"cf2509e076fbb9b22514923df916b7aacb1391dce9c7e1460b74947077b12510","height":275663,"timestamp":1492106024,"vouts":[{"RUDpN6PEBsE7ZFbGjUxk1W3QVsxnjBLYw6":117.50935263}]}}] - /*LP_swap_getcoinaddr(symbol,coinaddr,utxotxid,vout); - if ( coinaddr[0] != 0 ) - spendtxid = _LP_swap_spendtxid(symbol,destaddr,coinaddr,utxotxid,vout);*/ + //printf("spend of %s/v%d detected\n",bits256_str(str,utxotxid),vout); } - else + else if ( 0 && (coin= LP_coinfind(symbol)) != 0 && coin->electrum == 0 ) { - if ( (array= LP_listtransactions(symbol,destaddr,1000,0)) != 0 ) - { - if ( (n= cJSON_GetArraySize(array)) > 0 ) - { - for (i=0; i 0 ) - { - for (i=0; i jint(item,"vout") ) - { - item2 = jitem(vins,jint(item,"vout")); - if ( bits256_cmp(utxotxid,jbits256(item2,"txid")) == 0 && vout == jint(item2,"vout") ) - { - spendtxid = txid; - break; - } - } - } - } - } - if ( i == n ) - printf("dpowlist: native couldnt find spendtxid for %s\n",bits256_str(str,utxotxid)); - } - free_json(array); - } - if ( bits256_nonz(spendtxid) != 0 ) - return(spendtxid); - } - /*if ( iguana_isnotarychain(symbol) >= 0 ) + if ( (retjson= LP_gettxout(symbol,coinaddr,utxotxid,vout)) == 0 ) { - LP_swap_getcoinaddr(symbol,coinaddr,utxotxid,vout); - printf("fallback use DEX for native (%s) (%s)\n",coinaddr,bits256_str(str,utxotxid)); - if ( coinaddr[0] != 0 ) - { - spendtxid = _LP_swap_spendtxid(symbol,destaddr,coinaddr,utxotxid,vout); - printf("spendtxid.(%s)\n",bits256_str(str,spendtxid)); - } - }*/ + decode_hex(spendtxid.bytes,32,"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"); + printf("couldnt find spend of %s/v%d, but no gettxout\n",bits256_str(str,utxotxid),vout); + } else free_json(retjson); } return(spendtxid); + //char str[65]; printf("swap %s spendtxid.(%s)\n",symbol,bits256_str(str,utxotxid)); } int32_t basilisk_swap_bobredeemscript(int32_t depositflag,int32_t *secretstartp,uint8_t *redeemscript,uint32_t locktime,bits256 pubA0,bits256 pubB0,bits256 pubB1,bits256 privAm,bits256 privBn,uint8_t *secretAm,uint8_t *secretAm256,uint8_t *secretBn,uint8_t *secretBn256) @@ -1127,59 +1704,61 @@ int32_t basilisk_swapuserdata(uint8_t *userdata,bits256 privkey,int32_t ifpath,b int32_t basilisk_bobpayment_reclaim(struct basilisk_swap *swap,int32_t delay) { - uint8_t userdata[512]; int32_t retval,len = 0; static bits256 zero; - //printf("basilisk_bobpayment_reclaim\n"); - len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[1],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); - memcpy(swap->I.userdata_bobreclaim,userdata,len); - swap->I.userdata_bobreclaimlen = len; - if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.wiftaddr,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->bobreclaim,&swap->bobpayment,swap->I.myprivs[1],0,userdata,len,1,swap->changermd160,swap->bobpayment.I.destaddr)) == 0 ) - { - //for (i=0; ibobreclaim.I.datalen; i++) - // printf("%02x",swap->bobreclaim.txbytes[i]); - //printf(" <- bobreclaim\n"); - //basilisk_txlog(swap,&swap->bobreclaim,delay); - return(retval); - } + static bits256 zero; + uint8_t userdata[512]; int32_t retval,i,len = 0; struct iguana_info *coin; + if ( (coin= LP_coinfind(swap->I.bobstr)) != 0 ) + { + //printf("basilisk_bobpayment_reclaim\n"); + len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[1],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); + memcpy(swap->I.userdata_bobreclaim,userdata,len); + swap->I.userdata_bobreclaimlen = len; + if ( (retval= basilisk_rawtx_sign(coin->symbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,swap,&swap->bobreclaim,&swap->bobpayment,swap->I.myprivs[1],0,userdata,len,1,swap->changermd160,swap->bobpayment.I.destaddr,coin->zcash)) == 0 ) + { + for (i=0; ibobreclaim.I.datalen; i++) + printf("%02x",swap->bobreclaim.txbytes[i]); + printf(" <- bobreclaim\n"); + //basilisk_txlog(swap,&swap->bobreclaim,delay); + return(retval); + } + } else printf("basilisk_bobpayment_reclaim cant find (%s)\n",swap->I.bobstr); return(-1); } int32_t basilisk_bobdeposit_refund(struct basilisk_swap *swap,int32_t delay) { - uint8_t userdata[512]; int32_t i,retval,len = 0; char str[65]; - len = basilisk_swapuserdata(userdata,swap->I.privBn,0,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); - memcpy(swap->I.userdata_bobrefund,userdata,len); - swap->I.userdata_bobrefundlen = len; - if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.wiftaddr,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->bobrefund,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,0,swap->changermd160,swap->bobdeposit.I.destaddr)) == 0 ) - { - for (i=0; ibobrefund.I.datalen; i++) - printf("%02x",swap->bobrefund.txbytes[i]); - printf(" <- bobrefund.(%s)\n",bits256_str(str,swap->bobrefund.I.txid)); - //basilisk_txlog(swap,&swap->bobrefund,delay); - return(retval); - } + uint8_t userdata[512]; int32_t i,retval,len = 0; char str[65]; struct iguana_info *coin; + if ( (coin= LP_coinfind(swap->I.bobstr)) != 0 ) + { + len = basilisk_swapuserdata(userdata,swap->I.privBn,0,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); + memcpy(swap->I.userdata_bobrefund,userdata,len); + swap->I.userdata_bobrefundlen = len; + if ( (retval= basilisk_rawtx_sign(coin->symbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,swap,&swap->bobrefund,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,0,swap->changermd160,swap->bobdeposit.I.destaddr,coin->zcash)) == 0 ) + { + for (i=0; ibobrefund.I.datalen; i++) + printf("%02x",swap->bobrefund.txbytes[i]); + printf(" <- bobrefund.(%s)\n",bits256_str(str,swap->bobrefund.I.txid)); + //basilisk_txlog(swap,&swap->bobrefund,delay); + return(retval); + } + } else printf("basilisk_bobdeposit_refund cant find (%s)\n",swap->I.bobstr); + return(-1); } -void LP_swap_coinaddr(struct basilisk_swap *swap,struct iguana_info *coin,char *coinaddr,uint8_t *data,int32_t datalen) +void LP_swap_coinaddr(struct iguana_info *coin,char *coinaddr,uint64_t *valuep,uint8_t *data,int32_t datalen,int32_t v) { - cJSON *txobj,*vouts,*vout,*addresses,*item,*skey; uint8_t extraspace[8192]; bits256 signedtxid; struct iguana_msgtx msgtx; char *addr; int32_t n,m,suppress_pubkeys = 0; - if ( (txobj= bitcoin_data2json(coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->longestchain,&signedtxid,&msgtx,extraspace,sizeof(extraspace),data,datalen,0,suppress_pubkeys)) != 0 ) + cJSON *txobj,*vouts,*vout; uint8_t extraspace[32768]; bits256 signedtxid; struct iguana_msgtx msgtx; int32_t n,suppress_pubkeys = 0; + if ( valuep != 0 ) + *valuep = 0; + if ( (txobj= bitcoin_data2json(coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->longestchain,&signedtxid,&msgtx,extraspace,sizeof(extraspace),data,datalen,0,suppress_pubkeys,coin->zcash)) != 0 ) { //char str[65]; printf("got txid.%s (%s)\n",bits256_str(str,signedtxid),jprint(txobj,0)); if ( (vouts= jarray(&n,txobj,"vout")) != 0 && n > 0 ) { - vout = jitem(vouts,0); - //printf("VOUT.(%s)\n",jprint(vout,0)); - if ( (skey= jobj(vout,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 ) - { - item = jitem(addresses,0); - //printf("item.(%s)\n",jprint(item,0)); - if ( (addr= jstr(item,0)) != 0 ) - { - safecopy(coinaddr,addr,64); - //printf("extracted.(%s)\n",coinaddr); - } - } + vout = jitem(vouts,v); + if ( valuep != 0 ) + *valuep = LP_value_extract(vout,1); + LP_destaddr(coinaddr,vout); } free_json(txobj); } @@ -1187,82 +1766,84 @@ void LP_swap_coinaddr(struct basilisk_swap *swap,struct iguana_info *coin,char * int32_t basilisk_bobscripts_set(struct basilisk_swap *swap,int32_t depositflag,int32_t genflag) { - int32_t j; char coinaddr[64],checkaddr[64]; - bitcoin_address(coinaddr,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->changermd160,20); - if ( genflag != 0 && swap->I.iambob == 0 ) - printf("basilisk_bobscripts_set WARNING: alice generating BOB tx\n"); - if ( depositflag == 0 ) - { - swap->bobpayment.I.spendlen = basilisk_bobscript(swap->bobpayment.I.rmd160,swap->bobpayment.redeemscript,&swap->bobpayment.I.redeemlen,swap->bobpayment.spendscript,0,&swap->bobpayment.I.locktime,&swap->bobpayment.I.secretstart,&swap->I,0); - bitcoin_address(swap->bobpayment.p2shaddr,swap->bobcoin.taddr,swap->bobcoin.p2shtype,swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); - strcpy(swap->bobpayment.I.destaddr,swap->bobpayment.p2shaddr); - //LP_importaddress(swap->bobcoin.symbol,swap->bobpayment.I.destaddr); - //int32_t i; for (i=0; ibobpayment.I.redeemlen; i++) - // printf("%02x",swap->bobpayment.redeemscript[i]); - //printf(" <- bobpayment redeem %d %s\n",i,swap->bobpayment.I.destaddr); - if ( genflag != 0 && bits256_nonz(*(bits256 *)swap->I.secretBn256) != 0 && swap->bobpayment.I.datalen == 0 ) - { - basilisk_rawtx_gen(swap->ctx,"payment",swap->I.started,swap->persistent_pubkey33,1,1,&swap->bobpayment,swap->bobpayment.I.locktime,swap->bobpayment.spendscript,swap->bobpayment.I.spendlen,swap->bobpayment.coin->txfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr); - if ( swap->bobpayment.I.spendlen == 0 || swap->bobpayment.I.datalen == 0 ) - { - printf("error bob generating %p payment.%d\n",swap->bobpayment.txbytes,swap->bobpayment.I.spendlen); - sleep(DEX_SLEEP); - } - else + int32_t j; char coinaddr[64],checkaddr[64]; struct iguana_info *coin; + if ( (coin= LP_coinfind(swap->I.bobstr)) != 0 ) + { + bitcoin_address(coinaddr,coin->taddr,coin->pubtype,swap->changermd160,20); + if ( genflag != 0 && swap->I.iambob == 0 ) + printf("basilisk_bobscripts_set WARNING: alice generating BOB tx\n"); + if ( depositflag == 0 ) + { + swap->bobpayment.I.spendlen = basilisk_bobscript(swap->bobpayment.I.rmd160,swap->bobpayment.redeemscript,&swap->bobpayment.I.redeemlen,swap->bobpayment.spendscript,0,&swap->bobpayment.I.locktime,&swap->bobpayment.I.secretstart,&swap->I,0); + bitcoin_address(swap->bobpayment.p2shaddr,coin->taddr,coin->p2shtype,swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); + strcpy(swap->bobpayment.I.destaddr,swap->bobpayment.p2shaddr); + //LP_importaddress(coin->symbol,swap->bobpayment.I.destaddr); + //int32_t i; for (i=0; ibobpayment.I.redeemlen; i++) + // printf("%02x",swap->bobpayment.redeemscript[i]); + //printf(" <- bobpayment redeem %d %s\n",i,swap->bobpayment.I.destaddr); + if ( genflag != 0 && bits256_nonz(*(bits256 *)swap->I.secretBn256) != 0 && swap->bobpayment.I.datalen == 0 ) { - for (j=0; jbobpayment.I.datalen; j++) - printf("%02x",swap->bobpayment.txbytes[j]); - printf(" <- bobpayment.%d\n",swap->bobpayment.I.datalen); - for (j=0; jbobpayment.I.redeemlen; j++) - printf("%02x",swap->bobpayment.redeemscript[j]); - printf(" <- redeem.%d\n",swap->bobpayment.I.redeemlen); - printf(" <- GENERATED BOB PAYMENT.%d destaddr.(%s)\n",swap->bobpayment.I.datalen,swap->bobpayment.I.destaddr); - LP_swap_coinaddr(swap,&swap->bobcoin,checkaddr,swap->bobpayment.txbytes,swap->bobpayment.I.datalen); - if ( strcmp(swap->bobpayment.I.destaddr,checkaddr) != 0 ) + basilisk_rawtx_gen(swap->ctx,"payment",swap->I.started,swap->persistent_pubkey33,1,1,&swap->bobpayment,swap->bobpayment.I.locktime,swap->bobpayment.spendscript,swap->bobpayment.I.spendlen,coin->txfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr); + if ( swap->bobpayment.I.spendlen == 0 || swap->bobpayment.I.datalen == 0 ) { - printf("BOBPAYMENT REDEEMADDR MISMATCH??? %s != %s\n",swap->bobpayment.I.destaddr,checkaddr); - return(-1); + printf("error bob generating %p payment.%d\n",swap->bobpayment.txbytes,swap->bobpayment.I.spendlen); + sleep(DEX_SLEEP); + } + else + { + for (j=0; jbobpayment.I.datalen; j++) + printf("%02x",swap->bobpayment.txbytes[j]); + printf(" <- bobpayment.%d\n",swap->bobpayment.I.datalen); + for (j=0; jbobpayment.I.redeemlen; j++) + printf("%02x",swap->bobpayment.redeemscript[j]); + printf(" <- redeem.%d\n",swap->bobpayment.I.redeemlen); + printf(" <- GENERATED BOB PAYMENT.%d destaddr.(%s)\n",swap->bobpayment.I.datalen,swap->bobpayment.I.destaddr); + LP_swap_coinaddr(coin,checkaddr,0,swap->bobpayment.txbytes,swap->bobpayment.I.datalen,0); + if ( strcmp(swap->bobpayment.I.destaddr,checkaddr) != 0 ) + { + printf("BOBPAYMENT REDEEMADDR MISMATCH??? %s != %s\n",swap->bobpayment.I.destaddr,checkaddr); + return(-1); + } + LP_unspents_mark(coin->symbol,swap->bobpayment.vins); + //printf("bobscripts set completed\n"); + return(0); } - LP_unspents_mark(swap->bobcoin.symbol,swap->bobpayment.vins); - //printf("bobscripts set completed\n"); - return(0); } } - } - else - { - swap->bobdeposit.I.spendlen = basilisk_bobscript(swap->bobdeposit.I.rmd160,swap->bobdeposit.redeemscript,&swap->bobdeposit.I.redeemlen,swap->bobdeposit.spendscript,0,&swap->bobdeposit.I.locktime,&swap->bobdeposit.I.secretstart,&swap->I,1); - bitcoin_address(swap->bobdeposit.p2shaddr,swap->bobcoin.taddr,swap->bobcoin.p2shtype,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); - strcpy(swap->bobdeposit.I.destaddr,swap->bobdeposit.p2shaddr); - //LP_importaddress(swap->bobcoin.symbol,swap->bobdeposit.I.destaddr); - int32_t i; for (i=0; ibobdeposit.I.redeemlen; i++) - printf("%02x",swap->bobdeposit.redeemscript[i]); - printf(" <- bobdeposit redeem %d %s\n",i,swap->bobdeposit.I.destaddr); - if ( genflag != 0 && (swap->bobdeposit.I.datalen == 0 || swap->bobrefund.I.datalen == 0) ) - { - basilisk_rawtx_gen(swap->ctx,"deposit",swap->I.started,swap->persistent_pubkey33,1,1,&swap->bobdeposit,swap->bobdeposit.I.locktime,swap->bobdeposit.spendscript,swap->bobdeposit.I.spendlen,swap->bobdeposit.coin->txfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr); - if ( swap->bobdeposit.I.datalen == 0 || swap->bobdeposit.I.spendlen == 0 ) - { - printf("error bob generating %p deposit.%d\n",swap->bobdeposit.txbytes,swap->bobdeposit.I.spendlen); - sleep(DEX_SLEEP); - } - else + else + { + swap->bobdeposit.I.spendlen = basilisk_bobscript(swap->bobdeposit.I.rmd160,swap->bobdeposit.redeemscript,&swap->bobdeposit.I.redeemlen,swap->bobdeposit.spendscript,0,&swap->bobdeposit.I.locktime,&swap->bobdeposit.I.secretstart,&swap->I,1); + bitcoin_address(swap->bobdeposit.p2shaddr,coin->taddr,coin->p2shtype,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); + strcpy(swap->bobdeposit.I.destaddr,swap->bobdeposit.p2shaddr); + //int32_t i; for (i=0; ibobdeposit.I.redeemlen; i++) + // printf("%02x",swap->bobdeposit.redeemscript[i]); + //printf(" <- bobdeposit redeem %d %s\n",i,swap->bobdeposit.I.destaddr); + if ( genflag != 0 && (swap->bobdeposit.I.datalen == 0 || swap->bobrefund.I.datalen == 0) ) { - for (j=0; jbobdeposit.I.datalen; j++) - printf("%02x",swap->bobdeposit.txbytes[j]); - printf(" <- GENERATED BOB DEPOSIT.%d (%s)\n",swap->bobdeposit.I.datalen,swap->bobdeposit.I.destaddr); - LP_swap_coinaddr(swap,&swap->bobcoin,checkaddr,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen); - if ( strcmp(swap->bobdeposit.I.destaddr,checkaddr) != 0 ) + basilisk_rawtx_gen(swap->ctx,"deposit",swap->I.started,swap->persistent_pubkey33,1,1,&swap->bobdeposit,swap->bobdeposit.I.locktime,swap->bobdeposit.spendscript,swap->bobdeposit.I.spendlen,coin->txfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr); + if ( swap->bobdeposit.I.datalen == 0 || swap->bobdeposit.I.spendlen == 0 ) { - printf("BOBDEPOSIT REDEEMADDR MISMATCH??? %s != %s\n",swap->bobdeposit.I.destaddr,checkaddr); - return(-1); + printf("error bob generating %p deposit.%d\n",swap->bobdeposit.txbytes,swap->bobdeposit.I.spendlen); + sleep(DEX_SLEEP); + } + else + { + for (j=0; jbobdeposit.I.datalen; j++) + printf("%02x",swap->bobdeposit.txbytes[j]); + printf(" <- GENERATED BOB DEPOSIT.%d (%s)\n",swap->bobdeposit.I.datalen,swap->bobdeposit.I.destaddr); + LP_swap_coinaddr(coin,checkaddr,0,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen,0); + if ( strcmp(swap->bobdeposit.I.destaddr,checkaddr) != 0 ) + { + printf("BOBDEPOSIT REDEEMADDR MISMATCH??? %s != %s\n",swap->bobdeposit.I.destaddr,checkaddr); + return(-1); + } + LP_unspents_mark(coin->symbol,swap->bobdeposit.vins); + printf("bobscripts set completed\n"); + return(0); } - LP_unspents_mark(swap->bobcoin.symbol,swap->bobdeposit.vins); - printf("bobscripts set completed\n"); - return(0); } } - } + } else printf("bobscripts set cant find (%s)\n",swap->I.bobstr); return(0); } @@ -1273,7 +1854,7 @@ int32_t basilisk_alicepayment_spend(struct basilisk_swap *swap,struct basilisk_r { int32_t i,retval; printf("alicepayment_spend\n"); - swap->alicepayment.I.spendlen = basilisk_alicescript(swap->alicepayment.redeemscript,&swap->alicepayment.I.redeemlen,swap->alicepayment.spendscript,0,swap->alicepayment.I.destaddr,swap->alicecoin.p2shtype,swap->I.pubAm,swap->I.pubBn); + swap->alicepayment.I.spendlen = basilisk_alicescript(swap->alicepayment.redeemscript,&swap->alicepayment.I.redeemlen,swap->alicepayment.spendscript,0,swap->alicepayment.I.destaddr,coin->p2shtype,swap->I.pubAm,swap->I.pubBn); printf("alicepayment_spend len.%d\n",swap->alicepayment.I.spendlen); if ( swap->I.iambob == 0 ) { @@ -1285,7 +1866,7 @@ int32_t basilisk_alicepayment_spend(struct basilisk_swap *swap,struct basilisk_r memcpy(swap->I.userdata_bobspend,swap->alicepayment.redeemscript,swap->alicepayment.I.spendlen); swap->I.userdata_bobspendlen = swap->alicepayment.I.spendlen; } - if ( (retval= basilisk_rawtx_sign(swap->alicecoin.symbol,swap->alicecoin.pubtype,swap->alicecoin.p2shtype,swap->alicecoin.isPoS,swap->alicecoin.wiftype,swap,dest,&swap->alicepayment,swap->I.privAm,&swap->I.privBn,0,0,1,swap->changermd160)) == 0 ) + if ( (retval= basilisk_rawtx_sign(coin->symbol,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,swap,dest,&swap->alicepayment,swap->I.privAm,&swap->I.privBn,0,0,1,swap->changermd160)) == 0 ) { for (i=0; iI.datalen; i++) printf("%02x",dest->txbytes[i]); @@ -1303,12 +1884,6 @@ void basilisk_alicepayment(struct basilisk_swap *swap,struct iguana_info *coin,s { char coinaddr[64]; alicepayment->I.spendlen = basilisk_alicescript(alicepayment->redeemscript,&alicepayment->I.redeemlen,alicepayment->spendscript,0,alicepayment->I.destaddr,coin->taddr,coin->p2shtype,pubAm,pubBn); - /*for (i=0; i<33; i++) - printf("%02x",swap->persistent_pubkey33[i]); - printf(" pubkey33, "); - for (i=0; i<20; i++) - printf("%02x",swap->changermd160[i]); - printf(" rmd160, ");*/ bitcoin_address(coinaddr,coin->taddr,coin->pubtype,swap->changermd160,20); //printf("%s suppress.%d fee.%d\n",coinaddr,alicepayment->I.suppress_pubkeys,swap->myfee.I.suppress_pubkeys); basilisk_rawtx_gen(swap->ctx,"alicepayment",swap->I.started,swap->persistent_pubkey33,0,1,alicepayment,alicepayment->I.locktime,alicepayment->spendscript,alicepayment->I.spendlen,swap->I.Atxfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr); @@ -1316,61 +1891,94 @@ void basilisk_alicepayment(struct basilisk_swap *swap,struct iguana_info *coin,s int32_t basilisk_alicetxs(int32_t pairsock,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) { - char coinaddr[64]; int32_t i,retval = -1; - if ( swap->alicepayment.I.datalen == 0 ) - basilisk_alicepayment(swap,swap->alicepayment.coin,&swap->alicepayment,swap->I.pubAm,swap->I.pubBn); - if ( swap->alicepayment.I.datalen == 0 || swap->alicepayment.I.spendlen == 0 ) - printf("error alice generating payment.%d\n",swap->alicepayment.I.spendlen); - else + char coinaddr[64]; int32_t i,retval = -1; struct iguana_info *coin; + if ( (coin= LP_coinfind(swap->I.alicestr)) != 0 ) { - bitcoin_address(swap->alicepayment.I.destaddr,swap->alicecoin.taddr,swap->alicecoin.p2shtype,swap->alicepayment.redeemscript,swap->alicepayment.I.redeemlen); - //LP_importaddress(swap->alicecoin.symbol,swap->alicepayment.I.destaddr); - strcpy(swap->alicepayment.p2shaddr,swap->alicepayment.I.destaddr); - retval = 0; - for (i=0; ialicepayment.I.datalen; i++) - printf("%02x",swap->alicepayment.txbytes[i]); - printf(" ALICE PAYMENT created.(%s)\n",swap->alicepayment.I.destaddr); - LP_unspents_mark(swap->alicecoin.symbol,swap->alicepayment.vins); - //LP_importaddress(swap->alicecoin.symbol,swap->alicepayment.I.destaddr); - //basilisk_txlog(swap,&swap->alicepayment,-1); - } - if ( swap->myfee.I.datalen == 0 ) - { - printf("generate fee %.8f\n",dstr(strcmp(swap->myfee.coin->symbol,"BTC") == 0 ? LP_MIN_TXFEE : swap->myfee.coin->txfee)); - bitcoin_address(coinaddr,swap->alicecoin.taddr,swap->alicecoin.pubtype,swap->changermd160,20); - if ( basilisk_rawtx_gen(swap->ctx,"myfee",swap->I.started,swap->persistent_pubkey33,swap->I.iambob,1,&swap->myfee,0,swap->myfee.spendscript,swap->myfee.I.spendlen,strcmp(swap->myfee.coin->symbol,"BTC") == 0 ? LP_MIN_TXFEE : swap->myfee.coin->txfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr) == 0 ) - { - printf("rawtxsend %s %.8f\n",swap->myfee.coin->symbol,dstr(strcmp(swap->myfee.coin->symbol,"BTC") == 0 ? LP_MIN_TXFEE : swap->myfee.coin->txfee)); - swap->I.statebits |= LP_swapdata_rawtxsend(pairsock,swap,0x80,data,maxlen,&swap->myfee,0x40,0); - LP_unspents_mark(swap->I.iambob!=0?swap->bobcoin.symbol:swap->alicecoin.symbol,swap->myfee.vins); - //basilisk_txlog(swap,&swap->myfee,-1); - for (i=0; imyfee.I.datalen; i++) - printf("%02x",swap->myfee.txbytes[i]); - printf(" <- fee state.%x\n",swap->I.statebits); - swap->I.statebits |= 0x40; - } + if ( swap->alicepayment.I.datalen == 0 ) + basilisk_alicepayment(swap,coin,&swap->alicepayment,swap->I.pubAm,swap->I.pubBn); + if ( swap->alicepayment.I.datalen == 0 || swap->alicepayment.I.spendlen == 0 ) + printf("error alice generating payment.%d\n",swap->alicepayment.I.spendlen); else { - printf("error creating myfee\n"); - return(-2); + bitcoin_address(swap->alicepayment.I.destaddr,coin->taddr,coin->p2shtype,swap->alicepayment.redeemscript,swap->alicepayment.I.redeemlen); + //LP_importaddress(coin->symbol,swap->alicepayment.I.destaddr); + strcpy(swap->alicepayment.p2shaddr,swap->alicepayment.I.destaddr); + retval = 0; + for (i=0; ialicepayment.I.datalen; i++) + printf("%02x",swap->alicepayment.txbytes[i]); + printf(" ALICE PAYMENT created.(%s)\n",swap->alicepayment.I.destaddr); + LP_unspents_mark(coin->symbol,swap->alicepayment.vins); + //LP_importaddress(coin->symbol,swap->alicepayment.I.destaddr); + //basilisk_txlog(swap,&swap->alicepayment,-1); } - } - if ( swap->alicepayment.I.datalen != 0 && swap->alicepayment.I.spendlen > 0 && swap->myfee.I.datalen != 0 && swap->myfee.I.spendlen > 0 ) - return(0); + if ( swap->myfee.I.datalen == 0 ) + { + printf("%s generate fee %.8f from.%s\n",coin->symbol,dstr(strcmp(coin->symbol,"BTC") == 0 ? LP_MIN_TXFEE : coin->txfee),coin->smartaddr); + bitcoin_address(coinaddr,coin->taddr,coin->pubtype,swap->changermd160,20); + if ( basilisk_rawtx_gen(swap->ctx,"myfee",swap->I.started,swap->persistent_pubkey33,swap->I.iambob,1,&swap->myfee,swap->myfee.I.locktime,swap->myfee.spendscript,swap->myfee.I.spendlen,strcmp(coin->symbol,"BTC") == 0 ? LP_MIN_TXFEE : coin->txfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr) == 0 ) + { + printf("rawtxsend %s %.8f\n",coin->symbol,dstr(strcmp(coin->symbol,"BTC") == 0 ? LP_MIN_TXFEE : coin->txfee)); + swap->I.statebits |= LP_swapdata_rawtxsend(pairsock,swap,0x80,data,maxlen,&swap->myfee,0x40,0); + LP_unspents_mark(swap->I.iambob!=0?coin->symbol:coin->symbol,swap->myfee.vins); + //basilisk_txlog(swap,&swap->myfee,-1); + for (i=0; imyfee.I.datalen; i++) + printf("%02x",swap->myfee.txbytes[i]); + printf(" <- fee state.%x\n",swap->I.statebits); + swap->I.statebits |= 0x40; + } + else + { + printf("error creating myfee\n"); + return(-2); + } + } + if ( swap->alicepayment.I.datalen != 0 && swap->alicepayment.I.spendlen > 0 && swap->myfee.I.datalen != 0 && swap->myfee.I.spendlen > 0 ) + { + printf("fee sent\n"); + return(0); + } + } else printf("basilisk alicetx cant find (%s)\n",swap->I.alicestr); return(-1); } int32_t LP_verify_otherfee(struct basilisk_swap *swap,uint8_t *data,int32_t datalen) { - if ( LP_rawtx_spendscript(swap,swap->bobcoin.longestchain,&swap->otherfee,0,data,datalen,0) == 0 ) + int32_t diff; struct iguana_info *coin; + if ( (coin= LP_coinfind(swap->I.iambob != 0 ? swap->I.alicestr : swap->I.bobstr)) != 0 ) { - printf("otherfee amount %.8f -> %s vs %s\n",dstr(swap->otherfee.I.amount),swap->otherfee.p2shaddr,swap->otherfee.I.destaddr); - if ( strcmp(swap->otherfee.I.destaddr,swap->otherfee.p2shaddr) == 0 ) + if ( LP_rawtx_spendscript(swap,coin->longestchain,&swap->otherfee,0,data,datalen,0) == 0 ) { - printf("dexfee verified\n"); - return(0); + printf("otherfee amount %.8f -> %s vs %s locktime %u vs %u\n",dstr(swap->otherfee.I.amount),swap->otherfee.p2shaddr,swap->otherfee.I.destaddr,swap->otherfee.I.locktime,swap->I.started+1); + if ( strcmp(swap->otherfee.I.destaddr,swap->otherfee.p2shaddr) == 0 ) + { + diff = swap->otherfee.I.locktime - (swap->I.started+1); + if ( diff < 0 ) + diff = -diff; + if ( diff < 10 ) + printf("dexfee verified\n"); + else printf("locktime mismatch in otherfee, reject %u vs %u\n",swap->otherfee.I.locktime,swap->I.started+1); + return(0); + } else printf("destaddress mismatch in other fee, reject (%s) vs (%s)\n",swap->otherfee.I.destaddr,swap->otherfee.p2shaddr); } - } + } else printf("cant find other coin iambob.%d\n",swap->I.iambob); + return(-1); +} + +int32_t LP_verify_alicespend(struct basilisk_swap *swap,uint8_t *data,int32_t datalen) +{ + struct iguana_info *coin; + if ( (coin= LP_coinfind(swap->I.alicestr)) != 0 ) + { + if ( LP_rawtx_spendscript(swap,coin->longestchain,&swap->alicespend,0,data,datalen,0) == 0 ) + { + printf("alicespend amount %.8f -> %s vs %s\n",dstr(swap->alicespend.I.amount),swap->alicespend.p2shaddr,swap->alicespend.I.destaddr); + if ( strcmp(swap->alicespend.I.destaddr,swap->alicespend.p2shaddr) == 0 ) + { + printf("alicespend verified\n"); + return(0); + } + } + } else printf("verify alicespend cant find (%s)\n",swap->I.alicestr); return(-1); } @@ -1383,108 +1991,120 @@ int32_t LP_verify_otherfee(struct basilisk_swap *swap,uint8_t *data,int32_t data int32_t LP_verify_bobdeposit(struct basilisk_swap *swap,uint8_t *data,int32_t datalen) { - uint8_t userdata[512]; int32_t retval=-1,len = 0; static bits256 zero; - if ( LP_rawtx_spendscript(swap,swap->bobcoin.longestchain,&swap->bobdeposit,0,data,datalen,0) == 0 ) - { - swap->aliceclaim.utxovout = 0; - swap->aliceclaim.utxotxid = swap->bobdeposit.I.signedtxid = LP_broadcast_tx(swap->bobdeposit.name,swap->bobcoin.symbol,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen); - if ( bits256_nonz(swap->bobdeposit.I.signedtxid) != 0 ) - swap->depositunconf = 1; - len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); - memcpy(swap->I.userdata_aliceclaim,userdata,len); - swap->I.userdata_aliceclaimlen = len; - bitcoin_address(swap->bobdeposit.p2shaddr,swap->bobcoin.taddr,swap->bobcoin.p2shtype,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); - strcpy(swap->bobdeposit.I.destaddr,swap->bobdeposit.p2shaddr); - basilisk_dontforget_update(swap,&swap->bobdeposit); - //LP_importaddress(swap->bobcoin.symbol,swap->bobdeposit.I.destaddr); - /*for (i=0; ibobdeposit.I.datalen; i++) - printf("%02x",swap->bobdeposit.txbytes[i]); - printf(" <- bobdeposit.%d %s\n",swap->bobdeposit.I.datalen,bits256_str(str,swap->bobdeposit.I.signedtxid)); - for (i=0; ibobdeposit.I.redeemlen; i++) - printf("%02x",swap->bobdeposit.redeemscript[i]); - printf(" <- bobdeposit redeem %d %s suppress.%d\n",i,swap->bobdeposit.I.destaddr,swap->aliceclaim.I.suppress_pubkeys);*/ - memcpy(swap->aliceclaim.redeemscript,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); - swap->aliceclaim.I.redeemlen = swap->bobdeposit.I.redeemlen; - memcpy(swap->aliceclaim.I.pubkey33,swap->persistent_pubkey33,33); - bitcoin_address(swap->aliceclaim.I.destaddr,swap->alicecoin.taddr,swap->alicecoin.pubtype,swap->persistent_pubkey33,33); - retval = 0; - if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.wiftaddr,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->aliceclaim,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,1,swap->changermd160,swap->bobdeposit.I.destaddr)) == 0 ) - { - /*for (i=0; ibobdeposit.I.datalen; i++) - printf("%02x",swap->bobdeposit.txbytes[i]); - printf(" <- bobdeposit\n"); - for (i=0; ialiceclaim.I.datalen; i++) - printf("%02x",swap->aliceclaim.txbytes[i]); - printf(" <- aliceclaim\n");*/ - //basilisk_txlog(swap,&swap->aliceclaim,swap->I.putduration+swap->I.callduration); - return(LP_waitmempool(swap->bobcoin.symbol,swap->bobdeposit.I.signedtxid,10)); - } else printf("error signing aliceclaim suppress.%d vin.(%s)\n",swap->aliceclaim.I.suppress_pubkeys,swap->bobdeposit.I.destaddr); - } + static bits256 zero; + uint8_t userdata[512]; int32_t retval=-1,len = 0; struct iguana_info *coin; + if ( (coin= LP_coinfind(swap->I.bobstr)) != 0 ) + { + if ( LP_rawtx_spendscript(swap,coin->longestchain,&swap->bobdeposit,0,data,datalen,0) == 0 ) + { + swap->aliceclaim.utxovout = 0; + swap->bobdeposit.I.signedtxid = LP_broadcast_tx(swap->bobdeposit.name,coin->symbol,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen); + if ( bits256_nonz(swap->bobdeposit.I.signedtxid) != 0 ) + swap->depositunconf = 1; + else swap->bobdeposit.I.signedtxid = swap->bobdeposit.I.actualtxid; + len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); + swap->aliceclaim.utxotxid = swap->bobdeposit.I.signedtxid; + memcpy(swap->I.userdata_aliceclaim,userdata,len); + swap->I.userdata_aliceclaimlen = len; + bitcoin_address(swap->bobdeposit.p2shaddr,coin->taddr,coin->p2shtype,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); + strcpy(swap->bobdeposit.I.destaddr,swap->bobdeposit.p2shaddr); + basilisk_dontforget_update(swap,&swap->bobdeposit); + //int32_t i; char str[65]; for (i=0; ibobdeposit.I.datalen; i++) + // printf("%02x",swap->bobdeposit.txbytes[i]); + //printf(" <- bobdeposit.%d %s\n",swap->bobdeposit.I.datalen,bits256_str(str,swap->bobdeposit.I.signedtxid)); + //for (i=0; ibobdeposit.I.redeemlen; i++) + // printf("%02x",swap->bobdeposit.redeemscript[i]); + //printf(" <- bobdeposit redeem %d %s suppress.%d\n",i,swap->bobdeposit.I.destaddr,swap->aliceclaim.I.suppress_pubkeys); + memcpy(swap->aliceclaim.redeemscript,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); + swap->aliceclaim.I.redeemlen = swap->bobdeposit.I.redeemlen; + memcpy(swap->aliceclaim.I.pubkey33,swap->persistent_pubkey33,33); + bitcoin_address(swap->aliceclaim.I.destaddr,coin->taddr,coin->pubtype,swap->persistent_pubkey33,33); + retval = 0; + if ( (retval= basilisk_rawtx_sign(coin->symbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,swap,&swap->aliceclaim,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,1,swap->changermd160,swap->bobdeposit.I.destaddr,coin->zcash)) == 0 ) + { + int32_t i; for (i=0; ibobdeposit.I.datalen; i++) + printf("%02x",swap->bobdeposit.txbytes[i]); + printf(" <- bobdeposit\n"); + for (i=0; ialiceclaim.I.datalen; i++) + printf("%02x",swap->aliceclaim.txbytes[i]); + printf(" <- aliceclaim\n"); + //basilisk_txlog(swap,&swap->aliceclaim,swap->I.putduration+swap->I.callduration); + return(LP_waitmempool(coin->symbol,swap->bobdeposit.I.destaddr,swap->bobdeposit.I.signedtxid,0,60)); + } else printf("error signing aliceclaim suppress.%d vin.(%s)\n",swap->aliceclaim.I.suppress_pubkeys,swap->bobdeposit.I.destaddr); + } + } else printf("verify bob depositcant find bob coin (%s)\n",swap->I.bobstr); printf("error with bobdeposit\n"); return(retval); } int32_t LP_verify_alicepayment(struct basilisk_swap *swap,uint8_t *data,int32_t datalen) { - if ( LP_rawtx_spendscript(swap,swap->alicecoin.longestchain,&swap->alicepayment,0,data,datalen,0) == 0 ) - { - swap->bobspend.utxovout = 0; - swap->bobspend.utxotxid = swap->alicepayment.I.signedtxid = LP_broadcast_tx(swap->alicepayment.name,swap->alicecoin.symbol,swap->alicepayment.txbytes,swap->alicepayment.I.datalen); - bitcoin_address(swap->alicepayment.p2shaddr,swap->alicecoin.taddr,swap->alicecoin.p2shtype,swap->alicepayment.redeemscript,swap->alicepayment.I.redeemlen); - strcpy(swap->alicepayment.I.destaddr,swap->alicepayment.p2shaddr); - if ( bits256_nonz(swap->alicepayment.I.signedtxid) != 0 ) - swap->aliceunconf = 1; - basilisk_dontforget_update(swap,&swap->alicepayment); - return(LP_waitmempool(swap->alicecoin.symbol,swap->alicepayment.I.signedtxid,10)); - //printf("import alicepayment address.(%s)\n",swap->alicepayment.p2shaddr); - //LP_importaddress(swap->alicecoin.symbol,swap->alicepayment.p2shaddr); - return(0); - } + struct iguana_info *coin; + if ( (coin= LP_coinfind(swap->I.alicestr)) != 0 ) + { + if ( LP_rawtx_spendscript(swap,coin->longestchain,&swap->alicepayment,0,data,datalen,0) == 0 ) + { + swap->bobspend.utxovout = 0; + swap->bobspend.utxotxid = swap->alicepayment.I.signedtxid = LP_broadcast_tx(swap->alicepayment.name,coin->symbol,swap->alicepayment.txbytes,swap->alicepayment.I.datalen); + bitcoin_address(swap->alicepayment.p2shaddr,coin->taddr,coin->p2shtype,swap->alicepayment.redeemscript,swap->alicepayment.I.redeemlen); + strcpy(swap->alicepayment.I.destaddr,swap->alicepayment.p2shaddr); + if ( bits256_nonz(swap->alicepayment.I.signedtxid) != 0 ) + swap->aliceunconf = 1; + basilisk_dontforget_update(swap,&swap->alicepayment); + return(LP_waitmempool(coin->symbol,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,60)); + //printf("import alicepayment address.(%s)\n",swap->alicepayment.p2shaddr); + //LP_importaddress(coin->symbol,swap->alicepayment.p2shaddr); + return(0); + } + } else printf("verify alicepayment couldnt find coin.(%s)\n",swap->I.alicestr); printf("error validating alicepayment\n"); return(-1); } int32_t LP_verify_bobpayment(struct basilisk_swap *swap,uint8_t *data,int32_t datalen) { - uint8_t userdata[512]; int32_t i,retval=-1,len = 0; bits256 revAm; - memset(revAm.bytes,0,sizeof(revAm)); - if ( LP_rawtx_spendscript(swap,swap->bobcoin.longestchain,&swap->bobpayment,0,data,datalen,0) == 0 ) - { - swap->alicespend.utxovout = 0; - swap->alicespend.utxotxid = swap->bobpayment.I.signedtxid = LP_broadcast_tx(swap->bobpayment.name,swap->bobpayment.coin->symbol,swap->bobpayment.txbytes,swap->bobpayment.I.datalen); - if ( bits256_nonz(swap->bobpayment.I.signedtxid) != 0 ) - swap->paymentunconf = 1; - for (i=0; i<32; i++) - revAm.bytes[i] = swap->I.privAm.bytes[31-i]; - len = basilisk_swapuserdata(userdata,revAm,0,swap->I.myprivs[0],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); - bitcoin_address(swap->bobpayment.p2shaddr,swap->bobcoin.taddr,swap->bobcoin.p2shtype,swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); - strcpy(swap->bobpayment.I.destaddr,swap->bobpayment.p2shaddr); - basilisk_dontforget_update(swap,&swap->bobpayment); - //LP_importaddress(swap->bobcoin.symbol,swap->bobpayment.I.destaddr); - /*for (i=0; ibobpayment.I.datalen; i++) - printf("%02x",swap->bobpayment.txbytes[i]); - printf(" <- bobpayment.%d\n",swap->bobpayment.I.datalen); - for (i=0; ibobpayment.I.redeemlen; i++) - printf("%02x",swap->bobpayment.redeemscript[i]); - printf(" <- bobpayment redeem %d %s %s\n",i,swap->bobpayment.I.destaddr,bits256_str(str,swap->bobpayment.I.signedtxid));*/ - memcpy(swap->I.userdata_alicespend,userdata,len); - swap->I.userdata_alicespendlen = len; - retval = 0; - memcpy(swap->alicespend.I.pubkey33,swap->persistent_pubkey33,33); - bitcoin_address(swap->alicespend.I.destaddr,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->persistent_pubkey33,33); - //char str[65],str2[65]; printf("bobpaid privAm.(%s) myprivs[0].(%s)\n",bits256_str(str,swap->I.privAm),bits256_str(str2,swap->I.myprivs[0])); - if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.wiftaddr,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->alicespend,&swap->bobpayment,swap->I.myprivs[0],0,userdata,len,1,swap->changermd160,swap->alicepayment.I.destaddr)) == 0 ) + uint8_t userdata[512]; int32_t i,retval=-1,len = 0; bits256 revAm; struct iguana_info *coin; + if ( (coin= LP_coinfind(swap->I.bobstr)) != 0 ) + { + memset(revAm.bytes,0,sizeof(revAm)); + if ( LP_rawtx_spendscript(swap,coin->longestchain,&swap->bobpayment,0,data,datalen,0) == 0 ) { + swap->alicespend.utxovout = 0; + swap->alicespend.utxotxid = swap->bobpayment.I.signedtxid = LP_broadcast_tx(swap->bobpayment.name,coin->symbol,swap->bobpayment.txbytes,swap->bobpayment.I.datalen); + if ( bits256_nonz(swap->bobpayment.I.signedtxid) != 0 ) + swap->paymentunconf = 1; + for (i=0; i<32; i++) + revAm.bytes[i] = swap->I.privAm.bytes[31-i]; + len = basilisk_swapuserdata(userdata,revAm,0,swap->I.myprivs[0],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); + bitcoin_address(swap->bobpayment.p2shaddr,coin->taddr,coin->p2shtype,swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); + strcpy(swap->bobpayment.I.destaddr,swap->bobpayment.p2shaddr); + basilisk_dontforget_update(swap,&swap->bobpayment); + //LP_importaddress(coin->symbol,swap->bobpayment.I.destaddr); /*for (i=0; ibobpayment.I.datalen; i++) - printf("%02x",swap->bobpayment.txbytes[i]); - printf(" <- bobpayment\n"); - for (i=0; ialicespend.I.datalen; i++) - printf("%02x",swap->alicespend.txbytes[i]); - printf(" <- alicespend\n\n");*/ - swap->I.alicespent = 1; - return(LP_waitmempool(swap->bobcoin.symbol,swap->bobpayment.I.signedtxid,10)); - } else printf("error signing aliceclaim suppress.%d vin.(%s)\n",swap->alicespend.I.suppress_pubkeys,swap->bobpayment.I.destaddr); - } + printf("%02x",swap->bobpayment.txbytes[i]); + printf(" <- bobpayment.%d\n",swap->bobpayment.I.datalen); + for (i=0; ibobpayment.I.redeemlen; i++) + printf("%02x",swap->bobpayment.redeemscript[i]); + printf(" <- bobpayment redeem %d %s %s\n",i,swap->bobpayment.I.destaddr,bits256_str(str,swap->bobpayment.I.signedtxid));*/ + memcpy(swap->I.userdata_alicespend,userdata,len); + swap->I.userdata_alicespendlen = len; + retval = 0; + memcpy(swap->alicespend.I.pubkey33,swap->persistent_pubkey33,33); + bitcoin_address(swap->alicespend.I.destaddr,coin->taddr,coin->pubtype,swap->persistent_pubkey33,33); + //char str[65],str2[65]; printf("bobpaid privAm.(%s) myprivs[0].(%s)\n",bits256_str(str,swap->I.privAm),bits256_str(str2,swap->I.myprivs[0])); + if ( (retval= basilisk_rawtx_sign(coin->symbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,swap,&swap->alicespend,&swap->bobpayment,swap->I.myprivs[0],0,userdata,len,1,swap->changermd160,swap->alicepayment.I.destaddr,coin->zcash)) == 0 ) + { + /*for (i=0; ibobpayment.I.datalen; i++) + printf("%02x",swap->bobpayment.txbytes[i]); + printf(" <- bobpayment\n"); + for (i=0; ialicespend.I.datalen; i++) + printf("%02x",swap->alicespend.txbytes[i]); + printf(" <- alicespend\n\n");*/ + swap->I.alicespent = 1; + return(LP_waitmempool(coin->symbol,swap->bobpayment.I.destaddr,swap->bobpayment.I.signedtxid,0,60)); + } else printf("error signing aliceclaim suppress.%d vin.(%s)\n",swap->alicespend.I.suppress_pubkeys,swap->bobpayment.I.destaddr); + } + } else printf("verify bobpayment cant find (%s)\n",swap->I.bobstr); printf("error validating bobpayment\n"); return(-1); } diff --git a/iguana/exchanges/LP_utxo.c b/iguana/exchanges/LP_utxo.c new file mode 100644 index 000000000..8ea1d2db5 --- /dev/null +++ b/iguana/exchanges/LP_utxo.c @@ -0,0 +1,1180 @@ + +/****************************************************************************** + * 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_utxo.c +// marketmaker +// + + +struct LP_inuse_info +{ + bits256 txid,otherpub; + uint32_t expiration; + int32_t vout,ind; +} LP_inuse[1024]; +int32_t LP_numinuse; + +struct LP_inuse_info *_LP_inuse_find(bits256 txid,int32_t vout) +{ + int32_t i; + if ( bits256_nonz(txid) != 0 ) + { + for (i=0; iind; + *lp = LP_inuse[--LP_numinuse]; + lp->ind = ind; + memset(&LP_inuse[LP_numinuse],0,sizeof(struct LP_inuse_info)); + for (ind=0; ind= sizeof(LP_inuse)/sizeof(*LP_inuse) ) + { + now = (uint32_t)time(NULL); + n = 0; + oldesti = -1; + oldest = 0; + for (i=0; i lp->expiration ) + _LP_inuse_delete(lp->txid,lp->vout), n++; + else if ( oldest == 0 || lp->expiration < oldest ) + { + oldest = lp->expiration; + oldesti = i; + } + } + if ( n == 0 ) + { + printf("_LP_inuse_add out of slots error, pick oldesti %d\n",oldesti); + lp = &LP_inuse[oldesti]; + _LP_inuse_delete(lp->txid,lp->vout); + } else printf("expired %d inuse slots\n",n); + } + if ( bits256_nonz(txid) != 0 ) + { + if ( (lp= _LP_inuse_find(txid,vout)) == 0 ) + { + lp = &LP_inuse[LP_numinuse]; + memset(lp,0,sizeof(*lp)); + lp->txid = txid; + lp->vout = vout; + lp->expiration = expiration; + lp->otherpub = otherpub; + lp->ind = LP_numinuse++; + } + else + { + if ( bits256_nonz(otherpub) != 0 ) + lp->otherpub = otherpub; + if ( expiration > lp->expiration || expiration == 0 ) + lp->expiration = expiration; + } + return(lp); + } else printf("_LP_inuse_add [%d] overflow\n",LP_numinuse); + return(0); +} + +int32_t LP_reservation_check(bits256 txid,int32_t vout,bits256 pubkey) +{ + struct LP_inuse_info *lp; int32_t retval = -1; + if ( bits256_nonz(pubkey) != 0 ) + { + portable_mutex_lock(&LP_inusemutex); + if ( (lp= _LP_inuse_find(txid,vout)) != 0 ) + { + if ( bits256_cmp(lp->otherpub,pubkey) == 0 ) + retval = 0; + } + portable_mutex_unlock(&LP_inusemutex); + } + return(retval); +} + +uint32_t LP_allocated(bits256 txid,int32_t vout) +{ + struct LP_inuse_info *lp; uint32_t now,duration = 0; + now = (uint32_t)time(NULL); + portable_mutex_lock(&LP_inusemutex); + if ( (lp= _LP_inuse_find(txid,vout)) != 0 ) + { + if ( lp->expiration != 0 && now < lp->expiration ) + duration = (lp->expiration - now); + } + portable_mutex_unlock(&LP_inusemutex); + return(duration); +} + +void LP_unavailableset(bits256 txid,int32_t vout,uint32_t expiration,bits256 otherpub) +{ + portable_mutex_lock(&LP_inusemutex); + _LP_inuse_add(expiration,otherpub,txid,vout); + portable_mutex_unlock(&LP_inusemutex); +} + +void LP_availableset(bits256 txid,int32_t vout) +{ + portable_mutex_lock(&LP_inusemutex); + _LP_inuse_delete(txid,vout); + portable_mutex_unlock(&LP_inusemutex); +} + +int32_t LP_isavailable(struct LP_utxoinfo *utxo) +{ + struct _LP_utxoinfo u; + u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; + if ( LP_allocated(utxo->payment.txid,utxo->payment.vout) == 0 && LP_allocated(u.txid,u.vout) == 0 ) + return(1); + else return(0); +} + +uint64_t LP_value_extract(cJSON *obj,int32_t addinterest) +{ + double val = 0.; uint64_t value = 0; int32_t electrumflag; + electrumflag = (jobj(obj,"tx_hash") != 0); + if ( electrumflag == 0 ) + { + if ( (val= jdouble(obj,"amount")) < SMALLVAL ) + val = jdouble(obj,"value"); + value = (val + 0.0000000049) * SATOSHIDEN; + } else value = j64bits(obj,"value"); + if ( value != 0 ) + { + if ( addinterest != 0 && jobj(obj,"interest") != 0 ) + value += (jdouble(obj,"interest") * SATOSHIDEN); + } + return(value); +} + +int32_t LP_destaddr(char *destaddr,cJSON *item) +{ + int32_t m,retval = -1; cJSON *addresses,*skey; char *addr; + if ( (skey= jobj(item,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 ) + { + item = jitem(addresses,0); + if ( (addr= jstr(item,0)) != 0 ) + { + safecopy(destaddr,addr,64); + retval = 0; + } + //printf("item.(%s) -> dest.(%s)\n",jprint(item,0),destaddr); + } + return(retval); +} + +int32_t LP_txdestaddr(char *destaddr,bits256 txid,int32_t vout,cJSON *txobj) +{ + int32_t n,retval = -1; cJSON *vouts; + if ( (vouts= jarray(&n,txobj,"vout")) != 0 && vout < n ) + retval = LP_destaddr(destaddr,jitem(vouts,vout)); + return(retval); +} + +struct LP_address *_LP_address(struct iguana_info *coin,char *coinaddr) +{ + struct LP_address *ap = 0; + if ( (ap= _LP_addressfind(coin,coinaddr)) == 0 ) + { + ap = _LP_addressadd(coin,coinaddr); + //printf("LP_address %s %s\n",coin->symbol,coinaddr); + } + return(ap); +} + +struct LP_address *LP_addressfind(struct iguana_info *coin,char *coinaddr) +{ + struct LP_address *ap = 0; + if ( coin != 0 ) + { + portable_mutex_lock(&coin->addrmutex); + ap = _LP_addressfind(coin,coinaddr); + portable_mutex_unlock(&coin->addrmutex); + } + return(ap); +} + +struct LP_address *LP_address(struct iguana_info *coin,char *coinaddr) +{ + struct LP_address *ap = 0; + if ( coin != 0 ) + { + portable_mutex_lock(&coin->addrmutex); + ap = _LP_address(coin,coinaddr); + portable_mutex_unlock(&coin->addrmutex); + } + return(ap); +} + +int32_t LP_address_minmax(uint64_t *balancep,uint64_t *minp,uint64_t *maxp,struct LP_address *ap) +{ + struct LP_address_utxo *up,*tmp; int32_t n = 0; + *minp = *maxp = *balancep = 0; + DL_FOREACH_SAFE(ap->utxos,up,tmp) + { + if ( up->spendheight <= 0 ) + { + if ( up->U.value > *maxp ) + *maxp = up->U.value; + if ( *minp == 0 || up->U.value < *minp ) + *minp = up->U.value; + *balancep += up->U.value; + n++; + } + } + if ( 0 && n > 0 ) + printf("n.%d %s min %.8f max %.8f\n",n,ap->coinaddr,dstr(*minp),dstr(*maxp)); + return(n); +} + +int32_t LP_address_utxo_ptrs(struct iguana_info *coin,int32_t iambob,struct LP_address_utxo **utxos,int32_t max,struct LP_address *ap,char *coinaddr) +{ + struct LP_address_utxo *up,*tmp; struct LP_transaction *tx; cJSON *txout; int32_t n = 0; + if ( strcmp(ap->coinaddr,coinaddr) != 0 ) + printf("UNEXPECTED coinaddr mismatch (%s) != (%s)\n",ap->coinaddr,coinaddr); + //LP_listunspent_issue(coin->symbol,coin->smartaddr,2); + //portable_mutex_lock(&LP_utxomutex); + DL_FOREACH_SAFE(ap->utxos,up,tmp) + { + //char str[65]; printf("LP_address_utxo_ptrs %s n.%d %.8f %s v%d spendheight.%d allocated.%d\n",ap->coinaddr,n,dstr(up->U.value),bits256_str(str,up->U.txid),up->U.vout,up->spendheight,LP_allocated(up->U.txid,up->U.vout)); + if ( up->spendheight <= 0 && LP_RTmetrics_avoidtxid(up->U.txid) < 0 ) + { + if ( coin->electrum == 0 ) + { + if ( (txout= LP_gettxout(coin->symbol,coinaddr,up->U.txid,up->U.vout)) != 0 ) + { + if ( LP_value_extract(txout,0) == 0 ) + { + //printf("LP_address_utxo_ptrs skip zero value %s/v%d\n",bits256_str(str,up->U.txid),up->U.vout); + free_json(txout); + up->spendheight = 1; + if ( (tx= LP_transactionfind(coin,up->U.txid)) != 0 && up->U.vout < tx->numvouts ) + tx->outpoints[up->U.vout].spendheight = 1; + continue; + } + free_json(txout); + } + else + { + //printf("LP_address_utxo_ptrs skips %s %s payment %s/v%d is spent\n",coin->symbol,coinaddr,bits256_str(str,up->U.txid),up->U.vout); + up->spendheight = 1; + if ( (tx= LP_transactionfind(coin,up->U.txid)) != 0 && up->U.vout < tx->numvouts ) + tx->outpoints[up->U.vout].spendheight = 1; + continue; + } + } + else + { + if ( up->SPV < 0 || up->U.height == 0 ) + { +//printf("LP_address_utxo_ptrs skips %s/v%u due to SPV.%d ht.%d\n",bits256_str(str,up->U.txid),up->U.vout,up->SPV,up->U.height); + if ( (tx= LP_transactionfind(coin,up->U.txid)) != 0 && up->U.vout < tx->numvouts ) + tx->outpoints[up->U.vout].spendheight = 1; + continue; + } + } + if ( LP_allocated(up->U.txid,up->U.vout) == 0 ) + { + utxos[n++] = up; + if ( n >= max ) + break; + } //else printf("LP_allocated skip\n"); + } + else + { + if ( (tx= LP_transactionfind(coin,up->U.txid)) != 0 && up->U.vout < tx->numvouts ) + tx->outpoints[up->U.vout].spendheight = 1; + } + } + //portable_mutex_unlock(&LP_utxomutex); + //printf("return n.%d for %s %s\n",n,coin->symbol,coinaddr); + return(n); +} + +struct LP_address_utxo *LP_address_utxofind(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout) +{ + struct LP_address *ap; struct LP_address_utxo *up,*tmp; + //printf("LP_address_utxofind %s add addr.%s\n",coin->symbol,coinaddr); + if ( (ap= _LP_address(coin,coinaddr)) != 0 ) + { + DL_FOREACH_SAFE(ap->utxos,up,tmp) + { + if ( vout == up->U.vout && bits256_cmp(up->U.txid,txid) == 0 ) + return(up); + } + } + return(0); +} + +void LP_mark_spent(char *symbol,bits256 txid,int32_t vout) +{ + struct iguana_info *coin; struct LP_transaction *tx; struct LP_address_utxo *up; + if ( (coin= LP_coinfind(symbol)) != 0 ) + { + if ( (tx= LP_transactionfind(coin,txid)) != 0 ) + { + if ( vout < tx->numvouts ) + { + tx->outpoints[vout].spendheight = 1; + if ( (up= LP_address_utxofind(coin,tx->outpoints[vout].coinaddr,txid,vout)) != 0 ) + up->spendheight = 1; + } + } + } +} + +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) +{ + struct LP_address *ap; cJSON *txobj; struct LP_transaction *tx; struct LP_address_utxo *up,*tmp; int32_t flag,retval = 0; //char str[65]; + if ( coin == 0 ) + return(0); + if ( spendheight > 0 ) // dont autocreate entries for spends we dont care about + ap = LP_addressfind(coin,coinaddr); + else ap = LP_address(coin,coinaddr); + //printf("%s add addr.%s ht.%d ap.%p\n",coin->symbol,coinaddr,height,ap); + if ( ap != 0 ) + { + flag = 0; + DL_FOREACH_SAFE(ap->utxos,up,tmp) + { + if ( vout == up->U.vout && bits256_cmp(up->U.txid,txid) == 0 ) + { + flag = 1; + if ( height > 0 && up->U.height != height ) + up->U.height = height, flag |= 2; + if ( spendheight > 0 && up->spendheight != spendheight ) + up->spendheight = spendheight, flag |= 4; + if ( value != 0 && up->U.value == 0 && up->U.value != value ) + up->U.value = value, flag |= 8; + //up->timestamp = timestamp; + //char str[65]; printf("found >>>>>>>>>> %s %s %s/v%d ht.%d %.8f\n",coin->symbol,coinaddr,bits256_str(str,txid),vout,height,dstr(value)); + break; + } + } + if ( flag == 0 && value != 0 ) + { + if ( coin->electrum == 0 ) + { + if ( (txobj= LP_gettxout(coin->symbol,coinaddr,txid,vout)) == 0 ) + { + //char str[65]; printf("prevent utxoadd since gettxout %s %s %s/v%d missing\n",coin->symbol,coinaddr,bits256_str(str,txid),vout); + return(0); + } else free_json(txobj); + } + up = calloc(1,sizeof(*up)); + up->U.txid = txid; + up->U.vout = vout; + up->U.height = height; + up->U.value = value; + up->spendheight = spendheight; + //up->timestamp = timestamp; + retval = 1; + if ( (tx= LP_transactionfind(coin,txid)) != 0 && tx->SPV > 0 ) + { + up->SPV = tx->SPV; + } + char str[65]; + if ( 0 && strcmp(coin->smartaddr,coinaddr) == 0 && strcmp("KMD",coin->symbol) == 0 ) + printf("%s ADD UTXO >> %s %s %s/v%d ht.%d %.8f\n",debug,coin->symbol,coinaddr,bits256_str(str,txid),vout,height,dstr(value)); + portable_mutex_lock(&coin->addrmutex); + DL_APPEND(ap->utxos,up); + portable_mutex_unlock(&coin->addrmutex); + } + } // else printf("cant get ap %s %s\n",coin->symbol,coinaddr); + //printf("done %s add addr.%s ht.%d\n",coin->symbol,coinaddr,height); + return(retval); +} + +struct LP_address *LP_address_utxo_reset(struct iguana_info *coin) +{ + struct LP_address *ap; struct LP_address_utxo *up,*tmp; int32_t i,n,vout,height; cJSON *array,*item; int64_t value; bits256 txid; uint32_t now; + LP_address(coin,coin->smartaddr); + LP_listunspent_issue(coin->symbol,coin->smartaddr,2); + if ( (ap= LP_addressfind(coin,coin->smartaddr)) == 0 ) + { + printf("LP_address_utxo_reset: cant find address data\n"); + return(0); + } + if ( (array= LP_listunspent(coin->symbol,coin->smartaddr)) != 0 ) + { + DL_FOREACH_SAFE(ap->utxos,up,tmp) + { + portable_mutex_lock(&coin->addrmutex); + DL_DELETE(ap->utxos,up); + portable_mutex_unlock(&coin->addrmutex); + portable_mutex_lock(&LP_gcmutex); + up->spendheight = (int32_t)time(NULL); + DL_APPEND(LP_garbage_collector2,up); + portable_mutex_unlock(&LP_gcmutex); + } + now = (uint32_t)time(NULL); + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + char str[65]; + for (i=0; ielectrum != 0 ) + { + txid = jbits256(item,"tx_hash"); + vout = juint(item,"tx_pos"); + value = j64bits(item,"value"); + height = jint(item,"height"); + } + else + { + txid = jbits256(item,"txid"); + vout = juint(item,"vout"); + value = LP_value_extract(item,0); + height = LP_txheight(coin,txid); + } + LP_address_utxoadd(now,"withdraw",coin,coin->smartaddr,txid,vout,value,height,-1); + if ( (up= LP_address_utxofind(coin,coin->smartaddr,txid,vout)) == 0 ) + printf("couldnt find just added %s/%d ht.%d %.8f\n",bits256_str(str,txid),vout,height,dstr(value)); + } + printf("added %d from listunspents\n",n); + } + free_json(array); + } + return(ap); +} + +cJSON *LP_address_item(struct iguana_info *coin,struct LP_address_utxo *up,int32_t electrumret) +{ + cJSON *item = cJSON_CreateObject(); + if ( electrumret == 0 ) + { + jaddbits256(item,"txid",up->U.txid); + jaddnum(item,"vout",up->U.vout); + if ( up->U.height > 0 ) + jaddnum(item,"confirmations",LP_getheight(coin) - up->U.height + 1); + jaddnum(item,"amount",dstr(up->U.value)); + jaddstr(item,"scriptPubKey",""); + } + else + { + jaddbits256(item,"tx_hash",up->U.txid); + jaddnum(item,"tx_pos",up->U.vout); + jaddnum(item,"height",up->U.height); + jadd64bits(item,"value",up->U.value); + if ( up->U.value == 0 ) + printf("ERROR LP_address_item illegal.(%s)\n",jprint(item,0)); + } + return(item); +} + +uint64_t _LP_unspents_metric(uint64_t total,int32_t n) { return((total<<16) | (n & 0xffff)); } + +cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrumret) +{ + cJSON *array,*item; int32_t n; uint64_t total; struct LP_address *ap=0,*atmp; struct LP_address_utxo *up,*tmp; cJSON *txobj; + array = cJSON_CreateArray(); + if ( coinaddr != 0 && coinaddr[0] != 0 ) + { + //portable_mutex_lock(&coin->addrmutex); + if ( (ap= _LP_addressfind(coin,coinaddr)) != 0 ) + { + total = n = 0; + DL_FOREACH_SAFE(ap->utxos,up,tmp) + { + if ( up->spendheight <= 0 && up->U.height > 0 ) + { + if ( coin->electrum == 0 ) + { + if ( (txobj= LP_gettxout(coin->symbol,coinaddr,up->U.txid,up->U.vout)) == 0 ) + up->spendheight = 1; + else free_json(txobj); + } + if ( up->spendheight <= 0 && up->U.value != 0 ) + { + char str[65]; + if ( LP_allocated(up->U.txid,up->U.vout) != 0 ) + printf("%s %s/v%d allocated\n",coin->symbol,bits256_str(str,up->U.txid),up->U.vout); + else if ( coin->electrum == 0 || up->SPV > 0 ) + { + jaddi(array,LP_address_item(coin,up,electrumret)); + n++; + total += up->U.value; + } + } + //printf("new array %s\n",jprint(array,0)); + } + } + ap->total = total; + ap->n = n; + } + //portable_mutex_unlock(&coin->addrmutex); + } + else + { + HASH_ITER(hh,coin->addresses,ap,atmp) + { + if ( ap->total > 0 && ap->n > 0 ) + { + item = cJSON_CreateObject(); + jadd64bits(item,ap->coinaddr,_LP_unspents_metric(ap->total,ap->n)); + jaddi(array,item); + } + } + } + //printf("%s %s utxos.(%s) ap.%p\n",coin->symbol,coinaddr,jprint(array,0),ap); + return(array); +} + +cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electrumret) +{ + cJSON *array,*retjson,*item; int32_t i,n; uint64_t balance = 0; + if ( coin->electrum == 0 ) + { + if ( (array= LP_listunspent(coin->symbol,coinaddr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; ismartaddr,coinaddr) == 0 ) + balance = LP_unspents_load(coin->symbol,coinaddr); + else + { + if ( (array= LP_address_utxos(coin,coinaddr,1)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; isymbol); + jaddstr(retjson,"address",coinaddr); + jaddnum(retjson,"balance",dstr(balance)); + return(retjson); +} + +int32_t LP_unspents_array(struct iguana_info *coin,char *coinaddr,cJSON *array) +{ + int32_t i,n,v,errs,height,count=0; uint64_t value,val; cJSON *item,*txobj; bits256 txid; + if ( (n= cJSON_GetArraySize(array)) <= 0 ) + return(0); + //printf("%s %s LP_unspents.(%s)\n",coin->symbol,coinaddr,jprint(array,0)); + for (i=0; ielectrum == 0 && (txobj= LP_gettxout(coin->symbol,coinaddr,txid,v)) != 0 ) + { + value = LP_value_extract(txobj,0); + if ( value != 0 && value != val ) + { + char str[65]; printf("REJECT %s %s/v%d value.%llu vs %llu (%s)\n",coin->symbol,bits256_str(str,txid),v,(long long)value,(long long)val,jprint(txobj,0)); + errs++; + } + //ht = LP_txheight(coin,txid); + //if ( coin->height != 0 ) + // ht = LP_getheight(coin) - jint(txobj,"confirmations") + 1; + //else ht = 0; + /*if ( ht != 0 && ht < height-2 ) + { + printf("REJECT %s %s/v%d ht.%d vs %d confs.%d (%s)\n",symbol,bits256_str(str,txid),v,ht,height,jint(txobj,"confirmations"),jprint(item,0)); + errs++; + }*/ + free_json(txobj); + } + if ( errs == 0 ) + { + //printf("from LP_unspents_array\n"); + LP_address_utxoadd((uint32_t)time(NULL),"LP_unspents_array",coin,coinaddr,txid,v,val,height,-1); + count++; + } + } + return(count); +} + +void LP_utxosetkey(uint8_t *key,bits256 txid,int32_t vout) +{ + memcpy(key,txid.bytes,sizeof(txid)); + memcpy(&key[sizeof(txid)],&vout,sizeof(vout)); +} + +struct LP_utxoinfo *_LP_utxofind(int32_t iambob,bits256 txid,int32_t vout) +{ + struct LP_utxoinfo *utxo=0; uint8_t key[sizeof(txid) + sizeof(vout)]; + LP_utxosetkey(key,txid,vout); + HASH_FIND(hh,G.LP_utxoinfos[iambob!=0],key,sizeof(key),utxo); + return(utxo); +} + +void _LP_utxo_delete(int32_t iambob,struct LP_utxoinfo *utxo) +{ + HASH_DELETE(hh,G.LP_utxoinfos[iambob],utxo); +} + +void _LP_utxo2_delete(int32_t iambob,struct LP_utxoinfo *utxo) +{ + HASH_DELETE(hh,G.LP_utxoinfos2[iambob],utxo); +} + +struct LP_utxoinfo *_LP_utxo2find(int32_t iambob,bits256 txid2,int32_t vout2) +{ + struct LP_utxoinfo *utxo=0; uint8_t key2[sizeof(txid2) + sizeof(vout2)]; + LP_utxosetkey(key2,txid2,vout2); + HASH_FIND(hh2,G.LP_utxoinfos2[iambob],key2,sizeof(key2),utxo); + return(utxo); +} + +struct LP_utxoinfo *LP_utxofind(int32_t iambob,bits256 txid,int32_t vout) +{ + struct LP_utxoinfo *utxo=0; + /*if ( iambob != 0 ) + { + printf("LP_utxofind deprecated iambob\n"); + return(0); + }*/ + portable_mutex_lock(&LP_utxomutex); + utxo = _LP_utxofind(iambob,txid,vout); + portable_mutex_unlock(&LP_utxomutex); + return(utxo); +} + +struct LP_utxoinfo *LP_utxo2find(int32_t iambob,bits256 txid2,int32_t vout2) +{ + struct LP_utxoinfo *utxo=0; + /*if ( iambob != 0 ) + { + printf("LP_utxo2find deprecated iambob\n"); + return(0); + }*/ + portable_mutex_lock(&LP_utxomutex); + utxo = _LP_utxo2find(iambob,txid2,vout2); + portable_mutex_unlock(&LP_utxomutex); + return(utxo); +} + +struct LP_transaction *LP_transactionfind(struct iguana_info *coin,bits256 txid) +{ + struct LP_transaction *tx; + portable_mutex_lock(&coin->txmutex); + HASH_FIND(hh,coin->transactions,txid.bytes,sizeof(txid),tx); + portable_mutex_unlock(&coin->txmutex); + return(tx); +} + +struct LP_transaction *LP_transactionadd(struct iguana_info *coin,bits256 txid,int32_t height,int32_t numvouts,int32_t numvins) +{ + static long totalsize; + struct LP_transaction *tx; int32_t i; //char str[65]; + if ( (tx= LP_transactionfind(coin,txid)) == 0 ) + { + //if ( bits256_nonz(txid) == 0 && tx->height == 0 ) + // getchar(); + tx = calloc(1,sizeof(*tx) + (sizeof(*tx->outpoints) * numvouts)); + totalsize += sizeof(*tx) + (sizeof(*tx->outpoints) * numvouts); + //char str[65]; printf("%s ht.%d NEW TXID.(%s) vouts.[%d] size.%ld total %ld\n",coin->symbol,height,bits256_str(str,txid),numvouts,sizeof(*tx) + (sizeof(*tx->outpoints) * numvouts),totalsize); + for (i=0; ioutpoints[i].spendvini = -1; + tx->height = height; + tx->numvouts = numvouts; + tx->numvins = numvins; + //tx->timestamp = timestamp; + tx->txid = txid; + portable_mutex_lock(&coin->txmutex); + HASH_ADD_KEYPTR(hh,coin->transactions,tx->txid.bytes,sizeof(tx->txid),tx); + portable_mutex_unlock(&coin->txmutex); + } //else printf("warning adding already existing txid %s\n",bits256_str(str,tx->txid)); + return(tx); +} + +cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJSON *txobj) +{ + struct LP_transaction *tx; int32_t i,height,numvouts,numvins,spentvout; cJSON *vins,*vouts,*vout,*vin; bits256 spenttxid; char str[65]; + if ( coin->inactive != 0 ) + return(0); + if ( txobj != 0 || (txobj= LP_gettx(coin->symbol,txid)) != 0 ) + { + if ( coin->electrum == 0 ) + height = LP_txheight(coin,txid); + else height = -1; + vins = jarray(&numvins,txobj,"vin"); + vouts = jarray(&numvouts,txobj,"vout"); + // maybe filter so only addresses we care about are using RAM + if ( iter == 0 && vouts != 0 && (tx= LP_transactionadd(coin,txid,height,numvouts,numvins)) != 0 ) + { + //printf("create txid %s numvouts.%d numvins.%d\n",bits256_str(str,txid),numvouts,numvins); + for (i=0; ioutpoints[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_transactioninit iter0",coin,tx->outpoints[i].coinaddr,txid,i,tx->outpoints[i].value,height,-1); + } + //printf("numvouts.%d\n",numvouts); + } + if ( iter == 1 && vins != 0 ) + { + for (i=0; inumvouts ) + { + 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); + } + } + return(txobj); + } //else printf("LP_transactioninit error for %s %s\n",coin->symbol,bits256_str(str,txid)); + return(0); +} + +int32_t LP_txheight(struct iguana_info *coin,bits256 txid) +{ + bits256 blockhash; struct LP_transaction *tx; cJSON *blockobj,*txobj; int32_t height = 0; + if ( coin == 0 ) + return(-1); + if ( coin->electrum == 0 ) + { + if ( (txobj= LP_gettx(coin->symbol,txid)) != 0 ) + { + //*timestampp = juint(txobj,"locktime"); + //*blocktimep = juint(txobj,"blocktime"); + blockhash = jbits256(txobj,"blockhash"); + if ( bits256_nonz(blockhash) != 0 && (blockobj= LP_getblock(coin->symbol,blockhash)) != 0 ) + { + height = jint(blockobj,"height"); + //char str[65]; + //if ( strcmp(coin->symbol,"CHIPS") != 0 && strcmp(coin->symbol,"BTC") != 0 ) + // printf("%s %s LP_txheight.%d\n",coin->symbol,bits256_str(str,txid),height); + free_json(blockobj); + } // else printf("%s LP_txheight error (%s)\n",coin->symbol,jprint(txobj,0)); likely just unconfirmed + free_json(txobj); + } + } + else + { + if ( (tx= LP_transactionfind(coin,txid)) != 0 ) + height = tx->height; + } + return(height); +} + +int32_t LP_numconfirms(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t mempool) +{ + struct iguana_info *coin; int32_t ht,numconfirms = 100; + cJSON *txobj; + if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) + return(-1); + if ( coin->electrum == 0 ) + { + numconfirms = -1; + if ( (txobj= LP_gettxout(symbol,coinaddr,txid,vout)) != 0 ) + { + numconfirms = jint(txobj,"confirmations"); + free_json(txobj); + } + else if ( mempool != 0 && LP_mempoolscan(symbol,txid) >= 0 ) + numconfirms = 0; + else if ( (txobj= LP_gettx(symbol,txid)) != 0 ) + { + numconfirms = jint(txobj,"confirmations"); + free_json(txobj); + } + } + else + { + LP_listunspent_issue(symbol,coinaddr,1); + if ( (ht= LP_txheight(coin,txid)) > 0 && ht <= coin->height ) + numconfirms = (LP_getheight(coin) - ht + 1); + else if ( mempool != 0 ) + { + if ( LP_waitmempool(symbol,coinaddr,txid,vout,30) >= 0 ) + numconfirms = 0; + } + } + return(numconfirms); +} + +uint64_t LP_txinterestvalue(uint64_t *interestp,char *destaddr,struct iguana_info *coin,bits256 txid,int32_t vout) +{ + uint64_t interest,value = 0; cJSON *txobj; + *interestp = 0; + destaddr[0] = 0; + if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid,vout)) != 0 ) + { + if ( (value= LP_value_extract(txobj,0)) == 0 ) + { + char str[65]; printf("%s LP_txvalue.%s strange utxo.(%s) vout.%d\n",coin->symbol,bits256_str(str,txid),jprint(txobj,0),vout); + } + else if ( strcmp(coin->symbol,"KMD") == 0 ) + { + if ( coin->electrum == 0 ) + { + if ((interest= jdouble(txobj,"interest")) != 0. ) + { + //printf("add interest of %.8f to %.8f\n",interest,dstr(value)); + *interestp = SATOSHIDEN * interest; + } + } else *interestp = LP_komodo_interest(txid,value); + } + LP_destaddr(destaddr,txobj); + //char str[65]; printf("dest.(%s) %.8f <- %s.(%s) txobj.(%s)\n",destaddr,dstr(value),coin->symbol,bits256_str(str,txid),jprint(txobj,0)); + free_json(txobj); + } //else { char str[65]; printf("null gettxout return %s/v%d\n",bits256_str(str,txid),vout); } + return(value); +} + +int64_t basilisk_txvalue(char *symbol,bits256 txid,int32_t vout) +{ + char destaddr[64]; uint64_t value,interest = 0; struct iguana_info *coin; + if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) + return(0); + //char str[65]; printf("%s txvalue.(%s)\n",symbol,bits256_str(str,txid)); + value = LP_txinterestvalue(&interest,destaddr,coin,txid,vout); + return(value + interest); +} + +uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout) +{ + struct LP_transaction *tx; cJSON *txobj=0; struct iguana_info *coin; + if ( bits256_nonz(txid) == 0 ) + return(0); + if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) + return(0); + if ( coinaddr != 0 ) + coinaddr[0] = 0; + if ( (tx= LP_transactionfind(coin,txid)) == 0 ) + { + txobj = LP_transactioninit(coin,txid,0,0); + txobj = LP_transactioninit(coin,txid,1,txobj); + if ( txobj != 0 ) + free_json(txobj); + tx = LP_transactionfind(coin,txid); + } + if ( tx != 0 ) + { + if ( vout < tx->numvouts ) + { + /*if ( bits256_nonz(tx->outpoints[vout].spendtxid) != 0 ) + { + //printf("LP_txvalue %s/v%d is spent at %s\n",bits256_str(str,txid),vout,bits256_str(str2,tx->outpoints[vout].spendtxid)); + return(0); + } + else + { + if ( coinaddr != 0 ) + { + //if ( tx->outpoints[vout].coinaddr[0] == 0 ) + // tx->outpoints[vout].value = LP_txinterestvalue(&tx->outpoints[vout].interest,tx->outpoints[vout].coinaddr,coin,txid,vout); + strcpy(coinaddr,tx->outpoints[vout].coinaddr); + //printf("(%s) return value %.8f + interest %.8f\n",coinaddr,dstr(tx->outpoints[vout].value),dstr(tx->outpoints[vout].interest)); + } + return(tx->outpoints[vout].value + 0*tx->outpoints[vout].interest); + }*/ + return(tx->outpoints[vout].value); + } else printf("LP_txvalue vout.%d >= tx->numvouts.%d\n",vout,tx->numvouts); + } + else if ( coin->electrum == 0 ) + { + uint64_t value; + if ( (txobj= LP_gettxout(coin->symbol,coinaddr,txid,vout)) != 0 ) + { + value = LP_value_extract(txobj,0);//SATOSHIDEN * (jdouble(txobj,"value") + jdouble(txobj,"interest")); + if ( coinaddr != 0 ) + LP_destaddr(coinaddr,txobj); + //printf("pruned node? LP_txvalue couldnt find %s tx %s, but gettxout %.8f\n",coin->symbol,bits256_str(str,txid),dstr(value)); + if ( value != 0 ) + { + free_json(txobj); + return(value); + } + } + //printf("pruned node? LP_txvalue couldnt find %s tx %s/v%d (%s)\n",coin->symbol,bits256_str(str,txid),vout,txobj!=0?jprint(txobj,0):""); + if ( txobj != 0 ) + free_json(txobj); + } + return(0); +} + +int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2) +{ + uint64_t val,val2=0,txfee,threshold=0; cJSON *txobj; int32_t bypass = 0; char destaddr[64],destaddr2[64]; struct iguana_info *coin = LP_coinfind(symbol); + if ( bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 ) + { + printf("null txid not eligible\n"); + return(-1); + } + destaddr[0] = destaddr2[0] = 0; + if ( coin != 0 && IAMLP != 0 && coin->inactive != 0 ) + bypass = 1; + if ( bypass != 0 ) + val = satoshis; + else val = LP_txvalue(destaddr,symbol,txid,vout); + txfee = LP_txfeecalc(LP_coinfind(symbol),0,0); + if ( val >= satoshis && val > (1+LP_MINSIZE_TXFEEMULT)*txfee ) + { + threshold = (iambob != 0) ? LP_DEPOSITSATOSHIS(satoshis) : (LP_DEXFEE(satoshis) + txfee); + if ( bypass != 0 ) + val2 = threshold; + else val2 = LP_txvalue(destaddr2,symbol,txid2,vout2); + if ( val2 >= threshold ) + { + if ( bypass == 0 && strcmp(destaddr,destaddr2) != 0 ) + printf("mismatched %s destaddr (%s) vs (%s)\n",symbol,destaddr,destaddr2); + else if ( bypass == 0 && ((iambob == 0 && val2 > val) || (iambob != 0 && val2 <= satoshis)) ) + printf("iambob.%d ineligible due to offsides: val %.8f and val2 %.8f vs %.8f diff %lld\n",iambob,dstr(val),dstr(val2),dstr(satoshis),(long long)(val2 - val)); + else + { + *valp = val; + *val2p = val2; + if ( destaddr[0] == 0 ) + strcpy(destaddr,destaddr2); + if ( coin != 0 ) + { + /*if ( coin->electrum != 0 ) + { + if ( (tx= LP_transactionfind(coin,txid)) != 0 && vout < tx->numvouts && tx->outpoints[vout].spendheight > 0 ) + { + //printf("txid spent\n"); + return(0); + } + if ( (tx= LP_transactionfind(coin,txid2)) != 0 && vout2 < tx->numvouts && tx->outpoints[vout2].spendheight > 0 ) + { + //printf("txid2 spent\n"); + return(0); + } + if ( (up= LP_address_utxofind(coin,destaddr,txid,vout)) != 0 && up->spendheight > 0 ) + { + //printf("txid %s spentB\n",destaddr); + return(0); + } + if ( (up= LP_address_utxofind(coin,destaddr,txid2,vout2)) != 0 && up->spendheight > 0 ) + { + //printf("txid2 %s spentB\n",destaddr); + return(0); + } + } + else*/ + { + if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid,vout)) == 0 ) + return(0); + else free_json(txobj); + if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid2,vout2)) == 0 ) + return(0); + else free_json(txobj); + } + } + return(1); + } + } else printf("no val2 %.8f < threshold %.8f\n",dstr(val),dstr(threshold)); + } + /*char str2[65]; + if ( val != 0 && val2 != 0 ) + printf("spent.%d %s txid or value %.8f < %.8f or val2 %.8f < %.8f, %s/v%d %s/v%d or < 10x txfee %.8f\n",iambob,symbol,dstr(val),dstr(satoshis),dstr(val2),dstr(threshold),bits256_str(str,txid),vout,bits256_str(str2,txid2),vout2,dstr(txfee)); + if ( val == 0 ) + LP_address_utxoadd(coin,destaddr,txid,vout,satoshis,-1,1); + if ( val2 == 0 ) + LP_address_utxoadd(coin,destaddr,txid2,vout2,threshold,-1,1); + for (iter=0; iter<2; iter++) + { + if ( (utxo= LP_utxofind(iter,txid,vout)) != 0 ) + { + //printf("iambob.%d case 00\n",iter); + if ( utxo->T.spentflag == 0 ) + utxo->T.spentflag = (uint32_t)time(NULL); + } + if ( (utxo= LP_utxo2find(iter,txid,vout)) != 0 ) + { + //printf("iambob.%d case 01\n",iter); + if ( utxo->T.spentflag == 0 ) + utxo->T.spentflag = (uint32_t)time(NULL); + } + if ( (utxo= LP_utxofind(iter,txid2,vout2)) != 0 ) + { + //printf("iambob.%d case 10\n",iter); + if ( utxo->T.spentflag == 0 ) + utxo->T.spentflag = (uint32_t)time(NULL); + } + if ( (utxo= LP_utxo2find(iter,txid2,vout2)) != 0 ) + { + //printf("iambob.%d case 11\n",iter); + if ( utxo->T.spentflag == 0 ) + utxo->T.spentflag = (uint32_t)time(NULL); + } + }*/ + *valp = val; + *val2p = val2; + return(0); +} + +int32_t LP_inventory_prevent(int32_t iambob,char *symbol,bits256 txid,int32_t vout) +{ + struct LP_address_utxo *up; struct LP_utxoinfo *utxo; struct LP_transaction *tx; struct iguana_info *coin; + if ( (coin= LP_coinfind(symbol)) == 0 ) + return(1); + if ( LP_allocated(txid,vout) != 0 ) + return(1); + if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 || (utxo= LP_utxo2find(iambob,txid,vout)) != 0 ) + { + if ( coin != 0 && (tx= LP_transactionfind(coin,txid)) != 0 ) + { + if ( tx->outpoints[vout].spendheight > 0 ) + utxo->T.spentflag = tx->outpoints[vout].spendheight; + else utxo->T.spentflag = 0; + } + if ( utxo->T.spentflag != 0 ) + { + //char str[65]; printf("prevent adding iambob.%d %s/v%d to inventory\n",iambob,bits256_str(str,txid),vout); + return(1); + } + } + if ( (up= LP_address_utxofind(coin,coin->smartaddr,txid,vout)) != 0 && up->spendheight > 0 ) + return(1); + return(0); +} + +cJSON *LP_dustcombine_item(struct LP_address_utxo *up) +{ + cJSON *item = cJSON_CreateObject(); + jaddbits256(item,"txid",up->U.txid); + jaddnum(item,"vout",up->U.vout); + return(item); +} + +uint64_t LP_dustcombine(struct LP_address_utxo *ups[2],int32_t dustcombine,struct iguana_info *coin) +{ + struct LP_address *ap=0; struct LP_address_utxo *up,*tmp,*min0,*min1; cJSON *txobj; + if ( coin == 0 || coin->electrum != 0 || dustcombine <= 0 || dustcombine > 2 ) + return(0); + min1 = min0 = 0; + ups[0] = ups[1] = 0; + if ( (ap= _LP_addressfind(coin,coin->smartaddr)) != 0 ) + { + DL_FOREACH_SAFE(ap->utxos,up,tmp) + { + if ( up->spendheight <= 0 && up->U.height > 0 && up->U.value != 0 ) + { + if ( (txobj= LP_gettxout(coin->symbol,coin->smartaddr,up->U.txid,up->U.vout)) == 0 ) + up->spendheight = 1; + else + { + free_json(txobj); + if ( LP_inventory_prevent(1,coin->symbol,up->U.txid,up->U.vout) == 0 ) + { + if ( min1 == 0 || up->U.value < min1->U.value ) + { + if ( min0 == 0 || up->U.value < min0->U.value ) + { + min1 = min0; + min0 = up; + } else min1 = up; + } + } + } + } + } + } + if ( min0 != 0 ) + { + ups[0] = min0; + if ( dustcombine == 2 && min1 != 0 ) + { + ups[1] = min1; + return(min0->U.value + min1->U.value); + } else return(min0->U.value); + } + return(0); +} + +int32_t LP_undospends(struct iguana_info *coin,int32_t lastheight) +{ + int32_t i,ht,num = 0; struct LP_transaction *tx,*tmp; + HASH_ITER(hh,coin->transactions,tx,tmp) + { + for (i=0; inumvouts; i++) + { + if ( bits256_nonz(tx->outpoints[i].spendtxid) == 0 ) + continue; + if ( (ht= tx->outpoints[i].spendheight) == 0 ) + { + tx->outpoints[i].spendheight = LP_txheight(coin,tx->outpoints[i].spendtxid); + } + if ( (ht= tx->outpoints[i].spendheight) != 0 && ht > lastheight ) + { + char str[65]; printf("clear spend %s/v%d at ht.%d > lastheight.%d\n",bits256_str(str,tx->txid),i,ht,lastheight); + tx->outpoints[i].spendheight = 0; + tx->outpoints[i].spendvini = -1; + memset(tx->outpoints[i].spendtxid.bytes,0,sizeof(bits256)); + } + } + } + return(num); +} diff --git a/iguana/exchanges/LP_utxos.c b/iguana/exchanges/LP_utxos.c index f13b1e436..90e0aafc8 100644 --- a/iguana/exchanges/LP_utxos.c +++ b/iguana/exchanges/LP_utxos.c @@ -18,60 +18,35 @@ // marketmaker // -int32_t LP_ismine(struct LP_utxoinfo *utxo) -{ - if ( utxo != 0 && bits256_cmp(utxo->pubkey,LP_mypub25519) == 0 ) - return(1); - else return(0); -} -int32_t LP_isavailable(struct LP_utxoinfo *utxo) +int32_t LP_ismine(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 ) + if ( utxo != 0 && bits256_cmp(utxo->pubkey,G.LP_mypub25519) == 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); } -void LP_utxosetkey(uint8_t *key,bits256 txid,int32_t vout) -{ - memcpy(key,txid.bytes,sizeof(txid)); - memcpy(&key[sizeof(txid)],&vout,sizeof(vout)); -} - -struct LP_utxoinfo *_LP_utxofind(int32_t iambob,bits256 txid,int32_t vout) -{ - struct LP_utxoinfo *utxo=0; uint8_t key[sizeof(txid) + sizeof(vout)]; - LP_utxosetkey(key,txid,vout); - HASH_FIND(hh,LP_utxoinfos[iambob],key,sizeof(key),utxo); - return(utxo); -} - -struct LP_utxoinfo *_LP_utxo2find(int32_t iambob,bits256 txid2,int32_t vout2) -{ - struct LP_utxoinfo *utxo=0; uint8_t key2[sizeof(txid2) + sizeof(vout2)]; - LP_utxosetkey(key2,txid2,vout2); - HASH_FIND(hh2,LP_utxoinfos2[iambob],key2,sizeof(key2),utxo); - return(utxo); -} - -struct LP_utxoinfo *LP_utxofind(int32_t iambob,bits256 txid,int32_t vout) -{ - struct LP_utxoinfo *utxo=0; - portable_mutex_lock(&LP_utxomutex); - utxo = _LP_utxofind(iambob,txid,vout); - portable_mutex_unlock(&LP_utxomutex); - return(utxo); -} - 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; @@ -84,15 +59,6 @@ struct LP_utxoinfo *LP_utxopairfind(int32_t iambob,bits256 txid,int32_t vout,bit return(0); } -struct LP_utxoinfo *LP_utxo2find(int32_t iambob,bits256 txid2,int32_t vout2) -{ - struct LP_utxoinfo *utxo=0; - portable_mutex_lock(&LP_utxomutex); - utxo = _LP_utxo2find(iambob,txid2,vout2); - portable_mutex_unlock(&LP_utxomutex); - return(utxo); -} - struct LP_utxoinfo *LP_utxofinds(int32_t iambob,bits256 txid,int32_t vout,bits256 txid2,int32_t vout2) { struct LP_utxoinfo *utxo; @@ -111,6 +77,41 @@ int32_t LP_utxoaddptrs(struct LP_utxoinfo *ptrs[],int32_t n,struct LP_utxoinfo * return(n); } +/*uint32_t LP_allocated(bits256 txid,int32_t vout) +{ + struct LP_utxoinfo *utxo; + if ( (utxo= _LP_utxofind(0,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + { + //char str[65]; printf("%s/v%d not available\n",bits256_str(str,txid),vout); + return(utxo); + } + if ( (utxo= _LP_utxo2find(0,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + { + //char str[65]; printf("%s/v%d not available2\n",bits256_str(str,txid),vout); + return(utxo); + } + if ( (utxo= _LP_utxofind(1,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + { + //char str[65]; printf("%s/v%d not available\n",bits256_str(str,txid),vout); + return(utxo); + } + if ( (utxo= _LP_utxo2find(1,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + { + //char str[65]; printf("%s/v%d not available2\n",bits256_str(str,txid),vout); + return(utxo); + } + 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_utxocollisions(struct LP_utxoinfo *ptrs[],struct LP_utxoinfo *refutxo) { int32_t iambob,n = 0; struct LP_utxoinfo *utxo; struct _LP_utxoinfo u; @@ -193,47 +194,12 @@ void LP_availableset(struct LP_utxoinfo *utxo) } } } - -int32_t LP_utxopurge(int32_t allutxos) -{ - char str[65]; struct LP_utxoinfo *utxo,*tmp; int32_t iambob,n = 0; - printf("LP_utxopurge mypub.(%s)\n",bits256_str(str,LP_mypub25519)); - portable_mutex_lock(&LP_utxomutex); - for (iambob=0; iambob<=1; iambob++) - { - HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) - { - if ( LP_isavailable(utxo) > 0 ) - { - if ( allutxos != 0 || LP_ismine(utxo) > 0 ) - { - printf("iambob.%d delete.(%s)\n",iambob,bits256_str(str,utxo->payment.txid)); - HASH_DELETE(hh,LP_utxoinfos[iambob],utxo); - //free(utxo); let the LP_utxoinfos2 free the utxo, should be 1:1 - } else n++; - } else n++; - } - HASH_ITER(hh,LP_utxoinfos2[iambob],utxo,tmp) - { - if ( LP_isavailable(utxo) > 0 ) - { - if ( allutxos != 0 || LP_ismine(utxo) > 0 ) - { - printf("iambob.%d delete2.(%s)\n",iambob,bits256_str(str,utxo->payment.txid)); - HASH_DELETE(hh2,LP_utxoinfos2[iambob],utxo); - free(utxo); - } else n++; - } else n++; - } - } - portable_mutex_unlock(&LP_utxomutex); - return(n); -} +*/ cJSON *LP_inventoryjson(cJSON *item,struct LP_utxoinfo *utxo) { struct _LP_utxoinfo u; - jaddstr(item,"method","utxo"); + //jaddstr(item,"method","oldutxo"); if ( utxo == 0 ) return(item); if ( utxo->gui[0] != 0 ) @@ -267,8 +233,8 @@ cJSON *LP_inventoryjson(cJSON *item,struct LP_utxoinfo *utxo) 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->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); @@ -282,133 +248,50 @@ cJSON *LP_utxojson(struct LP_utxoinfo *utxo) jaddbits256(item,"pubkey",utxo->pubkey); //jaddnum(item,"profit",utxo->S.profitmargin); jaddstr(item,"base",utxo->coin); - jaddstr(item,"script",utxo->spendscript); + //jaddstr(item,"script",utxo->spendscript); return(item); } -int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2) -{ - //struct LP_utxoinfo *utxo; - uint64_t val,val2=0,txfee,threshold=0; int32_t bypass = 0; char destaddr[64],destaddr2[64]; struct iguana_info *coin = LP_coinfind(symbol); - destaddr[0] = destaddr2[0] = 0; - if ( coin != 0 && IAMLP != 0 && coin->inactive != 0 ) - bypass = 1; - if ( bypass != 0 ) - val = satoshis; - else val = LP_txvalue(destaddr,symbol,txid,vout); - txfee = LP_txfeecalc(symbol,0); - if ( val >= satoshis && val > (1+LP_MINSIZE_TXFEEMULT)*txfee ) - { - threshold = (iambob != 0) ? LP_DEPOSITSATOSHIS(satoshis) : (LP_DEXFEE(satoshis) + txfee); - if ( bypass != 0 ) - val2 = threshold; - else val2 = LP_txvalue(destaddr2,symbol,txid2,vout2); - if ( val2 >= threshold ) - { - if ( bypass == 0 && strcmp(destaddr,destaddr2) != 0 ) - printf("mismatched %s destaddr (%s) vs (%s)\n",symbol,destaddr,destaddr2); - else if ( bypass == 0 && ((iambob == 0 && val2 > val) || (iambob != 0 && val2 <= satoshis)) ) - printf("iambob.%d ineligible due to offsides: val %.8f and val2 %.8f vs %.8f diff %lld\n",iambob,dstr(val),dstr(val2),dstr(satoshis),(long long)(val2 - val)); - else - { - *valp = val; - *val2p = val2; - return(1); - } - } // else printf("no val2\n"); - } - // char str[65],str2[65]; printf("spent.%d %s txid or value %.8f < %.8f or val2 %.8f < %.8f, %s/v%d %s/v%d or < 10x txfee %.8f\n",iambob,symbol,dstr(val),dstr(satoshis),dstr(val2),dstr(threshold),bits256_str(str,txid),vout,bits256_str(str2,txid2),vout2,dstr(txfee)); - /*for (iter=0; iter<2; iter++) - { - if ( (utxo= LP_utxofind(iter,txid,vout)) != 0 ) - { - //printf("iambob.%d case 00\n",iter); - if ( utxo->T.spentflag == 0 ) - utxo->T.spentflag = (uint32_t)time(NULL); - } - if ( (utxo= LP_utxo2find(iter,txid,vout)) != 0 ) - { - //printf("iambob.%d case 01\n",iter); - if ( utxo->T.spentflag == 0 ) - utxo->T.spentflag = (uint32_t)time(NULL); - } - if ( (utxo= LP_utxofind(iter,txid2,vout2)) != 0 ) - { - //printf("iambob.%d case 10\n",iter); - if ( utxo->T.spentflag == 0 ) - utxo->T.spentflag = (uint32_t)time(NULL); - } - if ( (utxo= LP_utxo2find(iter,txid2,vout2)) != 0 ) - { - //printf("iambob.%d case 11\n",iter); - if ( utxo->T.spentflag == 0 ) - utxo->T.spentflag = (uint32_t)time(NULL); - } - }*/ - *valp = val; - *val2p = val2; - return(0); -} - -char *LP_utxos(int32_t iambob,struct LP_peerinfo *mypeer,char *symbol,int32_t lastn) -{ - int32_t i,n,m; uint64_t val,val2; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray(); - //n = mypeer != 0 ? mypeer->numutxos : 0; - if ( lastn <= 0 ) - lastn = LP_PROPAGATION_SLACK * 2; - HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) - { - //char str[65]; printf("check %s.%s\n",utxo->coin,bits256_str(str,utxo->payment.txid)); - if ( (symbol == 0 || symbol[0] == 0 || strcmp(symbol,utxo->coin) == 0) && utxo->T.spentflag == 0 ) - { - u = (iambob != 0) ? utxo->deposit : utxo->fee; - if ( LP_iseligible(&val,&val2,utxo->iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,u.txid,u.vout) == 0 ) - { - char str[65]; printf("iambob.%d not eligible (%.8f %.8f) %s %s/v%d\n",iambob,dstr(val),dstr(val2),utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout); - continue; - } else jaddi(utxosjson,LP_utxojson(utxo)); - } - } - if ( (n= cJSON_GetArraySize(utxosjson)) > lastn ) - { - m = n - lastn; - for (i=0; iT.spentflag != 0 ) - { - //char str[65]; printf("prevent adding %s/v%d to inventory\n",bits256_str(str,txid),vout); - return(1); - } - } - return(0); -} - struct LP_utxoinfo *LP_utxo_bestfit(char *symbol,uint64_t destsatoshis) { - uint64_t srcvalue,srcvalue2; struct LP_utxoinfo *utxo,*tmp,*bestutxo = 0; + uint64_t srcvalue,srcvalue2; struct LP_utxoinfo *utxo,*tmp,*bestutxo = 0; int32_t bestsize,iambob = 0; if ( symbol == 0 || destsatoshis == 0 ) { printf("LP_utxo_bestfit error symbol.%p %.8f\n",symbol,dstr(destsatoshis)); return(0); } - HASH_ITER(hh,LP_utxoinfos[0],utxo,tmp) + 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/2 && (bestutxo == 0 || (bestutxo->S.satoshis < destsatoshis && utxo->S.satoshis >= destsatoshis) || (bestutxo->S.satoshis >= destsatoshis && utxo->S.satoshis < bestutxo->S.satoshis)) ) + //printf("(%.8f %.8f %.8f)\n",dstr(utxo->payment.value),dstr(utxo->fee.value),dstr(utxo->S.satoshis)); + //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); + bestsize = 0; + if ( bestutxo == 0 ) + { + if ( utxo->S.satoshis > destsatoshis/LP_MINCLIENTVOL ) + bestsize = 1; + } + else { + if ( bestutxo->S.satoshis < destsatoshis ) + { + if ( utxo->S.satoshis > destsatoshis ) + bestsize = 1; + else if ( utxo->S.satoshis > bestutxo->S.satoshis ) + bestsize = 1; + } + else + { + if ( utxo->S.satoshis > destsatoshis && utxo->S.satoshis < bestutxo->S.satoshis ) + bestsize = 1; + } + } + if ( bestsize > 0 ) + { + //printf("bestsize.%d %.8f %.8f -> %.8f\n",bestsize,dstr(utxo->payment.value),dstr(utxo->fee.value),dstr(utxo->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 ) @@ -416,7 +299,7 @@ struct LP_utxoinfo *LP_utxo_bestfit(char *symbol,uint64_t destsatoshis) continue; } bestutxo = utxo; - } //else printf("skip alice utxo %.8f vs dest %.8f\n",dstr(utxo->S.satoshis),dstr(destsatoshis)); + } //else printf("skip alice utxo %.8f vs dest %.8f, bestsize.%d %p\n",dstr(utxo->S.satoshis),dstr(destsatoshis),bestsize,bestutxo); } } return(bestutxo); @@ -424,173 +307,90 @@ struct LP_utxoinfo *LP_utxo_bestfit(char *symbol,uint64_t destsatoshis) void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector) { - //cJSON *argjson; struct _LP_utxoinfo u; char *msg; if ( utxo == 0 ) return; utxo->T.spentflag = (uint32_t)time(NULL); - if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 ) - LP_mypeer->numutxos--; - /*if ( LP_mypubsock >= 0 ) - { - argjson = cJSON_CreateObject(); - jaddstr(argjson,"method","checktxid"); - jaddbits256(argjson,"txid",utxo->payment.txid); - jaddnum(argjson,"vout",utxo->payment.vout); - if ( selector != 0 ) - { - if ( bits256_nonz(utxo->deposit.txid) != 0 ) - u = utxo->deposit; - else u = utxo->fee; - jaddbits256(argjson,"checktxid",u.txid); - jaddnum(argjson,"checkvout",u.vout); - } - msg = jprint(argjson,1); - /LP_send(LP_mypubsock,msg,(int32_t)strlen(msg)+1,1); - }*/ -} - -char *LP_spentcheck(cJSON *argjson) -{ - bits256 txid,checktxid; int32_t vout,checkvout; struct LP_utxoinfo *utxo; int32_t iambob,retval = 0; - txid = jbits256(argjson,"txid"); - vout = jint(argjson,"vout"); - for (iambob=0; iambob<=1; iambob++) - { - if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 && utxo->T.spentflag == 0 ) - { - if ( jobj(argjson,"check") == 0 ) - checktxid = txid, checkvout = vout; - else - { - checktxid = jbits256(argjson,"checktxid"); - checkvout = jint(argjson,"checkvout"); - } - if ( LP_txvalue(0,utxo->coin,checktxid,checkvout) == 0 ) - { - if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 ) - LP_mypeer->numutxos--; - utxo->T.spentflag = (uint32_t)time(NULL); - retval++; - //printf("indeed txid was spent\n"); - } - } - } - if ( retval > 0 ) - return(clonestr("{\"result\":\"marked as spent\"}")); - return(clonestr("{\"error\":\"cant find txid to check spent status\"}")); -} - -void LP_utxo_clientpublish(struct LP_utxoinfo *utxo) -{ - bits256 zero; char *msg; - if ( LP_isunspent(utxo) > 0 ) - { - memset(zero.bytes,0,sizeof(zero)); - msg = jprint(LP_utxojson(utxo),1); - LP_broadcast_message(LP_mypubsock,utxo->coin,"",zero,msg); - } - /*struct LP_peerinfo *peer,*tmp; cJSON *retjson; char *retstr; int32_t n = 0; - HASH_ITER(hh,LP_peerinfos,peer,tmp) - { - if ( (retstr= issue_LP_notifyutxo(peer->ipaddr,peer->port,utxo)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( jobj(retjson,"error") == 0 ) - { - utxo->T.lasttime = (uint32_t)time(NULL); - n++; - } - free_json(retjson); - } - free(retstr); - } - //if ( utxo->T.lasttime != 0 ) - // return(0); - } - return(n);*/ } -struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bits256 txid,int32_t vout,int64_t value,bits256 txid2,int32_t vout2,int64_t value2,char *spendscript,char *coinaddr,bits256 pubkey,char *gui,uint32_t sessionid) +struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t vout,int64_t value,bits256 txid2,int32_t vout2,int64_t value2,char *coinaddr,bits256 pubkey,char *gui,uint32_t sessionid,uint64_t satoshis) { - uint64_t val,val2=0,tmpsatoshis,txfee; cJSON *txobj; 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 || spendscript == 0 || spendscript[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 ) + uint64_t val,val2=0,txfee; int32_t spendvini,numconfirms,selector; bits256 spendtxid; struct iguana_info *coin; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo = 0; + if ( symbol == 0 || symbol[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 || vout < 0 || vout2 < 0 || value <= 0 || value2 <= 0 )//|| sessionid == 0 ) { - printf("session.%u malformed addutxo %d %d %d %d %d %d %d %d %d\n",sessionid,symbol == 0,spendscript == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(txid2) == 0,vout < 0,vout2 < 0,value <= 0,value2 <= 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); + //printf("LP_utxoadd reject inactive %s\n",symbol); return(0); } - txfee = LP_txfeecalc(coin->symbol,0); - if ( iambob != 0 && value2 < 9 * (value >> 3) + 2*txfee ) // big txfee padding + txfee = LP_txfeecalc(coin,0,0); + /*if ( iambob != 0 && value2 < 9 * (satoshis >> 3) + 2*txfee ) // big txfee padding { if ( value2 > 2*txfee ) tmpsatoshis = (((value2 - 2*txfee) / 9) << 3); - else return(0); - } else tmpsatoshis = (value - txfee); - char str[65],str2[65],dispflag = (iambob == 0); - if ( iambob == 0 && bits256_cmp(pubkey,LP_mypub25519) != 0 ) + else + { + printf("value2 %.8f <= 2 * %.8f\n",dstr(value2),dstr(txfee)); + return(0); + } + } else tmpsatoshis = (satoshis - 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 ( LP_iseligible(&val,&val2,iambob,symbol,txid,vout,tmpsatoshis,txid2,vout2) <= 0 ) - { - printf("iambob.%d utxoadd %s inactive.%u got ineligible txid value %.8f, value2 %.8f, tmpsatoshis %.8f\n",iambob,symbol,coin->inactive,dstr(value),dstr(value2),dstr(tmpsatoshis)); - return(0); - } - numconfirms = -1; - if ( (txobj= LP_gettx(symbol,txid)) != 0 ) + if ( coin->inactive == 0 ) { - numconfirms = jint(txobj,"confirmations"); - free_json(txobj); - } - if ( numconfirms <= 0 ) - { - printf("LP_utxoadd reject numconfirms.%d\n",numconfirms); - return(0); + if ( LP_iseligible(&val,&val2,iambob,symbol,txid,vout,satoshis,txid2,vout2) <= 0 ) + { + static uint32_t counter; + if ( counter++ < 3 ) + printf("iambob.%d utxoadd %s inactive.%u got ineligible txid value %.8f:%.8f, value2 %.8f:%.8f, tmpsatoshis %.8f\n",iambob,symbol,coin->inactive,dstr(value),dstr(val),dstr(value2),dstr(val2),dstr(satoshis)); + 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); + } } - numconfirms = -1; - if ( (txobj= LP_gettx(symbol,txid2)) != 0 ) + else { - numconfirms = jint(txobj,"confirmations"); - free_json(txobj); - } - if ( numconfirms <= 0 ) - { - printf("LP_utxoadd reject2 numconfirms.%d\n",numconfirms); - return(0); + 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 ( (selector= LP_mempool_vinscan(&spendtxid,&spendvini,symbol,txid,vout,txid2,vout2)) >= 0 ) - { - printf("utxoadd selector.%d spent in mempool %s vini.%d",selector,bits256_str(str,spendtxid),spendvini); - return(0); - } 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)); + printf("duplicate %.8f %.8f %.8f vs utxo.(%.8f %.8f %.8f)\n",dstr(value),dstr(value2),dstr(satoshis),dstr(utxo->payment.value),dstr(utxo->deposit.value),dstr(utxo->S.satoshis)); } u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; - if ( bits256_cmp(txid,utxo->payment.txid) != 0 || bits256_cmp(txid2,u.txid) != 0 || vout != utxo->payment.vout || value != utxo->payment.value || tmpsatoshis != utxo->S.satoshis || vout2 != u.vout || value2 != u.value || strcmp(symbol,utxo->coin) != 0 || strcmp(spendscript,utxo->spendscript) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || bits256_cmp(pubkey,utxo->pubkey) != 0 ) + if ( bits256_cmp(txid,utxo->payment.txid) != 0 || bits256_cmp(txid2,u.txid) != 0 || vout != utxo->payment.vout || value != utxo->payment.value || satoshis != utxo->S.satoshis || vout2 != u.vout || value2 != u.value || strcmp(symbol,utxo->coin) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || bits256_cmp(pubkey,utxo->pubkey) != 0 ) { utxo->T.errors++; char str[65],str2[65],str3[65],str4[65],str5[65],str6[65]; 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); + //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 %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(spendscript,utxo->spendscript) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,bits256_cmp(pubkey,utxo->pubkey) != 0,value != utxo->payment.value,bits256_str(str5,pubkey),bits256_str(str6,utxo->pubkey)); + printf("error on subsequent utxo iambob.%d %.8f %.8f add.(%s %s) when.(%s %s) %d %d %d %d %d %d %d %d %d %d pubkeys.(%s vs %s)\n",iambob,dstr(val),dstr(val2),bits256_str(str,txid),bits256_str(str2,txid2),bits256_str(str3,utxo->payment.txid),bits256_str(str4,utxo->deposit.txid),bits256_cmp(txid,utxo->payment.txid) != 0,bits256_cmp(txid2,u.txid) != 0,vout != utxo->payment.vout,satoshis != utxo->S.satoshis,vout2 != u.vout,value2 != u.value,strcmp(symbol,utxo->coin) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,bits256_cmp(pubkey,utxo->pubkey) != 0,value != utxo->payment.value,bits256_str(str5,pubkey),bits256_str(str6,utxo->pubkey)); utxo = 0; } } @@ -601,6 +401,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit //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); } } @@ -610,11 +411,11 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit 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)); + //safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript)); utxo->payment.txid = txid; utxo->payment.vout = vout; utxo->payment.value = value; - utxo->S.satoshis = tmpsatoshis; + utxo->S.satoshis = satoshis; if ( (utxo->iambob= iambob) != 0 ) { utxo->deposit.txid = txid2; @@ -630,21 +431,24 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit LP_utxosetkey(utxo->key,txid,vout); LP_utxosetkey(utxo->key2,txid2,vout2); if ( LP_ismine(utxo) > 0 ) - utxo->T.sessionid = LP_sessionid; + utxo->T.sessionid = G.LP_sessionid; else utxo->T.sessionid = sessionid; - printf("U.%d %s %.8f %.8f addutxo.%d pubkey.%s session.%u\n",LP_mypeer!=0?LP_mypeer->numutxos:-1,symbol,dstr(value),dstr(value2),LP_ismine(utxo) > 0,bits256_str(str,utxo->pubkey),utxo->T.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 <<<<<<<<<<<<<<< %.8f\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,dstr(satoshis)); portable_mutex_lock(&LP_utxomutex); - HASH_ADD_KEYPTR(hh,LP_utxoinfos[iambob],utxo->key,sizeof(utxo->key),utxo); + 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,LP_utxoinfos2[iambob],utxo->key2,sizeof(utxo->key2),utxo); + HASH_ADD_KEYPTR(hh2,G.LP_utxoinfos2[iambob],utxo->key2,sizeof(utxo->key2),utxo); portable_mutex_unlock(&LP_utxomutex); if ( iambob != 0 ) { - if ( LP_mypeer != 0 ) - LP_mypeer->numutxos++; if ( LP_ismine(utxo) > 0 ) { - LP_utxo_clientpublish(utxo); + //LP_utxo_clientpublish(utxo); if ( LP_mypeer != 0 ) utxo->T.lasttime = (uint32_t)time(NULL); } @@ -652,126 +456,75 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit return(utxo); } -struct LP_utxoinfo *LP_utxoaddjson(int32_t iambob,int32_t pubsock,cJSON *argjson) -{ - struct LP_utxoinfo *utxo; - if ( jobj(argjson,"iambob") == 0 || iambob != jint(argjson,"iambob") ) - { - printf("LP_utxoaddjson: iambob.%d != arg.%d obj.%p (%s)\n",iambob,jint(argjson,"iambob"),jobj(argjson,"iambob"),jprint(argjson,0)); - return(0); - } - portable_mutex_lock(&LP_UTXOmutex); - utxo = LP_utxoadd(iambob,pubsock,jstr(argjson,"coin"),jbits256(argjson,"txid"),jint(argjson,"vout"),j64bits(argjson,"value"),jbits256(argjson,"txid2"),jint(argjson,"vout2"),j64bits(argjson,"value2"),jstr(argjson,"script"),jstr(argjson,"address"),jbits256(argjson,"pubkey"),jstr(argjson,"gui"),juint(argjson,"session")); - if ( LP_ismine(utxo) > 0 && utxo->T.lasttime == 0 ) - { - utxo->T.lasttime = (uint32_t)time(NULL); - printf("set lasttime!\n"); - } - portable_mutex_unlock(&LP_UTXOmutex); - return(utxo); -} - -int32_t LP_utxosparse(char *destipaddr,uint16_t destport,char *retstr,uint32_t now) +int32_t _LP_utxos_remove(bits256 txid,int32_t vout) { - struct LP_peerinfo *destpeer,*peer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; bits256 txid; struct LP_utxoinfo *utxo; - //printf("parse.(%s)\n",retstr); - if ( (array= cJSON_Parse(retstr)) != 0 ) + struct LP_utxoinfo *utxo,*utxo2; int32_t retval = 0,iambob = 1; + utxo = utxo2 = 0; + if ( (utxo= _LP_utxofind(iambob,txid,vout)) != 0 ) { - if ( (n= cJSON_GetArraySize(array)) > 0 ) + if ( LP_isavailable(utxo) == 0 ) + retval = -1; + else { - for (i=0; iT.lasttime = now; - } - } - if ( (destpeer= LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport)) != 0 ) - { - destpeer->numutxos = n; } } - free_json(array); } - return(n); + else if ( (utxo2= _LP_utxo2find(iambob,txid,vout)) != 0 ) + { + if ( LP_isavailable(utxo2) == 0 ) + retval = -1; + else _LP_utxo2_delete(iambob,utxo2); + } + return(retval); } -int32_t LP_utxosquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *coin,int32_t lastn,char *myipaddr,uint16_t myport,int32_t maxentries) +int32_t LP_utxos_remove(bits256 txid,int32_t vout) { - char *retstr; struct LP_peerinfo *peer; uint32_t now; int32_t retval = -1; - peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); - if ( coin == 0 ) - coin = ""; - //printf("utxo query.(%s)\n",destipaddr); - if ( IAMLP != 0 ) - retstr = issue_LP_getutxos(destipaddr,destport,coin,lastn,myipaddr,myport,mypeer != 0 ? mypeer->numpeers : 0,maxentries); - else retstr = issue_LP_clientgetutxos(destipaddr,destport,coin,maxentries); - if ( retstr != 0 ) - { - now = (uint32_t)time(NULL); - retval = LP_utxosparse(destipaddr,destport,retstr,now); - //printf("got.(%s)\n",retstr); - free(retstr); - /*i = 0; - if ( lastn >= mypeer->numutxos ) - firsti = -1; - else firsti = (mypeer->numutxos - lastn); - HASH_ITER(hh,LP_utxoinfos,utxo,tmp) - { - if ( i++ < firsti ) - continue; - if ( utxo->lasttime != now && strcmp(utxo->ipaddr,"127.0.0.1") != 0 ) - { - char str[65]; printf("{%s:%u %s} ",utxo->ipaddr,utxo->port,bits256_str(str,utxo->txid)); - flag++; - if ( (retstr= issue_LP_notifyutxo(destipaddr,destport,utxo)) != 0 ) - free(retstr); - } - } - if ( flag != 0 ) - printf(" <- missing utxos\n");*/ - } + int32_t retval; + portable_mutex_lock(&LP_utxomutex); + retval = _LP_utxos_remove(txid,vout); + portable_mutex_unlock(&LP_utxomutex); return(retval); } -cJSON *LP_inventory(char *symbol,int32_t iambob) +cJSON *LP_inventory(char *symbol) { - struct LP_utxoinfo *utxo,*tmp; struct _LP_utxoinfo u; char *myipaddr; cJSON *array; uint64_t val,val2; + 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"; - HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) + 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)); + 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); + //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); + //if ( iambob != 0 ) + // LP_utxo_clientpublish(utxo); jaddi(array,LP_inventoryjson(cJSON_CreateObject(),utxo)); } - //else printf("skip %s %d %d %d %d\n",bits256_str(str,utxo->pubkey),LP_isunspent(utxo) != 0,strcmp(symbol,utxo->coin) == 0,utxo->iambob == iambob,LP_ismine(utxo) > 0); + else if ( 0 && LP_ismine(utxo) > 0 && strcmp(symbol,utxo->coin) == 0 ) + printf("skip %s %s %d %d %d %d\n",utxo->coin,bits256_str(str,utxo->payment.txid),LP_isunspent(utxo) != 0,strcmp(symbol,utxo->coin) == 0,utxo->iambob == iambob,LP_ismine(utxo) > 0); } return(array); } @@ -806,40 +559,60 @@ int32_t LP_nearestvalue(int32_t iambob,uint64_t *values,int32_t n,uint64_t targe return(mini); } -uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 myprivkey,bits256 mypub) +int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 myprivkey,bits256 mypub) { - char *script; struct LP_utxoinfo *utxo; cJSON *array,*item; bits256 txid,deposittxid; int32_t used,i,n,iambob,vout,depositvout; uint64_t *values=0,satoshis,txfee,depositval,targetval,value,total = 0; - if ( coin == 0 ) + 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,biggerval,value,total = 0; int64_t targetval; + if ( coin == 0 || (IAMLP == 0 && coin->inactive != 0) ) { - printf("coin not active\n"); + //printf("coin not active\n"); return(0); } - //printf("privkey init.(%s) %s\n",coin->symbol,coin->smartaddr); - if ( coin->inactive == 0 && (array= LP_listunspent(coin->symbol,coin->smartaddr)) != 0 ) - { - txfee = LP_txfeecalc(coin->symbol,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); + array = LP_listunspent(coin->symbol,coin->smartaddr); + 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)); - //if ( iambob == 0 && IAMLP != 0 ) - // continue; used = 0; for (i=0; i 0 ) + 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 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 ) { - //printf("%s\n",jprint(item,0)); values[i] = satoshis; + //flag += LP_address_utxoadd(coin,destaddr,txid,vout,satoshis,height,-1); } else used++; - //printf("%.8f ",dstr(satoshis)); } //printf("array.%d\n",n); while ( used < n-1 ) @@ -850,17 +623,28 @@ uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypr if ( (i= LP_maxvalue(values,n)) >= 0 ) { item = jitem(array,i); - deposittxid = jbits256(item,"txid"); - depositvout = juint(item,"vout"); - script = jstr(item,"scriptPubKey"); - depositval = values[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 = (depositval / 776) + txfee; - else targetval = (depositval / 9) * 8 + 2*txfee; - if ( depositval < (1+LP_MINSIZE_TXFEEMULT)*txfee ) + 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; - //printf("iambob.%d i.%d %.8f target %.8f\n",iambob,i,dstr(depositval),dstr(targetval)); i = -1; if ( iambob != 0 ) { @@ -871,48 +655,117 @@ uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypr } 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); - txid = jbits256(item,"txid"); - vout = juint(item,"vout"); - if ( jstr(item,"scriptPubKey") != 0 && strcmp(script,jstr(item,"scriptPubKey")) == 0 ) + 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,mypubsock,coin->symbol,txid,vout,value,deposittxid,depositvout,depositval,script,coin->smartaddr,mypub,LP_gui,LP_sessionid)) != 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 { - if ( (utxo= LP_utxoadd(0,mypubsock,coin->symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coin->smartaddr,mypub,LP_gui,LP_sessionid)) != 0 ) + //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("scriptmismatch.(%s) vs %s\n",script,jprint(item,0)); } //else printf("nothing near i.%d\n",i); } else break; } - if ( iambob == 1 ) - free(values); + 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(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 %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,ibytes,(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); @@ -924,29 +777,36 @@ bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguan 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,rmd160,coin->smartaddr); - LP_privkeyadd(privkey,rmd160); + 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 ( counter++ == 0 ) + if ( G.counter++ == 0 ) { - bitcoin_priv2wif(coin->wiftaddr,USERPASS_WIFSTR,privkey,188); - bitcoin_wif2priv(coin->wiftaddr,&tmptype,&checkkey,USERPASS_WIFSTR); + 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",USERPASS_WIFSTR,bits256_str(str,checkkey),bits256_str(str2,privkey)); + 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 *)USERPASS_WIFSTR,(int32_t)strlen(USERPASS_WIFSTR)); + 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(USERPASS,userpub)); + printf("userpass.(%s)\n",bits256_str(G.USERPASS,userpub)); } + } + if ( coin->importedprivkey == 0 && coin->electrum == 0 && coin->userpass[0] != 0 && LP_getheight(coin) > 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 ) @@ -954,27 +814,92 @@ bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguan printf("cant importprivkey.%s -> (%s), abort session\n",coin->symbol,jprint(retjson,1)); exit(-1); } + free_json(retjson); } + coin->importedprivkey = (uint32_t)time(NULL); } - LP_mypub25519 = *pubkeyp = curve25519(privkey,curve25519_basepoint9()); - LP_mypriv25519 = privkey; - //printf("privkey.(%s) -> LP_mypub25519.(%s)\n",bits256_str(str,privkey),bits256_str(str2,LP_mypub25519)); + 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,int32_t initonly) +void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase) { - struct iguana_info *coin,*tmp; bits256 pubkey,privkey; uint8_t pubkey33[33]; + struct iguana_info *coin,*tmp; bits256 pubkey,privkey; uint8_t pubkey33[33]; int32_t initonly; + initonly = (passphrase != 0); memset(privkey.bytes,0,sizeof(privkey)); - pubkey = 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); - if ( bits256_nonz(privkey) == 0 || coin->smartaddr[0] == 0 ) - privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,coin,passphrase,""); - if ( coin->inactive == 0 && initonly == 0 ) - LP_privkey_init(pubsock,coin,privkey,pubkey); + else if ( IAMLP == 0 || coin->inactive == 0 ) + { + //printf("from updates %s\n",coin->symbol); + if ( LP_privkey_init(pubsock,coin,G.LP_privkey,G.LP_mypub25519) == 0 && (LP_rand() % 10) == 0 ) + { + //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; + G.initializing = 0; + return(0); +} + diff --git a/iguana/exchanges/Makefile b/iguana/exchanges/Makefile new file mode 100644 index 000000000..be75a297c --- /dev/null +++ b/iguana/exchanges/Makefile @@ -0,0 +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 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 + diff --git a/iguana/exchanges/assetchains.old b/iguana/exchanges/assetchains.old new file mode 100755 index 000000000..e7584afcd --- /dev/null +++ b/iguana/exchanges/assetchains.old @@ -0,0 +1,89 @@ +#!/bin/bash +set -x +delay=60 +source pubkey.txt +echo $pubkey + +./komodod -pubkey=$pubkey -ac_name=REVS -ac_supply=1300000 -addnode=78.47.196.146 $1 & +./komodod -pubkey=$pubkey -ac_name=SUPERNET -ac_supply=816061 -addnode=78.47.196.146 $1 & +./komodod -pubkey=$pubkey -ac_name=DEX -ac_supply=999999 -addnode=78.47.196.146 $1 & +./komodod -pubkey=$pubkey -ac_name=PANGEA -ac_supply=999999 -addnode=78.47.196.146 $1 & +./komodod -pubkey=$pubkey -ac_name=JUMBLR -ac_supply=999999 -addnode=78.47.196.146 $1 & +./komodod -pubkey=$pubkey -ac_name=BET -ac_supply=999999 -addnode=78.47.196.146 $1 & +./komodod -pubkey=$pubkey -ac_name=CRYPTO -ac_supply=999999 -addnode=78.47.196.146 $1 & +./komodod -pubkey=$pubkey -ac_name=HODL -ac_supply=9999999 -addnode=78.47.196.146 $1 & +./komodod -pubkey=$pubkey -ac_name=SHARK -ac_supply=1401 -addnode=78.47.196.146 $1 & +./komodod -pubkey=$pubkey -ac_name=BOTS -ac_supply=999999 -addnode=78.47.196.146 $1 & +./komodod -pubkey=$pubkey -ac_name=MGW -ac_supply=999999 -addnode=78.47.196.146 $1 & +#./komodod -pubkey=$pubkey -ac_name=MVP -ac_supply=1000000 -addnode=78.47.196.146 $1 & +./komodod -pubkey=$pubkey -ac_name=COQUI -ac_supply=72000000 -addnode=78.47.196.146 $1 & +./komodod -pubkey=$pubkey -ac_name=WLC -ac_supply=210000000 -addnode=148.251.190.89 $1 & +./komodod -pubkey=$pubkey -ac_name=KV -ac_supply=1000000 -addnode=78.47.196.146 $1 & +./komodod -pubkey=$pubkey -ac_name=CEAL -ac_supply=366666666 -addnode=78.47.196.146 $1 & +./komodod -pubkey=$pubkey -ac_name=MESH -ac_supply=1000007 -addnode=78.47.196.146 $1 & +./komodod -pubkey=$pubkey -ac_name=MNZ -ac_supply=257142858 -addnode=51.15.138.138 $1 & +sleep $delay + +./komodod -pubkey=$pubkey -ac_name=USD -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=EUR -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=JPY -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=GBP -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=AUD -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=CAD -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=CHF -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=NZD -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=CNY -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=RUB -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=MXN -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=BRL -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=INR -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=HKD -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=TRY -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=ZAR -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=PLN -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=NOK -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=SEK -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=DKK -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=CZK -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=HUF -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=ILS -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=KRW -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=MYR -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=PHP -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=RON -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=SGD -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=THB -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=BGN -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=IDR -addnode=78.47.196.146 $1 & +sleep $delay +./komodod -pubkey=$pubkey -ac_name=HRK -addnode=78.47.196.146 $1 & diff --git a/iguana/exchanges/autofill b/iguana/exchanges/autofill index 47afea4f1..b0724a9db 100755 --- a/iguana/exchanges/autofill +++ b/iguana/exchanges/autofill @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autofill\",\"base\":\"KMD\",\"rel\":\"BTC\",\"price\":0.0005,\"relvolume\":0.1}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autofill\",\"base\":\"KMD\",\"rel\":\"BTC\",\"price\":0.0005,\"relvolume\":0.1}" diff --git a/iguana/exchanges/autoprice b/iguana/exchanges/autoprice index e612d19a9..21369b468 100755 --- a/iguana/exchanges/autoprice +++ b/iguana/exchanges/autoprice @@ -1,9 +1,12 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"BTC\",\"margin\":0.0001}" -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"BTC\",\"rel\":\"KMD\",\"margin\":0.0001}" -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"HUSH\",\"margin\":0.01}" -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"HUSH\",\"rel\":\"KMD\",\"margin\":0.01}" -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"USD\",\"margin\":0.01}" -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"USD\",\"rel\":\"KMD\",\"margin\":0.01}" -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"JUMBLR\",\"margin\":0.01}" -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"JUMBLR\",\"rel\":\"KMD\",\"margin\":0.01}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"BTC\",\"margin\":0.03}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"BTC\",\"rel\":\"KMD\",\"margin\":0.03}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"HUSH\",\"margin\":0.01}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"HUSH\",\"rel\":\"KMD\",\"margin\":0.01}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"USD\",\"margin\":0.01}" +#curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"USD\",\"rel\":\"KMD\",\"margin\":0.01}" +#curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"JUMBLR\",\"margin\":0.01}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"JUMBLR\",\"rel\":\"KMD\",\"margin\":0.01}" +#curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"MNZ\",\"rel\":\"KMD\",\"offset\":0.0,\"refbase\":\"BTC\",\"refrel\":\"KMD\",\"factor\":0.00006667,\"margin\":-0.2}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"MNZ\",\"offset\":0.0,\"refbase\":\"KMD\",\"refrel\":\"BTC\",\"factor\":15000,\"margin\":-0.2}" diff --git a/iguana/exchanges/autotrade b/iguana/exchanges/autotrade index f88b157bb..72e14f84a 100755 --- a/iguana/exchanges/autotrade +++ b/iguana/exchanges/autotrade @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autotrade\",\"base\":\"REVS\",\"rel\":\"KMD\",\"relvolume\":1.01,\"price\":1.234}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autotrade\",\"base\":\"REVS\",\"rel\":\"KMD\",\"relvolume\":1.01,\"price\":1.234}" diff --git a/iguana/exchanges/balance b/iguana/exchanges/balance new file mode 100755 index 000000000..22f84cdee --- /dev/null +++ b/iguana/exchanges/balance @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"balance\",\"coin\":\"KMD\",\"address\":\"RHV2As4rox97BuE3LK96vMeNY8VsGRTmBj\"}" diff --git a/iguana/exchanges/balance_loop b/iguana/exchanges/balance_loop new file mode 100755 index 000000000..ad28ac741 --- /dev/null +++ b/iguana/exchanges/balance_loop @@ -0,0 +1,12 @@ +#!/bin/bash +source userpass +ht=$1 +while true +do +#curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"snapshot\",\"coin\":\"KMD\",\"height\":$ht}" +ht=`curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"snapshot\",\"coin\":\"KMD\"}" | jq .blocks` + +echo next height $ht +sleep 600 +done + diff --git a/iguana/exchanges/barterDEX.c b/iguana/exchanges/barterDEX.c new file mode 100644 index 000000000..976016bc2 --- /dev/null +++ b/iguana/exchanges/barterDEX.c @@ -0,0 +1,14 @@ +#include +#include +#include +#include + +char *barterDEX(char *jsonstr) +{ +char *retstr,*str = "{\"result\":\"success\"}"; +printf("barterDEX.(%s)\n",jsonstr); +retstr = malloc(strlen(str)+1); +strcpy(retstr,str); +return(retstr); +} + diff --git a/iguana/exchanges/baserelswaps b/iguana/exchanges/baserelswaps new file mode 100755 index 000000000..abea1c80e --- /dev/null +++ b/iguana/exchanges/baserelswaps @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"swapstatus\",\"base\":\"MNZ\",\"rel\":\"KMD\"}" diff --git a/iguana/exchanges/bestfit b/iguana/exchanges/bestfit index 9ed9e4df2..bae6a79ac 100755 --- a/iguana/exchanges/bestfit +++ b/iguana/exchanges/bestfit @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"bestfit\",\"rel\":\"KMD\",\"relvolume\":1.01}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"bestfit\",\"rel\":\"KMD\",\"relvolume\":1.01}" diff --git a/iguana/exchanges/bot_buy b/iguana/exchanges/bot_buy new file mode 100755 index 000000000..d26f5a8f7 --- /dev/null +++ b/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}" diff --git a/iguana/exchanges/bot_list b/iguana/exchanges/bot_list new file mode 100755 index 000000000..40cb49145 --- /dev/null +++ b/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\"}" diff --git a/iguana/exchanges/bot_pause b/iguana/exchanges/bot_pause new file mode 100755 index 000000000..ed9323e71 --- /dev/null +++ b/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}" diff --git a/iguana/exchanges/bot_resume b/iguana/exchanges/bot_resume new file mode 100755 index 000000000..6d161b155 --- /dev/null +++ b/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}" diff --git a/iguana/exchanges/bot_sell b/iguana/exchanges/bot_sell new file mode 100755 index 000000000..3613db3cb --- /dev/null +++ b/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}" diff --git a/iguana/exchanges/bot_settings b/iguana/exchanges/bot_settings new file mode 100755 index 000000000..f02ca3016 --- /dev/null +++ b/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}" diff --git a/iguana/exchanges/bot_status b/iguana/exchanges/bot_status new file mode 100755 index 000000000..e64bc5ae7 --- /dev/null +++ b/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}" diff --git a/iguana/exchanges/bot_statuslist b/iguana/exchanges/bot_statuslist new file mode 100755 index 000000000..14b7e3522 --- /dev/null +++ b/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\"}" diff --git a/iguana/exchanges/bot_stop b/iguana/exchanges/bot_stop new file mode 100755 index 000000000..665e2ac9e --- /dev/null +++ b/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}" diff --git a/iguana/exchanges/buy b/iguana/exchanges/buy new file mode 100755 index 000000000..cf83a91df --- /dev/null +++ b/iguana/exchanges/buy @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"buy\",\"base\":\"KMD\",\"rel\":\"BTC\",\"relvolume\":0.005,\"price\":0.0005}" diff --git a/iguana/exchanges/cancelorder b/iguana/exchanges/cancelorder index 31f46e020..31fe7ea8c 100755 --- a/iguana/exchanges/cancelorder +++ b/iguana/exchanges/cancelorder @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"setprice\",\"base\":\"REVS\",\"rel\":\"KMD\",\"price\":9999999.99}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"setprice\",\"base\":\"REVS\",\"rel\":\"KMD\",\"price\":9999999.99}" diff --git a/iguana/exchanges/client b/iguana/exchanges/client index 8b3f8a7ba..a36758376 100755 --- a/iguana/exchanges/client +++ b/iguana/exchanges/client @@ -1,3 +1,4 @@ +#!/bin/bash source passphrase source coins pkill -15 marketmaker; diff --git a/iguana/exchanges/client_osx b/iguana/exchanges/client_osx index 9e1cada67..463a08eb4 100755 --- a/iguana/exchanges/client_osx +++ b/iguana/exchanges/client_osx @@ -1,3 +1,4 @@ +#!/bin/bash source passphrase source coins pkill -15 marketmaker; diff --git a/iguana/exchanges/coins b/iguana/exchanges/coins index 2964fc4f9..9b5789e13 100644 --- a/iguana/exchanges/coins +++ b/iguana/exchanges/coins @@ -1,2 +1,4 @@ -export coins="[{\"coin\":\"888\",\"name\":\"octocoin\",\"rpcport\":22888,\"pubtype\":18,\"p2shtype\":5,\"wiftype\":176,\"txfee\":2000000}, {\"coin\":\"ARG\",\"name\":\"argentum\",\"rpcport\":13581,\"pubtype\":23,\"p2shtype\":5,\"wiftype\":151,\"txfee\":50000}, {\"coin\":\"GLT\",\"name\":\"globaltoken\",\"rpcport\":9320,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":166,\"txfee\":10000}, {\"coin\":\"ZER\",\"name\":\"zero\",\"rpcport\":23801,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"HODLC\",\"name\":\"hodlcoin\",\"rpcport\":11989,\"pubtype\":40,\"p2shtype\":5,\"wiftype\":168,\"txfee\":5000}, {\"coin\":\"UIS\",\"name\":\"unitus\",\"rpcport\":50604,\"pubtype\":68,\"p2shtype\":10,\"wiftype\":132,\"txfee\":1000000}, {\"coin\":\"CRW\",\"name\":\"crown\",\"rpcport\":9341,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"HUC\",\"name\":\"huntercoin\",\"rpcport\":8399,\"pubtype\":40,\"p2shtype\":13,\"wiftype\":168,\"txfee\":100000}, {\"coin\":\"PIVX\",\"name\":\"pivx\",\"rpcport\":51473,\"pubtype\":30,\"p2shtype\":13,\"wiftype\":212,\"txfee\":10000}, {\"coin\":\"BDL\",\"name\":\"bitdeal\",\"rpcport\":9332,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"ARC\",\"name\":\"arcticcoin\",\"confpath\":\"${HOME#}/.arcticcore/arcticcoin.conf\",\"rpcport\":7208,\"pubtype\":23,\"p2shtype\":8,\"wiftype\":176,\"txfee\":10000}, {\"coin\":\"ZCL\",\"name\":\"zclassic\",\"rpcport\":8023,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"VIA\",\"name\":\"viacoin\",\"rpcport\":5222,\"pubtype\":71,\"p2shtype\":33,\"wiftype\":199,\"txfee\":100000}, {\"coin\":\"ERC\",\"name\":\"europecoin\",\"rpcport\":11989,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":168,\"txfee\":10000},{\"coin\":\"FAIR\",\"name\":\"faircoin\",\"confpath\":\"${HOME#}/.faircoin2/faircoin.conf\",\"rpcport\":40405,\"pubtype\":95,\"p2shtype\":36,\"wiftype\":223,\"txfee\":1000000}, {\"coin\":\"FLO\",\"name\":\"florincoin\",\"rpcport\":7313,\"pubtype\":35,\"p2shtype\":8,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"SXC\",\"name\":\"sexcoin\",\"rpcport\":9561,\"pubtype\":62,\"p2shtype\":5,\"wiftype\":190,\"txfee\":100000}, {\"coin\":\"CREA\",\"name\":\"creativecoin\",\"rpcport\":17711,\"pubtype\":28,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"TRC\",\"name\":\"terracoin\",\"rpcport\":13332,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"BTA\",\"name\":\"bata\",\"rpcport\":5493,\"pubtype\":25,\"p2shtype\":5,\"wiftype\":188,\"txfee\":100000}, {\"coin\":\"SMC\",\"name\":\"smartcoin\",\"rpcport\":58583,\"pubtype\":63,\"p2shtype\":5,\"wiftype\":191,\"txfee\":1000000}, {\"coin\":\"NMC\",\"name\":\"namecoin\",\"rpcport\":8336,\"pubtype\":52,\"p2shtype\":13,\"wiftype\":180,\"txfee\":100000}, {\"coin\":\"NAV\",\"name\":\"navcoin\",\"isPoS\":1,\"confpath\":\"${HOME#}/.navcoin4/navcoin.conf\",\"rpcport\":44444,\"pubtype\":53,\"p2shtype\":85,\"wiftype\":150,\"txfee\":10000}, {\"coin\":\"MOON\",\"name\":\"Mooncoin\",\"rpcport\":44663,\"pubtype\":3,\"p2shtype\":22,\"wiftype\":131,\"txfee\":100000}, {\"coin\":\"EMC2\",\"name\":\"einsteinium\",\"rpcport\":41879,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"SYS\",\"name\":\"syscoin\",\"rpcport\":8370,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"I0C\",\"name\":\"i0coin\",\"rpcport\":7332,\"pubtype\":105,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"DASH\",\"confpath\":\"${HOME#}/.dashcore/dash.conf\",\"name\":\"dashcore\",\"rpcport\":9998,\"pubtype\":76,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"STRAT\", \"name\": \"stratis\", \"active\":0, \"rpcport\":16174,\"pubtype\":63, \"p2shtype\":125, \"wiftype\":191, \"txfee\":10000}, {\"confpath\":\"${HOME#}/.muecore/mue.conf\",\"coin\":\"MUE\",\"name\":\"muecore\",\"rpcport\":29683,\"pubtype\":16,\"p2shtype\":76,\"wiftype\":126,\"txfee\":10000}, {\"coin\":\"MONA\",\"name\":\"monacoin\",\"rpcport\":9402,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"XMY\",\"name\":\"myriadcoin\",\"rpcport\":10889,\"pubtype\":50,\"p2shtype\":9,\"wiftype\":178,\"txfee\":5000}, {\"coin\":\"MAC\",\"name\":\"machinecoin\",\"rpcport\":40332,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":178,\"txfee\":50000}, {\"coin\":\"BTX\",\"name\":\"bitcore\",\"rpcport\":8556,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":50000}, {\"coin\":\"XRE\",\"name\":\"revolvercoin\",\"rpcport\":8775,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"LBC\",\"name\":\"lbrycrd\",\"rpcport\":9245,\"pubtype\":85,\"p2shtype\":122,\"wiftype\":28,\"txfee\":1000}, {\"coin\":\"SIB\",\"name\":\"sibcoin\",\"rpcport\":1944,\"pubtype\":63,\"p2shtype\":40,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"VTC\", \"name\":\"vertcoin\", \"rpcport\":5888, \"pubtype\":71, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000 }, {\"coin\":\"REVS\",\"active\":0, \"asset\":\"REVS\",\"rpcport\":10196}, {\"coin\":\"JUMBLR\",\"active\":0, \"asset\":\"JUMBLR\",\"rpcport\":15106}, {\"coin\":\"DOGE\",\"name\":\"dogecoin\",\"rpcport\":22555,\"pubtype\":30,\"p2shtype\":22,\"wiftype\":158,\"txfee\":100000000}, {\"coin\":\"HUSH\",\"name\":\"hush\",\"rpcport\":8822,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000 }, {\"active\":0,\"coin\":\"ZEC\",\"name\":\"zcash\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000 }, {\"coin\":\"DGB\",\"name\":\"digibyte\",\"rpcport\":14022,\"pubtype\":30,\"p2shtype\":5,\"wiftype\":128,\"txfee\":100000}, {\"coin\":\"MZC\", \"name\":\"mazacoin\", \"pubtype\":50, \"p2shtype\":9, \"wiftype\":224, \"txfee\":10000}, {\"coin\":\"UNO\", \"name\":\"unobtanium\", \"pubtype\":130, \"p2shtype\":30, \"wiftype\":224, \"txfee\":1000000}, {\"coin\":\"ZET\", \"name\":\"zetacoin\", \"pubtype\":80, \"p2shtype\":9,\"rpcport\":8332, \"wiftype\":224, \"txfee\":10000}, {\"coin\":\"BTM\", \"name\":\"bitmark\", \"pubtype\":85, \"p2shtype\":5, \"wiftype\":213, \"txfee\":10000}, {\"coin\":\"CARB\", \"name\":\"carboncoin\", \"pubtype\":47, \"p2shtype\":5, \"wiftype\":175, \"txfee\":10000}, {\"coin\":\"ANC\", \"name\":\"anoncoin\", \"pubtype\":23, \"p2shtype\":5, \"wiftype\":151, \"txfee\":2000000}, {\"coin\":\"FRK\", \"name\":\"franko\", \"pubtype\":35, \"p2shtype\":5, \"wiftype\":163, \"txfee\":10000}, {\"coin\":\"GAME\", \"rpcport\":40001, \"name\":\"gamecredits\", \"pubtype\":38, \"p2shtype\":5, \"wiftype\":166, \"txfee\":100000}, {\"coin\":\"LTC\", \"name\":\"litecoin\", \"rpcport\":9332, \"pubtype\":48, \"p2shtype\":5, \"wiftype\":176, \"txfee\":100000 }, {\"coin\":\"SUPERNET\",\"asset\":\"SUPERNET\",\"rpcport\":11341}, {\"coin\":\"WLC\",\"asset\":\"WLC\",\"rpcport\":12167}, {\"coin\":\"PANGEA\",\"asset\":\"PANGEA\",\"rpcport\":14068}, {\"coin\":\"DEX\",\"asset\":\"DEX\",\"rpcport\":11890}, {\"coin\":\"BET\",\"asset\":\"BET\",\"rpcport\":14250}, {\"coin\":\"CRYPTO\",\"asset\":\"CRYPTO\",\"rpcport\":8516}, {\"coin\":\"HODL\",\"asset\":\"HODL\",\"rpcport\":14431}, {\"coin\":\"SHARK\",\"asset\":\"SHARK\",\"rpcport\":10114}, {\"coin\":\"BOTS\",\"asset\":\"BOTS\",\"rpcport\":11964}, {\"coin\":\"MGW\",\"asset\":\"MGW\",\"rpcport\":12386}, {\"coin\":\"COQUI\",\"asset\":\"COQUI\",\"rpcport\":14276}, {\"coin\":\"KV\",\"asset\":\"KV\",\"rpcport\":8299}, {\"coin\":\"CEAL\",\"asset\":\"CEAL\",\"rpcport\":11116}, {\"coin\":\"MESH\",\"asset\":\"MESH\",\"rpcport\":9455}, {\"coin\":\"AUD\",\"asset\":\"AUD\",\"rpcport\":8045}, {\"coin\":\"BGN\",\"asset\":\"BGN\",\"rpcport\":9110}, {\"coin\":\"CAD\",\"asset\":\"CAD\",\"rpcport\":8720}, {\"coin\":\"CHF\",\"asset\":\"CHF\",\"rpcport\":15312}, {\"coin\":\"CNY\",\"asset\":\"CNY\",\"rpcport\":10384}, {\"coin\":\"CZK\",\"asset\":\"CZK\",\"rpcport\":9482}, {\"coin\":\"DKK\",\"asset\":\"DKK\",\"rpcport\":13830}, {\"coin\":\"EUR\",\"asset\":\"EUR\",\"rpcport\":8065}, {\"coin\":\"GBP\",\"asset\":\"GBP\",\"rpcport\":11505}, {\"coin\":\"HKD\",\"asset\":\"HKD\",\"rpcport\":15409}, {\"coin\":\"HRK\",\"asset\":\"HRK\",\"rpcport\":12617}, {\"coin\":\"HUF\",\"asset\":\"HUF\",\"rpcport\":13699}, {\"coin\":\"IDR\",\"asset\":\"IDR\",\"rpcport\":14459}, {\"coin\":\"ILS\",\"asset\":\"ILS\",\"rpcport\":14638}, {\"coin\":\"INR\",\"asset\":\"INR\",\"rpcport\":10536}, {\"coin\":\"JPY\",\"asset\":\"JPY\",\"rpcport\":13145}, {\"coin\":\"KRW\",\"asset\":\"KRW\",\"rpcport\":14020}, {\"coin\":\"MXN\",\"asset\":\"MXN\",\"rpcport\":13970}, {\"coin\":\"MYR\",\"asset\":\"MYR\",\"rpcport\":10688}, {\"coin\":\"NOK\",\"asset\":\"NOK\",\"rpcport\":11588}, {\"coin\":\"NZD\",\"asset\":\"NZD\",\"rpcport\":10915}, {\"coin\":\"PHP\",\"asset\":\"PHP\",\"rpcport\":11181}, {\"coin\":\"PLN\",\"asset\":\"PLN\",\"rpcport\":13493}, {\"coin\":\"BRL\",\"asset\":\"BRL\",\"rpcport\":9914}, {\"coin\":\"RON\",\"asset\":\"RON\",\"rpcport\":8675}, {\"coin\":\"RUB\",\"asset\":\"RUB\",\"rpcport\":8199}, {\"coin\":\"SEK\",\"asset\":\"SEK\",\"rpcport\":11447}, {\"coin\":\"SGD\",\"asset\":\"SGD\",\"rpcport\":14475}, {\"coin\":\"THB\",\"asset\":\"THB\",\"rpcport\":11847}, {\"coin\":\"TRY\",\"asset\":\"TRY\",\"rpcport\":13924}, {\"coin\":\"USD\",\"asset\":\"USD\",\"rpcport\":13967}, {\"coin\":\"ZAR\",\"asset\":\"ZAR\",\"rpcport\":15160}]" - +export coins="[{\"coin\":\"QTUM\",\"name\":\"qtum\",\"rpcport\":3889,\"pubtype\":58,\"p2shtype\":50,\"wiftype\":128,\"txfee\":400000}, {\"coin\":\"PURA\",\"name\":\"pura\",\"rpcport\":55555,\"pubtype\":55,\"p2shtype\":16,\"wiftype\":150,\"txfee\":10000}, {\"coin\":\"DSR\",\"name\":\"desire\",\"confpath\":\"${HOME#}/.desirecore/desire.conf\",\"rpcport\":9918,\"pubtype\":30,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"MNZ\",\"asset\":\"MNZ\",\"rpcport\":14337},{\"coin\":\"BTCZ\",\"name\":\"bitcoinz\",\"rpcport\":1979,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"MAGA\",\"name\":\"magacoin\",\"rpcport\":5332,\"pubtype\":23,\"p2shtype\":50,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"BSD\",\"name\":\"bitsend\",\"rpcport\":8800,\"pubtype\":102,\"p2shtype\":5,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"IOP\",\"name\":\"IoP\",\"rpcport\":8337,\"pubtype\":117,\"p2shtype\":174,\"wiftype\":49,\"txfee\":10000}, {\"coin\":\"BLOCK\",\"name\":\"blocknetdx\",\"rpcport\":41414,\"pubtype\":26,\"p2shtype\":28,\"wiftype\":154,\"txfee\":10000}, {\"coin\":\"CHIPS\", \"name\": \"chips\", \"rpcport\":57776,\"pubtype\":60, \"p2shtype\":85, \"wiftype\":188, \"txfee\":10000}, {\"coin\":\"888\",\"name\":\"octocoin\",\"rpcport\":22888,\"pubtype\":18,\"p2shtype\":5,\"wiftype\":176,\"txfee\":2000000}, {\"coin\":\"ARG\",\"name\":\"argentum\",\"rpcport\":13581,\"pubtype\":23,\"p2shtype\":5,\"wiftype\":151,\"txfee\":50000}, {\"coin\":\"GLT\",\"name\":\"globaltoken\",\"rpcport\":9320,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":166,\"txfee\":10000}, {\"coin\":\"ZER\",\"name\":\"zero\",\"rpcport\":23801,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"HODLC\",\"name\":\"hodlcoin\",\"rpcport\":11989,\"pubtype\":40,\"p2shtype\":5,\"wiftype\":168,\"txfee\":5000}, {\"coin\":\"UIS\",\"name\":\"unitus\",\"rpcport\":50604,\"pubtype\":68,\"p2shtype\":10,\"wiftype\":132,\"txfee\":2000000}, {\"coin\":\"CRW\",\"name\":\"crown\",\"rpcport\":9341,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"HUC\",\"name\":\"huntercoin\",\"rpcport\":8399,\"pubtype\":40,\"p2shtype\":13,\"wiftype\":168,\"txfee\":100000}, {\"coin\":\"PIVX\",\"name\":\"pivx\",\"rpcport\":51473,\"pubtype\":30,\"p2shtype\":13,\"wiftype\":212,\"txfee\":10000}, {\"coin\":\"BDL\",\"name\":\"bitdeal\",\"rpcport\":9332,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"ARC\",\"name\":\"arcticcoin\",\"confpath\":\"${HOME#}/.arcticcore/arcticcoin.conf\",\"rpcport\":7208,\"pubtype\":23,\"p2shtype\":8,\"wiftype\":176,\"txfee\":10000}, {\"coin\":\"ZCL\",\"name\":\"zclassic\",\"rpcport\":8023,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"VIA\",\"name\":\"viacoin\",\"rpcport\":5222,\"pubtype\":71,\"p2shtype\":33,\"wiftype\":199,\"txfee\":100000}, {\"coin\":\"ERC\",\"name\":\"europecoin\",\"rpcport\":11989,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":168,\"txfee\":10000},{\"coin\":\"FAIR\",\"name\":\"faircoin\",\"confpath\":\"${HOME#}/.faircoin2/faircoin.conf\",\"rpcport\":40405,\"pubtype\":95,\"p2shtype\":36,\"wiftype\":223,\"txfee\":1000000}, {\"coin\":\"FLO\",\"name\":\"florincoin\",\"rpcport\":7313,\"pubtype\":35,\"p2shtype\":8,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"SXC\",\"name\":\"sexcoin\",\"rpcport\":9561,\"pubtype\":62,\"p2shtype\":5,\"wiftype\":190,\"txfee\":100000}, {\"coin\":\"CREA\",\"name\":\"creativecoin\",\"rpcport\":17711,\"pubtype\":28,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"TRC\",\"name\":\"terracoin\",\"confpath\":\"${HOME#}/.terracoincore/terracoin.conf\",\"rpcport\":13332,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"BTA\",\"name\":\"bata\",\"rpcport\":5493,\"pubtype\":25,\"p2shtype\":5,\"wiftype\":188,\"txfee\":100000}, {\"coin\":\"SMC\",\"name\":\"smartcoin\",\"rpcport\":58583,\"pubtype\":63,\"p2shtype\":5,\"wiftype\":191,\"txfee\":1000000}, {\"coin\":\"NMC\",\"name\":\"namecoin\",\"rpcport\":8336,\"pubtype\":52,\"p2shtype\":13,\"wiftype\":180,\"txfee\":100000}, {\"coin\":\"NAV\",\"name\":\"navcoin\",\"isPoS\":1,\"confpath\":\"${HOME#}/.navcoin4/navcoin.conf\",\"rpcport\":44444,\"pubtype\":53,\"p2shtype\":85,\"wiftype\":150,\"txfee\":10000}, {\"coin\":\"MOON\",\"name\":\"Mooncoin\",\"rpcport\":44663,\"pubtype\":3,\"p2shtype\":22,\"wiftype\":131,\"txfee\":100000}, {\"coin\":\"EMC2\",\"name\":\"einsteinium\",\"rpcport\":41879,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"SYS\",\"name\":\"syscoin\",\"rpcport\":8370,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"I0C\",\"name\":\"i0coin\",\"rpcport\":7332,\"pubtype\":105,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"DASH\",\"confpath\":\"${HOME#}/.dashcore/dash.conf\",\"name\":\"dashcore\",\"rpcport\":9998,\"pubtype\":76,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"STRAT\", \"name\": \"stratis\", \"active\":0, \"rpcport\":16174,\"pubtype\":63, \"p2shtype\":125, \"wiftype\":191, \"txfee\":10000}, {\"confpath\":\"${HOME#}/.muecore/mue.conf\",\"coin\":\"MUE\",\"name\":\"muecore\",\"rpcport\":29683,\"pubtype\":16,\"p2shtype\":76,\"wiftype\":126,\"txfee\":10000}, {\"coin\":\"MONA\",\"name\":\"monacoin\",\"rpcport\":9402,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"XMY\",\"name\":\"myriadcoin\",\"rpcport\":10889,\"pubtype\":50,\"p2shtype\":9,\"wiftype\":178,\"txfee\":5000}, {\"coin\":\"MAC\",\"name\":\"machinecoin\",\"rpcport\":40332,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":178,\"txfee\":50000}, {\"coin\":\"BTX\",\"name\":\"bitcore\",\"rpcport\":8556,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":50000}, {\"coin\":\"XRE\",\"name\":\"revolvercoin\",\"rpcport\":8775,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"LBC\",\"name\":\"lbrycrd\",\"rpcport\":9245,\"pubtype\":85,\"p2shtype\":122,\"wiftype\":28,\"txfee\":1000}, {\"coin\":\"SIB\",\"name\":\"sibcoin\",\"rpcport\":1944,\"pubtype\":63,\"p2shtype\":40,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"VTC\", \"name\":\"vertcoin\", \"rpcport\":5888, \"pubtype\":71, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000 }, {\"coin\":\"REVS\",\"active\":0, \"asset\":\"REVS\",\"rpcport\":10196}, {\"coin\":\"JUMBLR\",\"active\":0, \"asset\":\"JUMBLR\",\"rpcport\":15106}, {\"coin\":\"DOGE\",\"name\":\"dogecoin\",\"rpcport\":22555,\"pubtype\":30,\"p2shtype\":22,\"wiftype\":158,\"txfee\":100000000}, {\"coin\":\"HUSH\",\"name\":\"hush\",\"rpcport\":8822,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000 }, {\"active\":0,\"coin\":\"ZEC\",\"name\":\"zcash\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000 }, {\"coin\":\"DGB\",\"name\":\"digibyte\",\"rpcport\":14022,\"pubtype\":30,\"p2shtype\":5,\"wiftype\":128,\"txfee\":100000}, {\"coin\":\"ZET\", \"name\":\"zetacoin\", \"pubtype\":80, \"p2shtype\":9,\"rpcport\":8332, \"wiftype\":224, \"txfee\":10000}, {\"coin\":\"GAME\", \"rpcport\":40001, \"name\":\"gamecredits\", \"pubtype\":38, \"p2shtype\":5, \"wiftype\":166, \"txfee\":100000}, {\"coin\":\"LTC\", \"name\":\"litecoin\", \"rpcport\":9332, \"pubtype\":48, \"p2shtype\":5, \"wiftype\":176, \"txfee\":100000 }, {\"coin\":\"SUPERNET\",\"asset\":\"SUPERNET\",\"rpcport\":11341}, {\"coin\":\"WLC\",\"asset\":\"WLC\",\"rpcport\":12167}, {\"coin\":\"PANGEA\",\"asset\":\"PANGEA\",\"rpcport\":14068}, {\"coin\":\"DEX\",\"asset\":\"DEX\",\"rpcport\":11890}, {\"coin\":\"BET\",\"asset\":\"BET\",\"rpcport\":14250}, {\"coin\":\"CRYPTO\",\"asset\":\"CRYPTO\",\"rpcport\":8516}, {\"coin\":\"HODL\",\"asset\":\"HODL\",\"rpcport\":14431}, {\"coin\":\"SHARK\",\"asset\":\"SHARK\",\"rpcport\":10114}, {\"coin\":\"BOTS\",\"asset\":\"BOTS\",\"rpcport\":11964}, {\"coin\":\"MGW\",\"asset\":\"MGW\",\"rpcport\":12386}, {\"coin\":\"COQUI\",\"asset\":\"COQUI\",\"rpcport\":14276}, {\"coin\":\"KV\",\"asset\":\"KV\",\"rpcport\":8299}, {\"coin\":\"CEAL\",\"asset\":\"CEAL\",\"rpcport\":11116}, {\"coin\":\"MESH\",\"asset\":\"MESH\",\"rpcport\":9455}]" +#, {\"coin\":\"AUD\",\"asset\":\"AUD\",\"rpcport\":8045}, {\"coin\":\"BGN\",\"asset\":\"BGN\",\"rpcport\":9110}, {\"coin\":\"CAD\",\"asset\":\"CAD\",\"rpcport\":8720}, {\"coin\":\"CHF\",\"asset\":\"CHF\",\"rpcport\":15312}, {\"coin\":\"CNY\",\"asset\":\"CNY\",\"rpcport\":10384}, {\"coin\":\"CZK\",\"asset\":\"CZK\",\"rpcport\":9482}, {\"coin\":\"DKK\",\"asset\":\"DKK\",\"rpcport\":13830}, {\"coin\":\"EUR\",\"asset\":\"EUR\",\"rpcport\":8065}, {\"coin\":\"GBP\",\"asset\":\"GBP\",\"rpcport\":11505}, {\"coin\":\"HKD\",\"asset\":\"HKD\",\"rpcport\":15409}, {\"coin\":\"HRK\",\"asset\":\"HRK\",\"rpcport\":12617}, {\"coin\":\"HUF\",\"asset\":\"HUF\",\"rpcport\":13699}, {\"coin\":\"IDR\",\"asset\":\"IDR\",\"rpcport\":14459}, {\"coin\":\"ILS\",\"asset\":\"ILS\",\"rpcport\":14638}, {\"coin\":\"INR\",\"asset\":\"INR\",\"rpcport\":10536}, {\"coin\":\"JPY\",\"asset\":\"JPY\",\"rpcport\":13145}, {\"coin\":\"KRW\",\"asset\":\"KRW\",\"rpcport\":14020}, {\"coin\":\"MXN\",\"asset\":\"MXN\",\"rpcport\":13970}, {\"coin\":\"MYR\",\"asset\":\"MYR\",\"rpcport\":10688}, {\"coin\":\"NOK\",\"asset\":\"NOK\",\"rpcport\":11588}, {\"coin\":\"NZD\",\"asset\":\"NZD\",\"rpcport\":10915}, {\"coin\":\"PHP\",\"asset\":\"PHP\",\"rpcport\":11181}, {\"coin\":\"PLN\",\"asset\":\"PLN\",\"rpcport\":13493}, {\"coin\":\"BRL\",\"asset\":\"BRL\",\"rpcport\":9914}, {\"coin\":\"RON\",\"asset\":\"RON\",\"rpcport\":8675}, {\"coin\":\"RUB\",\"asset\":\"RUB\",\"rpcport\":8199}, {\"coin\":\"SEK\",\"asset\":\"SEK\",\"rpcport\":11447}, {\"coin\":\"SGD\",\"asset\":\"SGD\",\"rpcport\":14475}, {\"coin\":\"THB\",\"asset\":\"THB\",\"rpcport\":11847}, {\"coin\":\"TRY\",\"asset\":\"TRY\",\"rpcport\":13924}, {\"coin\":\"USD\",\"asset\":\"USD\",\"rpcport\":13967}, {\"coin\":\"ZAR\",\"asset\":\"ZAR\",\"rpcport\":15160}]" +#{\"coin\":\"ZEN\",\"name\":\"zen\",\"rpcport\":8231,\"pubtype\":137,\"taddr\":32,\"p2shtype\":150,\"wiftype\":128,\"txfee\":10000}, +#{\"coin\":\"BLK\",\"name\":\"blackcoin\",\"rpcport\":15715,\"pubtype\":25,\"p2shtype\":85,\"wiftype\":153,\"txfee\":10000}, diff --git a/iguana/exchanges/coins.json b/iguana/exchanges/coins.json new file mode 100644 index 000000000..320b6ccaf --- /dev/null +++ b/iguana/exchanges/coins.json @@ -0,0 +1,4 @@ +[{\"coin\":\"QTUM\",\"name\":\"qtum\",\"rpcport\":3889,\"pubtype\":58,\"p2shtype\":50,\"wiftype\":128,\"txfee\":400000}, {\"coin\":\"PURA\",\"name\":\"pura\",\"rpcport\":55555,\"pubtype\":55,\"p2shtype\":16,\"wiftype\":150,\"txfee\":10000}, {\"coin\":\"DSR\",\"name\":\"desire\",\"confpath\":\"${HOME#}/.desirecore/desire.conf\",\"rpcport\":9918,\"pubtype\":30,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"MNZ\",\"asset\":\"MNZ\",\"rpcport\":14337},{\"coin\":\"BTCZ\",\"name\":\"bitcoinz\",\"rpcport\":1979,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"MAGA\",\"name\":\"magacoin\",\"rpcport\":5332,\"pubtype\":23,\"p2shtype\":50,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"BSD\",\"name\":\"bitsend\",\"rpcport\":8800,\"pubtype\":102,\"p2shtype\":5,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"IOP\",\"name\":\"IoP\",\"rpcport\":8337,\"pubtype\":117,\"p2shtype\":174,\"wiftype\":49,\"txfee\":10000}, {\"coin\":\"BLOCK\",\"name\":\"blocknetdx\",\"rpcport\":41414,\"pubtype\":26,\"p2shtype\":28,\"wiftype\":154,\"txfee\":10000}, {\"coin\":\"CHIPS\", \"name\": \"chips\", \"rpcport\":57776,\"pubtype\":60, \"p2shtype\":85, \"wiftype\":188, \"txfee\":10000}, {\"coin\":\"888\",\"name\":\"octocoin\",\"rpcport\":22888,\"pubtype\":18,\"p2shtype\":5,\"wiftype\":176,\"txfee\":2000000}, {\"coin\":\"ARG\",\"name\":\"argentum\",\"rpcport\":13581,\"pubtype\":23,\"p2shtype\":5,\"wiftype\":151,\"txfee\":50000}, {\"coin\":\"GLT\",\"name\":\"globaltoken\",\"rpcport\":9320,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":166,\"txfee\":10000}, {\"coin\":\"ZER\",\"name\":\"zero\",\"rpcport\":23801,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"HODLC\",\"name\":\"hodlcoin\",\"rpcport\":11989,\"pubtype\":40,\"p2shtype\":5,\"wiftype\":168,\"txfee\":5000}, {\"coin\":\"UIS\",\"name\":\"unitus\",\"rpcport\":50604,\"pubtype\":68,\"p2shtype\":10,\"wiftype\":132,\"txfee\":2000000}, {\"coin\":\"CRW\",\"name\":\"crown\",\"rpcport\":9341,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"HUC\",\"name\":\"huntercoin\",\"rpcport\":8399,\"pubtype\":40,\"p2shtype\":13,\"wiftype\":168,\"txfee\":100000}, {\"coin\":\"PIVX\",\"name\":\"pivx\",\"rpcport\":51473,\"pubtype\":30,\"p2shtype\":13,\"wiftype\":212,\"txfee\":10000}, {\"coin\":\"BDL\",\"name\":\"bitdeal\",\"rpcport\":9332,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"ARC\",\"name\":\"arcticcoin\",\"confpath\":\"${HOME#}/.arcticcore/arcticcoin.conf\",\"rpcport\":7208,\"pubtype\":23,\"p2shtype\":8,\"wiftype\":176,\"txfee\":10000}, {\"coin\":\"ZCL\",\"name\":\"zclassic\",\"rpcport\":8023,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"VIA\",\"name\":\"viacoin\",\"rpcport\":5222,\"pubtype\":71,\"p2shtype\":33,\"wiftype\":199,\"txfee\":100000}, {\"coin\":\"ERC\",\"name\":\"europecoin\",\"rpcport\":11989,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":168,\"txfee\":10000},{\"coin\":\"FAIR\",\"name\":\"faircoin\",\"confpath\":\"${HOME#}/.faircoin2/faircoin.conf\",\"rpcport\":40405,\"pubtype\":95,\"p2shtype\":36,\"wiftype\":223,\"txfee\":1000000}, {\"coin\":\"FLO\",\"name\":\"florincoin\",\"rpcport\":7313,\"pubtype\":35,\"p2shtype\":8,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"SXC\",\"name\":\"sexcoin\",\"rpcport\":9561,\"pubtype\":62,\"p2shtype\":5,\"wiftype\":190,\"txfee\":100000}, {\"coin\":\"CREA\",\"name\":\"creativecoin\",\"rpcport\":17711,\"pubtype\":28,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"TRC\",\"name\":\"terracoin\",\"confpath\":\"${HOME#}/.terracoincore/terracoin.conf\",\"rpcport\":13332,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"BTA\",\"name\":\"bata\",\"rpcport\":5493,\"pubtype\":25,\"p2shtype\":5,\"wiftype\":188,\"txfee\":100000}, {\"coin\":\"SMC\",\"name\":\"smartcoin\",\"rpcport\":58583,\"pubtype\":63,\"p2shtype\":5,\"wiftype\":191,\"txfee\":1000000}, {\"coin\":\"NMC\",\"name\":\"namecoin\",\"rpcport\":8336,\"pubtype\":52,\"p2shtype\":13,\"wiftype\":180,\"txfee\":100000}, {\"coin\":\"NAV\",\"name\":\"navcoin\",\"isPoS\":1,\"confpath\":\"${HOME#}/.navcoin4/navcoin.conf\",\"rpcport\":44444,\"pubtype\":53,\"p2shtype\":85,\"wiftype\":150,\"txfee\":10000}, {\"coin\":\"MOON\",\"name\":\"Mooncoin\",\"rpcport\":44663,\"pubtype\":3,\"p2shtype\":22,\"wiftype\":131,\"txfee\":100000}, {\"coin\":\"EMC2\",\"name\":\"einsteinium\",\"rpcport\":41879,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"SYS\",\"name\":\"syscoin\",\"rpcport\":8370,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"I0C\",\"name\":\"i0coin\",\"rpcport\":7332,\"pubtype\":105,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"DASH\",\"confpath\":\"${HOME#}/.dashcore/dash.conf\",\"name\":\"dashcore\",\"rpcport\":9998,\"pubtype\":76,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"STRAT\", \"name\": \"stratis\", \"active\":0, \"rpcport\":16174,\"pubtype\":63, \"p2shtype\":125, \"wiftype\":191, \"txfee\":10000}, {\"confpath\":\"${HOME#}/.muecore/mue.conf\",\"coin\":\"MUE\",\"name\":\"muecore\",\"rpcport\":29683,\"pubtype\":16,\"p2shtype\":76,\"wiftype\":126,\"txfee\":10000}, {\"coin\":\"MONA\",\"name\":\"monacoin\",\"rpcport\":9402,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"XMY\",\"name\":\"myriadcoin\",\"rpcport\":10889,\"pubtype\":50,\"p2shtype\":9,\"wiftype\":178,\"txfee\":5000}, {\"coin\":\"MAC\",\"name\":\"machinecoin\",\"rpcport\":40332,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":178,\"txfee\":50000}, {\"coin\":\"BTX\",\"name\":\"bitcore\",\"rpcport\":8556,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":50000}, {\"coin\":\"XRE\",\"name\":\"revolvercoin\",\"rpcport\":8775,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"LBC\",\"name\":\"lbrycrd\",\"rpcport\":9245,\"pubtype\":85,\"p2shtype\":122,\"wiftype\":28,\"txfee\":1000}, {\"coin\":\"SIB\",\"name\":\"sibcoin\",\"rpcport\":1944,\"pubtype\":63,\"p2shtype\":40,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"VTC\", \"name\":\"vertcoin\", \"rpcport\":5888, \"pubtype\":71, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000 }, {\"coin\":\"REVS\",\"active\":0, \"asset\":\"REVS\",\"rpcport\":10196}, {\"coin\":\"JUMBLR\",\"active\":0, \"asset\":\"JUMBLR\",\"rpcport\":15106}, {\"coin\":\"DOGE\",\"name\":\"dogecoin\",\"rpcport\":22555,\"pubtype\":30,\"p2shtype\":22,\"wiftype\":158,\"txfee\":100000000}, {\"coin\":\"HUSH\",\"name\":\"hush\",\"rpcport\":8822,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000 }, {\"active\":0,\"coin\":\"ZEC\",\"name\":\"zcash\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000 }, {\"coin\":\"DGB\",\"name\":\"digibyte\",\"rpcport\":14022,\"pubtype\":30,\"p2shtype\":5,\"wiftype\":128,\"txfee\":100000}, {\"coin\":\"ZET\", \"name\":\"zetacoin\", \"pubtype\":80, \"p2shtype\":9,\"rpcport\":8332, \"wiftype\":224, \"txfee\":10000}, {\"coin\":\"GAME\", \"rpcport\":40001, \"name\":\"gamecredits\", \"pubtype\":38, \"p2shtype\":5, \"wiftype\":166, \"txfee\":100000}, {\"coin\":\"LTC\", \"name\":\"litecoin\", \"rpcport\":9332, \"pubtype\":48, \"p2shtype\":5, \"wiftype\":176, \"txfee\":100000 }, {\"coin\":\"SUPERNET\",\"asset\":\"SUPERNET\",\"rpcport\":11341}, {\"coin\":\"WLC\",\"asset\":\"WLC\",\"rpcport\":12167}, {\"coin\":\"PANGEA\",\"asset\":\"PANGEA\",\"rpcport\":14068}, {\"coin\":\"DEX\",\"asset\":\"DEX\",\"rpcport\":11890}, {\"coin\":\"BET\",\"asset\":\"BET\",\"rpcport\":14250}, {\"coin\":\"CRYPTO\",\"asset\":\"CRYPTO\",\"rpcport\":8516}, {\"coin\":\"HODL\",\"asset\":\"HODL\",\"rpcport\":14431}, {\"coin\":\"SHARK\",\"asset\":\"SHARK\",\"rpcport\":10114}, {\"coin\":\"BOTS\",\"asset\":\"BOTS\",\"rpcport\":11964}, {\"coin\":\"MGW\",\"asset\":\"MGW\",\"rpcport\":12386}, {\"coin\":\"COQUI\",\"asset\":\"COQUI\",\"rpcport\":14276}, {\"coin\":\"KV\",\"asset\":\"KV\",\"rpcport\":8299}, {\"coin\":\"CEAL\",\"asset\":\"CEAL\",\"rpcport\":11116}, {\"coin\":\"MESH\",\"asset\":\"MESH\",\"rpcport\":9455}]" +#, {\"coin\":\"AUD\",\"asset\":\"AUD\",\"rpcport\":8045}, {\"coin\":\"BGN\",\"asset\":\"BGN\",\"rpcport\":9110}, {\"coin\":\"CAD\",\"asset\":\"CAD\",\"rpcport\":8720}, {\"coin\":\"CHF\",\"asset\":\"CHF\",\"rpcport\":15312}, {\"coin\":\"CNY\",\"asset\":\"CNY\",\"rpcport\":10384}, {\"coin\":\"CZK\",\"asset\":\"CZK\",\"rpcport\":9482}, {\"coin\":\"DKK\",\"asset\":\"DKK\",\"rpcport\":13830}, {\"coin\":\"EUR\",\"asset\":\"EUR\",\"rpcport\":8065}, {\"coin\":\"GBP\",\"asset\":\"GBP\",\"rpcport\":11505}, {\"coin\":\"HKD\",\"asset\":\"HKD\",\"rpcport\":15409}, {\"coin\":\"HRK\",\"asset\":\"HRK\",\"rpcport\":12617}, {\"coin\":\"HUF\",\"asset\":\"HUF\",\"rpcport\":13699}, {\"coin\":\"IDR\",\"asset\":\"IDR\",\"rpcport\":14459}, {\"coin\":\"ILS\",\"asset\":\"ILS\",\"rpcport\":14638}, {\"coin\":\"INR\",\"asset\":\"INR\",\"rpcport\":10536}, {\"coin\":\"JPY\",\"asset\":\"JPY\",\"rpcport\":13145}, {\"coin\":\"KRW\",\"asset\":\"KRW\",\"rpcport\":14020}, {\"coin\":\"MXN\",\"asset\":\"MXN\",\"rpcport\":13970}, {\"coin\":\"MYR\",\"asset\":\"MYR\",\"rpcport\":10688}, {\"coin\":\"NOK\",\"asset\":\"NOK\",\"rpcport\":11588}, {\"coin\":\"NZD\",\"asset\":\"NZD\",\"rpcport\":10915}, {\"coin\":\"PHP\",\"asset\":\"PHP\",\"rpcport\":11181}, {\"coin\":\"PLN\",\"asset\":\"PLN\",\"rpcport\":13493}, {\"coin\":\"BRL\",\"asset\":\"BRL\",\"rpcport\":9914}, {\"coin\":\"RON\",\"asset\":\"RON\",\"rpcport\":8675}, {\"coin\":\"RUB\",\"asset\":\"RUB\",\"rpcport\":8199}, {\"coin\":\"SEK\",\"asset\":\"SEK\",\"rpcport\":11447}, {\"coin\":\"SGD\",\"asset\":\"SGD\",\"rpcport\":14475}, {\"coin\":\"THB\",\"asset\":\"THB\",\"rpcport\":11847}, {\"coin\":\"TRY\",\"asset\":\"TRY\",\"rpcport\":13924}, {\"coin\":\"USD\",\"asset\":\"USD\",\"rpcport\":13967}, {\"coin\":\"ZAR\",\"asset\":\"ZAR\",\"rpcport\":15160}] +#{\"coin\":\"ZEN\",\"name\":\"zen\",\"rpcport\":8231,\"pubtype\":137,\"taddr\":32,\"p2shtype\":150,\"wiftype\":128,\"txfee\":10000}, +#{\"coin\":\"BLK\",\"name\":\"blackcoin\",\"rpcport\":15715,\"pubtype\":25,\"p2shtype\":85,\"wiftype\":153,\"txfee\":10000}, diff --git a/iguana/exchanges/coinswaps b/iguana/exchanges/coinswaps new file mode 100755 index 000000000..7d87697f9 --- /dev/null +++ b/iguana/exchanges/coinswaps @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"swapstatus\",\"coin\":\"CHIPS\"}" diff --git a/iguana/exchanges/debug b/iguana/exchanges/debug index 02017001a..a4f2297a3 100755 --- a/iguana/exchanges/debug +++ b/iguana/exchanges/debug @@ -1,3 +1,4 @@ +#!/bin/bash source passphrase source coins pkill -15 marketmaker; diff --git a/iguana/exchanges/deletemessages b/iguana/exchanges/deletemessages index ad1269cd8..5aba784a4 100755 --- a/iguana/exchanges/deletemessages +++ b/iguana/exchanges/deletemessages @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"deletemessages\",\"firsti\":0,\"num\":10}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"deletemessages\",\"firsti\":0,\"num\":10}" diff --git a/iguana/exchanges/disable b/iguana/exchanges/disable index c74b84fd5..636fc952f 100755 --- a/iguana/exchanges/disable +++ b/iguana/exchanges/disable @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"disable\",\"coin\":\"REVS\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"disable\",\"coin\":\"REVS\"}" diff --git a/iguana/exchanges/dividends b/iguana/exchanges/dividends index f3dde55a0..5385b9454 100755 --- a/iguana/exchanges/dividends +++ b/iguana/exchanges/dividends @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"dividends\",\"coin\":\"KMD\",\"height\":$1,\"prefix\":\"fiat/jumblr sendtoaddress\",\"suffix\":\"\",\"dividend\":50000,\"dust\":1}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"dividends\",\"coin\":\"KMD\",\"height\":$1,\"prefix\":\"fiat/jumblr sendtoaddress\",\"suffix\":\"\",\"dividend\":50000,\"dust\":1}" diff --git a/iguana/exchanges/electrum b/iguana/exchanges/electrum new file mode 100755 index 000000000..375d3d8f4 --- /dev/null +++ b/iguana/exchanges/electrum @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"BTC\",\"ipaddr\":\"173.212.225.176\",\"port\":50001}" diff --git a/iguana/exchanges/electrum.chips b/iguana/exchanges/electrum.chips new file mode 100755 index 000000000..f5cd61e8c --- /dev/null +++ b/iguana/exchanges/electrum.chips @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"CHIPS\",\"ipaddr\":\"173.212.225.176\",\"port\":50076}" diff --git a/iguana/exchanges/electrum.chips2 b/iguana/exchanges/electrum.chips2 new file mode 100755 index 000000000..2be709e78 --- /dev/null +++ b/iguana/exchanges/electrum.chips2 @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"CHIPS\",\"ipaddr\":\"136.243.45.140\",\"port\":50076}" diff --git a/iguana/exchanges/electrum.kmd b/iguana/exchanges/electrum.kmd new file mode 100755 index 000000000..865205062 --- /dev/null +++ b/iguana/exchanges/electrum.kmd @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"KMD\",\"ipaddr\":\"96.44.166.176\",\"port\":8777}" diff --git a/iguana/exchanges/electrum.kmd2 b/iguana/exchanges/electrum.kmd2 new file mode 100755 index 000000000..40bd30c93 --- /dev/null +++ b/iguana/exchanges/electrum.kmd2 @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"KMD\",\"ipaddr\":\"173.212.225.176\",\"port\":50011}" diff --git a/iguana/exchanges/electrum.kmd3 b/iguana/exchanges/electrum.kmd3 new file mode 100755 index 000000000..4bf1a6c10 --- /dev/null +++ b/iguana/exchanges/electrum.kmd3 @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"KMD\",\"ipaddr\":\"136.243.45.140\",\"port\":50011}" diff --git a/iguana/exchanges/electrums b/iguana/exchanges/electrums new file mode 100755 index 000000000..a4cabe5e3 --- /dev/null +++ b/iguana/exchanges/electrums @@ -0,0 +1,39 @@ +#!/bin/bash +source userpass + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"REVS\",\"ipaddr\":\"173.212.225.176\",\"port\":50050}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"CHIPS\",\"ipaddr\":\"173.212.225.176\",\"port\":50076}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"ARG\",\"ipaddr\":\"173.212.225.176\",\"port\":50081}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"BTC\",\"ipaddr\":\"136.243.45.140\",\"port\":50001}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"BTC\",\"ipaddr\":\"173.212.225.176\",\"port\":50001}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"CRW\",\"ipaddr\":\"173.212.225.176\",\"port\":50041}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"DASH\",\"ipaddr\":\"173.212.225.176\",\"port\":50098}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"DGB\",\"ipaddr\":\"136.243.45.140\",\"port\":50022}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"DGB\",\"ipaddr\":\"173.212.225.176\",\"port\":50022}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"DOGE\",\"ipaddr\":\"173.212.225.176\",\"port\":50015}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"FAIR\",\"ipaddr\":\"173.212.225.176\",\"port\":50005}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"HUSH\",\"ipaddr\":\"173.212.225.176\",\"port\":50013}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"KMD\",\"ipaddr\":\"136.243.45.140\",\"port\":50011}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"KMD\",\"ipaddr\":\"173.212.225.176\",\"port\":50011}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"LTC\",\"ipaddr\":\"173.212.225.176\",\"port\":50012}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"MONA\",\"ipaddr\":\"173.212.225.176\",\"port\":50002}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"NMC\",\"ipaddr\":\"173.212.225.176\",\"port\":50036}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"VTC\",\"ipaddr\":\"173.212.225.176\",\"port\":50088}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"ZEC\",\"ipaddr\":\"173.212.225.176\",\"port\":50032}" + diff --git a/iguana/exchanges/enable b/iguana/exchanges/enable index a974c1860..90b006dfe 100755 --- a/iguana/exchanges/enable +++ b/iguana/exchanges/enable @@ -1,2 +1,5 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"BTC\"}" +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\"}" diff --git a/iguana/exchanges/getcoin b/iguana/exchanges/getcoin index 88ce8912e..b37ccc666 100755 --- a/iguana/exchanges/getcoin +++ b/iguana/exchanges/getcoin @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"getcoin\",\"coin\":\"LTC\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getcoin\",\"coin\":\"LTC\"}" diff --git a/iguana/exchanges/getcoins b/iguana/exchanges/getcoins index 132e9a9c0..64b1d7461 100755 --- a/iguana/exchanges/getcoins +++ b/iguana/exchanges/getcoins @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"getcoins\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getcoins\"}" diff --git a/iguana/exchanges/getmessages b/iguana/exchanges/getmessages index 85d246c51..121e8ec0b 100755 --- a/iguana/exchanges/getmessages +++ b/iguana/exchanges/getmessages @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"getmessages\",\"firsti\":0,\"num\":10}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getmessages\",\"firsti\":0,\"num\":10}" diff --git a/iguana/exchanges/getpeers b/iguana/exchanges/getpeers index 32852ba6a..9ed1daf77 100755 --- a/iguana/exchanges/getpeers +++ b/iguana/exchanges/getpeers @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"getpeers\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getpeers\"}" diff --git a/iguana/exchanges/getpeersIP b/iguana/exchanges/getpeersIP index feef2e5d8..7c532e609 100755 --- a/iguana/exchanges/getpeersIP +++ b/iguana/exchanges/getpeersIP @@ -1,10 +1,11 @@ -curl --url "http://5.9.253.195:7779" --data "{\"method\":\"getpeers\"}" -curl --url "http://5.9.253.196:7779" --data "{\"method\":\"getpeers\"}" -curl --url "http://5.9.253.197:7779" --data "{\"method\":\"getpeers\"}" -curl --url "http://5.9.253.198:7779" --data "{\"method\":\"getpeers\"}" -curl --url "http://5.9.253.199:7779" --data "{\"method\":\"getpeers\"}" -curl --url "http://5.9.253.200:7779" --data "{\"method\":\"getpeers\"}" -curl --url "http://5.9.253.201:7779" --data "{\"method\":\"getpeers\"}" -curl --url "http://5.9.253.202:7779" --data "{\"method\":\"getpeers\"}" -curl --url "http://5.9.253.203:7779" --data "{\"method\":\"getpeers\"}" -curl --url "http://5.9.253.204:7779" --data "{\"method\":\"getpeers\"}" +#!/bin/bash +curl --url "http://5.9.253.195:7783" --data "{\"method\":\"getpeers\"}" +curl --url "http://5.9.253.196:7783" --data "{\"method\":\"getpeers\"}" +curl --url "http://5.9.253.197:7783" --data "{\"method\":\"getpeers\"}" +curl --url "http://5.9.253.198:7783" --data "{\"method\":\"getpeers\"}" +curl --url "http://5.9.253.199:7783" --data "{\"method\":\"getpeers\"}" +curl --url "http://5.9.253.200:7783" --data "{\"method\":\"getpeers\"}" +curl --url "http://5.9.253.201:7783" --data "{\"method\":\"getpeers\"}" +curl --url "http://5.9.253.202:7783" --data "{\"method\":\"getpeers\"}" +curl --url "http://5.9.253.203:7783" --data "{\"method\":\"getpeers\"}" +curl --url "http://5.9.253.204:7783" --data "{\"method\":\"getpeers\"}" diff --git a/iguana/exchanges/getprices b/iguana/exchanges/getprices index 216b2b86c..57031035c 100755 --- a/iguana/exchanges/getprices +++ b/iguana/exchanges/getprices @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"getprices\",\"coin\":\"REVS\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprices\",\"coin\":\"REVS\"}" diff --git a/iguana/exchanges/getrawtransaction b/iguana/exchanges/getrawtransaction new file mode 100755 index 000000000..c9d042c65 --- /dev/null +++ b/iguana/exchanges/getrawtransaction @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getrawtransaction\",\"coin\":\"KMD\",\"txid\":\"107a2683abbfa9188f78e17d3bcba66ece5bd7cbe105ab5bbaae79364159e84d\"}" diff --git a/iguana/exchanges/getutxos b/iguana/exchanges/getutxos index a84c72fb0..4782c9a0a 100755 --- a/iguana/exchanges/getutxos +++ b/iguana/exchanges/getutxos @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"getutxos\",\"coin\":\"REVS\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getutxos\",\"coin\":\"REVS\"}" diff --git a/iguana/exchanges/goal b/iguana/exchanges/goal index 3fd9dee0f..74fd1fcda 100755 --- a/iguana/exchanges/goal +++ b/iguana/exchanges/goal @@ -1,4 +1,5 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"goal\",\"coin\":\"KMD\",\"val\":99}" -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"goal\",\"coin\":\"BTC\",\"val\":10}" -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"goal\",\"coin\":\"REVS\",\"val\":1}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"goal\",\"coin\":\"KMD\",\"val\":99}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"goal\",\"coin\":\"BTC\",\"val\":10}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"goal\",\"coin\":\"REVS\",\"val\":1}" diff --git a/iguana/exchanges/goals b/iguana/exchanges/goals index b9735de5f..22f31bab8 100755 --- a/iguana/exchanges/goals +++ b/iguana/exchanges/goals @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"goal\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"goal\"}" diff --git a/iguana/exchanges/guistats b/iguana/exchanges/guistats new file mode 100755 index 000000000..98384f32a --- /dev/null +++ b/iguana/exchanges/guistats @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"statsdisp\",\"starttime\":0,\"endtime\":0,\"gui\":\"buildog\"}" diff --git a/iguana/exchanges/help b/iguana/exchanges/help index a5f08aa50..a16fa1181 100755 --- a/iguana/exchanges/help +++ b/iguana/exchanges/help @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"help\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"help\"}" diff --git a/iguana/exchanges/install b/iguana/exchanges/install index 8d25f26eb..efb2c7a2e 100755 --- a/iguana/exchanges/install +++ b/iguana/exchanges/install @@ -1,4 +1,6 @@ -cp dividends snapshot goals goal portfolio autoprice deletemessages getmessages debug register registerall trade ordermatch bestfit orderbook autotrade client run_osx client_osx run coins disable enable myprice myprices getcoins getpeers getpeersIP getprices getutxos help inv setprice status utxos ../dexscripts +#!/bin/bash +cp invreset sendrawtransaction processfiles stop millis mnzservers bot_buy bot_list bot_statuslist bot_pause bot_resume bot_sell bot_settings bot_status bot_stop guistats pubkeystats pendings coinswaps baserelswaps setpassphrase notarizations getrawtransaction parselog statsdisp m_js trust trusted setconfirms balance listunspent electrum snapshot_balance snapshot_loop secretaddresses dividends snapshot goals goal portfolio autoprice deletemessages getmessages debug buy sell bestfit orderbook client run_osx client_osx run coins disable enable myprice myprices getcoins getpeers getpeersIP getprices help inv setprice status ../dexscripts +cp coins.json .. cd ../dexscripts #cp ../exchanges/passphrase ../exchanges/userpass . -echo you will need to have a passphrase file with your passphrase and userpass file with userpass value in dexscripts dir +#echo you will need to have a passphrase file with your passphrase and userpass file with userpass value in dexscripts dir diff --git a/iguana/exchanges/inv b/iguana/exchanges/inv index b0b5e52b1..a42ac5d51 100755 --- a/iguana/exchanges/inv +++ b/iguana/exchanges/inv @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"inventory\",\"coin\":\"KMD\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"inventory\",\"coin\":\"REVS\"}" diff --git a/iguana/exchanges/invreset b/iguana/exchanges/invreset new file mode 100755 index 000000000..0304c7503 --- /dev/null +++ b/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\"}" diff --git a/iguana/exchanges/listunspent b/iguana/exchanges/listunspent new file mode 100755 index 000000000..127397d9c --- /dev/null +++ b/iguana/exchanges/listunspent @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"listunspent\",\"coin\":\"CHIPS\",\"address\":\"RMfQwu5ey23eWJ4as2ckd8dqsQJwo836ny\"}" diff --git a/iguana/exchanges/loop b/iguana/exchanges/loop index 8703827ba..2ad08f45b 100755 --- a/iguana/exchanges/loop +++ b/iguana/exchanges/loop @@ -1,7 +1,8 @@ +#!/bin/bash while true do source userpass -#curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"setprice\",\"base\":\"REVS\",\"rel\":\"KMD\",\"price\":1.234}" +#curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"setprice\",\"base\":\"REVS\",\"rel\":\"KMD\",\"price\":1.234}" ./s sleep 3600 done diff --git a/iguana/exchanges/m_js b/iguana/exchanges/m_js new file mode 100755 index 000000000..37e18a0c5 --- /dev/null +++ b/iguana/exchanges/m_js @@ -0,0 +1,4 @@ +#!/bin/sh +cd .. +make -f exchanges/Makefile + diff --git a/iguana/exchanges/message b/iguana/exchanges/message index 701f63049..f36c45c81 100755 --- a/iguana/exchanges/message +++ b/iguana/exchanges/message @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"$1\",\"method\":\"sendmessage\",\"message\":\"some sort of message\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"$1\",\"method\":\"sendmessage\",\"message\":\"some sort of message\"}" diff --git a/iguana/exchanges/millis b/iguana/exchanges/millis new file mode 100755 index 000000000..025f581cd --- /dev/null +++ b/iguana/exchanges/millis @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"millis\"}" diff --git a/iguana/exchanges/mm.c b/iguana/exchanges/mm.c index 91b2df3dc..a87481f15 100644 --- a/iguana/exchanges/mm.c +++ b/iguana/exchanges/mm.c @@ -19,17 +19,29 @@ // Copyright © 2017 SuperNET. All rights reserved. // + + +void PNACL_message(char *arg,...) +{ + +} #define FROM_MARKETMAKER + #include #include +#ifndef NATIVE_WINDOWS #include "OS_portable.h" +#else +#include "../../crypto777/OS_portable.h" +#endif // !_WIN_32 + #define MAX(a,b) ((a) > (b) ? (a) : (b)) char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *remoteaddr,uint16_t port); #include "stats.c" void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32]); //defined(__APPLE__) || -#if defined(WIN32) || defined(USE_STATIC_NANOMSG) +#ifdef FROM_JS // defined(WIN32) || defined(USE_STATIC_NANOMSG) #include "../../crypto777/nanosrc/nn.h" #include "../../crypto777/nanosrc/bus.h" #include "../../crypto777/nanosrc/pubsub.h" @@ -38,13 +50,23 @@ void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveas #include "../../crypto777/nanosrc/tcp.h" #include "../../crypto777/nanosrc/pair.h" #else -#include "/usr/local/include/nanomsg/nn.h" -#include "/usr/local/include/nanomsg/bus.h" -#include "/usr/local/include/nanomsg/pubsub.h" -#include "/usr/local/include/nanomsg/pipeline.h" -#include "/usr/local/include/nanomsg/reqrep.h" -#include "/usr/local/include/nanomsg/tcp.h" -#include "/usr/local/include/nanomsg/pair.h" +#if defined(WIN32) || defined(USE_STATIC_NANOMSG) + #include "../../crypto777/nanosrc/nn.h" + #include "../../crypto777/nanosrc/bus.h" + #include "../../crypto777/nanosrc/pubsub.h" + #include "../../crypto777/nanosrc/pipeline.h" + #include "../../crypto777/nanosrc/reqrep.h" + #include "../../crypto777/nanosrc/tcp.h" + #include "../../crypto777/nanosrc/pair.h" +#else + #include "/usr/local/include/nanomsg/nn.h" + #include "/usr/local/include/nanomsg/bus.h" + #include "/usr/local/include/nanomsg/pubsub.h" + #include "/usr/local/include/nanomsg/pipeline.h" + #include "/usr/local/include/nanomsg/reqrep.h" + #include "/usr/local/include/nanomsg/tcp.h" + #include "/usr/local/include/nanomsg/pair.h" +#endif #endif char DEX_baseaddr[64],DEX_reladdr[64]; @@ -54,7 +76,7 @@ struct mmpending_order int32_t dir; uint32_t pending,completed,canceled,cancelstarted,reported; cJSON *errorjson; - char exchange[16],base[16],rel[16],orderid[64]; + char exchange[16],base[65],rel[65],orderid[64]; } *Pending_orders; int32_t Num_Pending; @@ -395,7 +417,7 @@ void marketmaker_pendingupdate(char *exchange,char *base,char *rel) void marketmaker_pendinginit(char *exchange,char *base,char *rel) { - char *retstr,*orderid,*pairstr,relbase[64]; cJSON *retjson,*array,*item; int32_t i,j,n,dir; struct mmpending_order *ptr; + char *retstr,*orderid,*pairstr,relbase[65]; cJSON *retjson,*array,*item; int32_t i,j,n,dir; struct mmpending_order *ptr; sprintf(relbase,"%s-%s",rel,base); if ( (retstr= DEX_openorders(exchange)) != 0 ) { @@ -784,26 +806,98 @@ void marketmaker(double minask,double maxbid,char *baseaddr,char *reladdr,double #include "LP_nativeDEX.c" +/*MERK d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a ht.518777 -> {"pos":1,"merkle":["526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8", "f68b03a7b6e418c9b306d8d8b21917ae5a584696f9b0b8cb0741733d7097fdfd"],"block_height":518777} root.(0000000000000000000000000000000000000000000000000000000000000000) + MERK c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543 ht.518777 -> {"pos":2,"merkle":["fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501", "8c116e974c842ad3ad8b3ddbd71da3debb150e3fe692f5bd628381bc167311a7"],"block_height":518777} root.(0000000000000000000000000000000000000000000000000000000000000000)*/ +/*526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8 +d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a +c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543 +fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501*/ + +/*0: 526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8 +1: d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a +2: c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543 +3: fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501 +4: 8c116e974c842ad3ad8b3ddbd71da3debb150e3fe692f5bd628381bc167311a7 +5: f68b03a7b6e418c9b306d8d8b21917ae5a584696f9b0b8cb0741733d7097fdfd +6: a87ee259560f20b20182760c0e7cc7896d44381f0ad58a2e755a2b6b895b01ec*/ + +/* +0 1 2 3 + 4 5 + 6 + +1 -> [0, 5] +2 -> [3, 4] + +if odd -> right, else left +then /= 2 +*/ + +/*void testmerk() +{ + bits256 tree[256],roothash,txid; int32_t i; char str[65]; + memset(tree,0,sizeof(tree)); + decode_hex(tree[0].bytes,32,"526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8"); + decode_hex(tree[1].bytes,32,"d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a"); + decode_hex(tree[2].bytes,32,"c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543"); + decode_hex(tree[3].bytes,32,"fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501"); + roothash = iguana_merkle(tree,4); + for (i=0; i<256; i++) + { + if ( bits256_nonz(tree[i]) == 0 ) + break; + printf("%d: %s\n",i,bits256_str(str,tree[i])); + } + memset(tree,0,sizeof(tree)); + decode_hex(tree[0].bytes,32,"526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8"); + decode_hex(tree[1].bytes,32,"f68b03a7b6e418c9b306d8d8b21917ae5a584696f9b0b8cb0741733d7097fdfd"); + decode_hex(txid.bytes,32,"d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a"); + roothash = validate_merkle(1,txid,tree,2); + printf("validate 1: %s\n",bits256_str(str,roothash)); + memset(tree,0,sizeof(tree)); + decode_hex(tree[0].bytes,32,"fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501"); + decode_hex(tree[1].bytes,32,"8c116e974c842ad3ad8b3ddbd71da3debb150e3fe692f5bd628381bc167311a7"); + decode_hex(txid.bytes,32,"c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543"); + roothash = validate_merkle(2,txid,tree,2); + printf("validate 2: %s\n",bits256_str(str,roothash)); +}*/ + void LP_main(void *ptr) { - char *passphrase; double profitmargin; cJSON *argjson = ptr; + char *passphrase; double profitmargin; uint16_t port; cJSON *argjson = ptr; if ( (passphrase= jstr(argjson,"passphrase")) != 0 ) { profitmargin = jdouble(argjson,"profitmargin"); LP_profitratio += profitmargin; - LPinit(7779,7780,7781,7782,passphrase,jint(argjson,"client"),jstr(argjson,"userhome"),argjson); + if ( (port= juint(argjson,"rpcport")) < 1000 ) + port = LP_RPCPORT; + LPinit(port,LP_RPCPORT+10,LP_RPCPORT+20,LP_RPCPORT+30,passphrase,jint(argjson,"client"),jstr(argjson,"userhome"),argjson); } } int main(int argc, const char * argv[]) { - char dirname[512],*base,*rel,*name,*exchange,*apikey,*apisecret,*blocktrail,*retstr,*baseaddr,*reladdr,*passphrase; + char dirname[512],*base,*rel,*name,*exchange,*apikey,*apisecret,*blocktrail,*retstr,*baseaddr,*reladdr,*passphrase; double profitmargin,maxexposure,incrratio,start_rel,start_base,minask,maxbid,incr; cJSON *retjson,*loginjson; int32_t i; OS_init(); sprintf(dirname,"%s",GLOBAL_DBDIR), OS_ensure_directory(dirname); sprintf(dirname,"%s/SWAPS",GLOBAL_DBDIR), OS_ensure_directory(dirname); sprintf(dirname,"%s/PRICES",GLOBAL_DBDIR), OS_ensure_directory(dirname); + sprintf(dirname,"%s/UNSPENTS",GLOBAL_DBDIR), OS_ensure_directory(dirname); +#ifdef FROM_JS + argc = 2; + retjson = cJSON_Parse("{\"client\":1,\"passphrase\":\"test\"}"); + printf("calling LP_main(%s)\n",jprint(retjson,0)); + LP_main(retjson); + emscripten_set_main_loop(LP_fromjs_iter,1,0); +#else + if ( argc == 1 ) + { + LP_NXT_redeems(); + sleep(3); + return(0); + } if ( argc > 1 && (retjson= cJSON_Parse(argv[1])) != 0 ) { if ( (passphrase= jstr(retjson,"passphrase")) == 0 ) @@ -812,10 +906,10 @@ int main(int argc, const char * argv[]) { printf("error launching LP_main (%s)\n",jprint(retjson,0)); exit(-1); - } else printf("(%s) launched.(%s)\n",argv[1],passphrase); + } //else printf("(%s) launched.(%s)\n",argv[1],passphrase); incr = 100.; - while ( 1 ) - sleep(1); + while ( (1) ) + sleep(100000); profitmargin = jdouble(retjson,"profitmargin"); minask = jdouble(retjson,"minask"); maxbid = jdouble(retjson,"maxbid"); @@ -875,5 +969,6 @@ int main(int argc, const char * argv[]) } free_json(retjson); } +#endif return 0; } diff --git a/iguana/exchanges/mnzservers b/iguana/exchanges/mnzservers new file mode 100755 index 000000000..40f904b49 --- /dev/null +++ b/iguana/exchanges/mnzservers @@ -0,0 +1,12 @@ +#!/bin/bash +source userpass + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"b4a6361506d847817205a8e51374eb129fc33c3b5466235afdbc65f2291ffb4c\",\"method\":\"trust\",\"trust\":1}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"bd0c69da4ec3ed61613734f9f681f846fde5d8efc894c82dafbeeb7a01844872\",\"method\":\"trust\",\"trust\":1}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"8f7782b532808a30a1fe6ffc1fa3c55fea6d734f000763fa88d42ccfed60d213\",\"method\":\"trust\",\"trust\":1}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"d80a74847cd60899afdd673570f8b698e4089e5ad4d6e9e205b5e5891ec0c84f\",\"method\":\"trust\",\"trust\":1}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"322e236db07484b31aea9400a6f3f5ed972e29c6d4115c63aaedaa541d41e758\",\"method\":\"trust\",\"trust\":1}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"8579b74435093690d3d7680ecdac0dd1b892dc5ecd4fb603f0e22fd003176342\",\"method\":\"trust\",\"trust\":1}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"c4e3c95bd9612cce3fe1cfcc0a0e9c625bab7e4b83bc68f0ede73633e6a8c17f\",\"method\":\"trust\",\"trust\":1}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"43467b51e07fae3b19101fca7fe1bf250d34c8deecfd493c723f87d5eda1a64b\",\"method\":\"trust\",\"trust\":1}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"e900c42a0d883d098f382b59cf5655dd1d92b2c94f6580095a4f6382514f7a59\",\"method\":\"trust\",\"trust\":1}" diff --git a/iguana/exchanges/myprice b/iguana/exchanges/myprice index cdb93dabc..6dfac2dbb 100755 --- a/iguana/exchanges/myprice +++ b/iguana/exchanges/myprice @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"myprice\",\"base\":\"REVS\",\"rel\":\"KMD\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"myprice\",\"base\":\"REVS\",\"rel\":\"KMD\"}" diff --git a/iguana/exchanges/myprices b/iguana/exchanges/myprices index 7333d682b..1c82512c0 100755 --- a/iguana/exchanges/myprices +++ b/iguana/exchanges/myprices @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"myprices\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"myprices\"}" diff --git a/iguana/exchanges/nodeinstall b/iguana/exchanges/nodeinstall new file mode 100644 index 000000000..737de1e99 --- /dev/null +++ b/iguana/exchanges/nodeinstall @@ -0,0 +1,16 @@ +cd /var/www/html/ +node install http-server -g + +#start http-server to start current directory serving via http://127.0.0.1:8080 +http-server . + +node install node-nanomsg + +# test.js +#var nano = require('nanomsg'); +#var sub = nano.socket('sub'); +#var addr = 'ws://5.9.253.197:7785' +#sub.connect(addr); +#sub.on('data', function (buf) { +#console.log(String(buf)); +#}); diff --git a/iguana/exchanges/notarizations b/iguana/exchanges/notarizations new file mode 100755 index 000000000..9484aa5e0 --- /dev/null +++ b/iguana/exchanges/notarizations @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"notarizations\",\"coin\":\"$1\"}" diff --git a/iguana/exchanges/numutxos b/iguana/exchanges/numutxos index b20de95fc..9455dd239 100755 --- a/iguana/exchanges/numutxos +++ b/iguana/exchanges/numutxos @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"numutxos\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"numutxos\"}" diff --git a/iguana/exchanges/orderbook b/iguana/exchanges/orderbook index 3ec8ffbdf..a61784991 100755 --- a/iguana/exchanges/orderbook +++ b/iguana/exchanges/orderbook @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"orderbook\",\"base\":\"JUMBLR\",\"rel\":\"KMD\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"orderbook\",\"base\":\"REVS\",\"rel\":\"KMD\"}" diff --git a/iguana/exchanges/ordermatch b/iguana/exchanges/ordermatch index 05d30ba7e..f4b2ca61c 100755 --- a/iguana/exchanges/ordermatch +++ b/iguana/exchanges/ordermatch @@ -1,3 +1,4 @@ +#!/bin/bash source userpass #ordermatch(base, txfee=0, rel, desttxfee=0, price, txid, vout, feetxid, feevout, duration=3600)\n\ -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"ordermatch\",\"base\":\"REVS\",\"rel\":\"KMD\",\"price\":1.234,\"duration\":600,\"txfee\":0,\"desttxfee\":0,\"txid\":\"$1\",\"vout\":$2,\"feetxid\":\"$3\",\"feevout\":$4}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"ordermatch\",\"base\":\"REVS\",\"rel\":\"KMD\",\"price\":1.234,\"duration\":600,\"txfee\":0,\"desttxfee\":0,\"txid\":\"$1\",\"vout\":$2,\"feetxid\":\"$3\",\"feevout\":$4}" diff --git a/iguana/exchanges/parselog b/iguana/exchanges/parselog new file mode 100755 index 000000000..c594944e9 --- /dev/null +++ b/iguana/exchanges/parselog @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"parselog\"}" diff --git a/iguana/exchanges/pendings b/iguana/exchanges/pendings new file mode 100755 index 000000000..a2aa46c83 --- /dev/null +++ b/iguana/exchanges/pendings @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"statsdisp\",\"starttime\":2000000000,\"endtime\":2000000000}" diff --git a/iguana/exchanges/portfolio b/iguana/exchanges/portfolio index 2265e0fc2..b22adbc06 100755 --- a/iguana/exchanges/portfolio +++ b/iguana/exchanges/portfolio @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"portfolio\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"portfolio\"}" diff --git a/iguana/exchanges/pricearray b/iguana/exchanges/pricearray index 8a01248af..dc812dba6 100755 --- a/iguana/exchanges/pricearray +++ b/iguana/exchanges/pricearray @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"pricearray\",\"base\":\"KMD\",\"rel\":\"BTC\",\"timescale\":60}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"pricearray\",\"base\":\"KMD\",\"rel\":\"BTC\",\"timescale\":60}" diff --git a/iguana/exchanges/processfiles b/iguana/exchanges/processfiles new file mode 100755 index 000000000..9404f967a --- /dev/null +++ b/iguana/exchanges/processfiles @@ -0,0 +1,3 @@ +ls -l /proc/$1/fd +echo sockstat +cat /proc/$1/net/sockstat diff --git a/iguana/exchanges/profile b/iguana/exchanges/profile new file mode 100755 index 000000000..50c1df851 --- /dev/null +++ b/iguana/exchanges/profile @@ -0,0 +1 @@ +gprof -b ../marketmaker ../gmon.out diff --git a/iguana/exchanges/pub b/iguana/exchanges/pub index edafc5b98..2e3241fee 100755 --- a/iguana/exchanges/pub +++ b/iguana/exchanges/pub @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"6578099f6474d9b8bd66a7a136b922029a989818ec0309aee962dd6ac1862b74\",\"method\":\"forward\",\"method2\":\"publish\",\"data\":\"nonsense\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"6578099f6474d9b8bd66a7a136b922029a989818ec0309aee962dd6ac1862b74\",\"method\":\"forward\",\"method2\":\"publish\",\"data\":\"nonsense\"}" diff --git a/iguana/exchanges/pubkeystats b/iguana/exchanges/pubkeystats new file mode 100755 index 000000000..6897c0a51 --- /dev/null +++ b/iguana/exchanges/pubkeystats @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"statsdisp\",\"starttime\":0,\"endtime\":0,\"pubkey\":\"a2593155464e37fcc88245780240a412a38cf3d316809445aad73f4e7789187d\"}" diff --git a/iguana/exchanges/recentswaps b/iguana/exchanges/recentswaps new file mode 100755 index 000000000..d24b99840 --- /dev/null +++ b/iguana/exchanges/recentswaps @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"recentswaps\",\"limit\":1}" diff --git a/iguana/exchanges/register b/iguana/exchanges/register deleted file mode 100755 index bbe660faa..000000000 --- a/iguana/exchanges/register +++ /dev/null @@ -1,2 +0,0 @@ -source userpass -curl --url "http://5.9.253.195:7779" --data "{\"userpass\":\"9bb4846d24136fc7c33515e45bccbab5c8fb7b57b411aa20057b371da9358255\",\"agent\":\"stats\",\"method\":\"register\",\"client\":\"6d3332be4904feafd326609bd76b66528dc7b2e2d75a7bd110c6bf8d19c4cf58\",\"pushaddr\":\"5.9.253.195\",\"pushport\":\"10000\"}" diff --git a/iguana/exchanges/registerall b/iguana/exchanges/registerall deleted file mode 100755 index 9024b8230..000000000 --- a/iguana/exchanges/registerall +++ /dev/null @@ -1,3 +0,0 @@ - -source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"registerall\",\"numnodes\":10}" diff --git a/iguana/exchanges/run b/iguana/exchanges/run index 59e4ec2e4..ec549c0c7 100755 --- a/iguana/exchanges/run +++ b/iguana/exchanges/run @@ -1,3 +1,4 @@ +#!/bin/bash source passphrase source coins pkill -15 marketmaker; diff --git a/iguana/exchanges/run_osx b/iguana/exchanges/run_osx index c8924d6f4..970217843 100755 --- a/iguana/exchanges/run_osx +++ b/iguana/exchanges/run_osx @@ -1,3 +1,4 @@ +#!/bin/bash source passphrase source coins pkill -15 marketmaker; diff --git a/iguana/exchanges/secretaddresses b/iguana/exchanges/secretaddresses new file mode 100755 index 000000000..29ebd0041 --- /dev/null +++ b/iguana/exchanges/secretaddresses @@ -0,0 +1,6 @@ +#!/bin/bash +source userpass +echo "usage: ./secretaddresses 'passphrase'" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"secretaddresses\",\"num\":16,\"passphrase\":\"$1\"}" + diff --git a/iguana/exchanges/sell b/iguana/exchanges/sell new file mode 100755 index 000000000..a48ffaac1 --- /dev/null +++ b/iguana/exchanges/sell @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"sell\",\"base\":\"KMD\",\"rel\":\"BTC\",\"basevolume\":10.0\",\"price\":0.0005}" diff --git a/iguana/exchanges/sendrawtransaction b/iguana/exchanges/sendrawtransaction new file mode 100755 index 000000000..c3c2b09a0 --- /dev/null +++ b/iguana/exchanges/sendrawtransaction @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"sendrawtransaction\",\"coin\":\"KMD\",\"signedtx\":\"$1\"}" diff --git a/iguana/exchanges/setconfirms b/iguana/exchanges/setconfirms new file mode 100755 index 000000000..78905f158 --- /dev/null +++ b/iguana/exchanges/setconfirms @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"setconfirms\",\"coin\":\"REVS\",\"numconfirms\":1}" diff --git a/iguana/exchanges/setpassphrase b/iguana/exchanges/setpassphrase new file mode 100755 index 000000000..eec8bc5b1 --- /dev/null +++ b/iguana/exchanges/setpassphrase @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"passphrase\",\"passphrase\":\"put the passphrase here\",\"gui\":\"buildog\"}" diff --git a/iguana/exchanges/setprice b/iguana/exchanges/setprice index e5a9c3c9c..40b88e0a5 100755 --- a/iguana/exchanges/setprice +++ b/iguana/exchanges/setprice @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"setprice\",\"base\":\"REVS\",\"rel\":\"KMD\",\"price\":1.234}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"setprice\",\"base\":\"REVS\",\"rel\":\"KMD\",\"price\":1.234}" diff --git a/iguana/exchanges/snapshot b/iguana/exchanges/snapshot index 2b875af59..75a0a60aa 100755 --- a/iguana/exchanges/snapshot +++ b/iguana/exchanges/snapshot @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"snapshot\",\"coin\":\"KMD\",\"height\":$1}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"snapshot\",\"coin\":\"KMD\",\"height\":$1}" diff --git a/iguana/exchanges/snapshot_balance b/iguana/exchanges/snapshot_balance new file mode 100644 index 000000000..b66f1a9e4 --- /dev/null +++ b/iguana/exchanges/snapshot_balance @@ -0,0 +1,5 @@ +#!/bin/bash +source userpass +ht=$1 +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"snapshot_balance\",\"coin\":\"KMD\",\"height\":$ht,\"addresses\":[\"RSAzPFzgTZHNcxLNLdGyVPbjbMA8PRY7Ss\", \"RBgD5eMGwZppid4x7PTEC2Wg1AzvxbsQqB\"]}" + diff --git a/iguana/exchanges/snapshot_loop b/iguana/exchanges/snapshot_loop new file mode 100755 index 000000000..05bedaa82 --- /dev/null +++ b/iguana/exchanges/snapshot_loop @@ -0,0 +1,12 @@ +#!/bin/bash +source userpass +ht=$1 +while true +do +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"snapshot\",\"coin\":\"KMD\",\"height\":$ht}" +#ht=`komodo-cli getinfo | jq .blocks` +ht=$(( $ht + 1000 )) +echo next height $ht +sleep 1 +done + diff --git a/iguana/exchanges/stats.c b/iguana/exchanges/stats.c index 3c98b48f5..681da52d2 100644 --- a/iguana/exchanges/stats.c +++ b/iguana/exchanges/stats.c @@ -19,6 +19,8 @@ // Copyright © 2017 SuperNET. All rights reserved. // + + #include #include #include "../../crypto777/OS_portable.h" @@ -28,7 +30,25 @@ #include "DEXstats.h" char *stats_JSON(void *ctx,char *myipaddr,int32_t mypubsock,cJSON *argjson,char *remoteaddr,uint16_t port); -#ifndef WIN32 +char *stats_validmethods[] = +{ + "psock", "getprices", "notify", "getpeers", // from issue_ "uitem", "listunspent", + "orderbook", "help", "getcoins", "pricearray", "balance", "tradestatus" +}; + +int32_t LP_valid_remotemethod(cJSON *argjson) +{ + char *method; int32_t i; + if ( (method= jstr(argjson,"method")) != 0 ) + { + for (i=0; i= 0 ) @@ -325,11 +346,7 @@ char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *po j = i = 0; filetype[0] = 0; //printf("url.(%s) method.(%s)\n",&url[i],urlmethod); -#ifdef __PNACL__ - snprintf(furl,sizeof(furl),"%s/%s",GLOBAL_DBDIR,url+1); -#else snprintf(furl,sizeof(furl),"%s",url+1); -#endif if ( strcmp(&url[i],"/") == 0 && strcmp(urlmethod,"GET") == 0 ) { *jsonflagp = 1; @@ -337,7 +354,7 @@ char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *po return(clonestr("{\"error\":\"cant find index7779\"}")); else return(filestr); } - else if ( (filestr= OS_filestr(&filesize,furl)) != 0 ) + /*else if ( (filestr= OS_filestr(&filesize,furl)) != 0 ) allows arbitrary file access! { *jsonflagp = 1; for (i=(int32_t)strlen(url)-1; i>0; i--) @@ -347,7 +364,7 @@ char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *po strcpy(filetype,url+i+1); //printf("return filetype.(%s) size.%ld\n",filetype,filesize); return(filestr); - } + }*/ if ( strncmp(&url[i],"/api",strlen("/api")) == 0 ) { *jsonflagp = 1; @@ -494,13 +511,25 @@ char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *po if ( userpass != 0 && jstr(argjson,"userpass") == 0 ) jaddstr(argjson,"userpass",userpass); //printf("after urlconv.(%s) argjson.(%s)\n",jprint(json,0),jprint(argjson,0)); +#ifdef FROM_MARKETMAKER + if ( strcmp(remoteaddr,"127.0.0.1") == 0 || LP_valid_remotemethod(argjson) > 0 ) + { + if ( (retstr= stats_JSON(ctx,myipaddr,-1,argjson,remoteaddr,port)) != 0 ) + { + if ( (retitem= cJSON_Parse(retstr)) != 0 ) + jaddi(retarray,retitem); + free(retstr); + } + } else retstr = clonestr("{\"error\":\"invalid remote method\"}"); +#else if ( (retstr= stats_JSON(ctx,myipaddr,-1,argjson,remoteaddr,port)) != 0 ) { if ( (retitem= cJSON_Parse(retstr)) != 0 ) jaddi(retarray,retitem); free(retstr); } - //printf("(%s) {%s} -> (%s) postflag.%d (%s)\n",urlstr,jprint(argjson,0),cJSON_Print(json),*postflagp,retstr); +#endif + //printf("(%s) {%s} -> (%s) postflag.%d (%s)\n",urlstr,jprint(argjson,0),jprint(json,0),*postflagp,retstr); } free_json(origargjson); retstr = jprint(retarray,1); @@ -517,7 +546,13 @@ char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *po //printf("ARGJSON.(%s)\n",jprint(arg,0)); if ( userpass != 0 && jstr(arg,"userpass") == 0 ) jaddstr(arg,"userpass",userpass); +#ifdef FROM_MARKETMAKER + if ( strcmp(remoteaddr,"127.0.0.1") == 0 || LP_valid_remotemethod(arg) > 0 ) + retstr = stats_JSON(ctx,myipaddr,-1,arg,remoteaddr,port); + else retstr = clonestr("{\"error\":\"invalid remote method\"}"); +#else retstr = stats_JSON(ctx,myipaddr,-1,arg,remoteaddr,port); +#endif } free_json(argjson); free_json(json); @@ -553,163 +588,242 @@ int32_t iguana_getheadersize(char *buf,int32_t recvlen) return(recvlen); } -void stats_rpcloop(void *args) +uint16_t RPC_port; +extern portable_mutex_t LP_commandmutex,LP_gcmutex; +extern struct rpcrequest_info *LP_garbage_collector; + +void LP_rpc_processreq(void *_ptr) { - static char *jsonbuf; - uint16_t port; char filetype[128],content_type[128]; - int32_t recvlen,flag,bindsock,postflag=0,contentlen,sock,remains,numsent,jsonflag=0,hdrsize,len; - socklen_t clilen; char helpname[512],remoteaddr[64],*buf,*retstr,*space; - struct sockaddr_in cli_addr; uint32_t ipbits,i,size = 32*IGUANA_MAXPACKETSIZE + 512; - if ( (port= *(uint16_t *)args) == 0 ) - port = 7779; - if ( jsonbuf == 0 ) - jsonbuf = calloc(1,IGUANA_MAXPACKETSIZE); - while ( (bindsock= iguana_socket(1,"0.0.0.0",port)) < 0 ) + static uint32_t spawned,maxspawned; + char filetype[128],content_type[128]; + int32_t recvlen,flag,postflag=0,contentlen,remains,sock,numsent,jsonflag=0,hdrsize,len; + char helpname[512],remoteaddr[64],*buf,*retstr,*space,*jsonbuf; struct rpcrequest_info *req = _ptr; + uint32_t ipbits,i,size = IGUANA_MAXPACKETSIZE + 512; + ipbits = req->ipbits;; + expand_ipbits(remoteaddr,ipbits); + sock = req->sock; + recvlen = flag = 0; + retstr = 0; + space = calloc(1,size); + jsonbuf = calloc(1,size); + remains = size-1; + buf = jsonbuf; + spawned++; + if ( spawned > maxspawned ) { - //if ( coin->MAXPEERS == 1 ) - // break; - //exit(-1); - sleep(3); + printf("max rpc threads spawned and alive %d <- %d\n",maxspawned,spawned); + maxspawned = spawned; } - printf(">>>>>>>>>> DEX stats 127.0.0.1:%d bind sock.%d DEX stats API enabled <<<<<<<<<\n",port,bindsock); - space = calloc(1,size); - while ( bindsock >= 0 ) + while ( remains > 0 ) { - clilen = sizeof(cli_addr); - sock = accept(bindsock,(struct sockaddr *)&cli_addr,&clilen); - if ( sock < 0 ) - { - //printf("iguana_rpcloop ERROR on accept usock.%d errno %d %s\n",sock,errno,strerror(errno)); - continue; - } - memcpy(&ipbits,&cli_addr.sin_addr.s_addr,sizeof(ipbits)); - expand_ipbits(remoteaddr,ipbits); - //printf("remote RPC request from (%s) %x\n",remoteaddr,ipbits); - - memset(jsonbuf,0,IGUANA_MAXPACKETSIZE); - remains = (int32_t)(IGUANA_MAXPACKETSIZE - 1); - buf = jsonbuf; - recvlen = flag = 0; - retstr = 0; - while ( remains > 0 ) + //printf("flag.%d remains.%d recvlen.%d\n",flag,remains,recvlen); + if ( (len= (int32_t)recv(sock,buf,remains,0)) < 0 ) { - //printf("flag.%d remains.%d recvlen.%d\n",flag,remains,recvlen); - if ( (len= (int32_t)recv(sock,buf,remains,0)) < 0 ) + if ( errno == EAGAIN ) { - if ( errno == EAGAIN ) - { - printf("EAGAIN for len %d, remains.%d\n",len,remains); - usleep(10000); - } - break; + printf("EAGAIN for len %d, remains.%d\n",len,remains); + usleep(10000); } - else + break; + } + else + { + if ( len > 0 ) { - if ( len > 0 ) + buf[len] = 0; + if ( recvlen == 0 ) { - buf[len] = 0; - if ( recvlen == 0 ) + if ( (contentlen= iguana_getcontentlen(buf,recvlen)) > 0 ) { - if ( (contentlen= iguana_getcontentlen(buf,recvlen)) > 0 ) + hdrsize = iguana_getheadersize(buf,recvlen); + if ( hdrsize > 0 ) { - hdrsize = iguana_getheadersize(buf,recvlen); - if ( hdrsize > 0 ) + if ( len < (hdrsize + contentlen) ) { - if ( len < (hdrsize + contentlen) ) - { - remains = (hdrsize + contentlen) - len; - buf = &buf[len]; - flag = 1; - //printf("got.(%s) %d remains.%d of len.%d contentlen.%d hdrsize.%d remains.%d\n",buf,recvlen,remains,len,contentlen,hdrsize,(hdrsize+contentlen)-len); - continue; - } + remains = (hdrsize + contentlen) - len; + buf = &buf[len]; + flag = 1; + //printf("got.(%s) %d remains.%d of len.%d contentlen.%d hdrsize.%d remains.%d\n",buf,recvlen,remains,len,contentlen,hdrsize,(hdrsize+contentlen)-len); + continue; } } } - recvlen += len; - remains -= len; - buf = &buf[len]; - if ( flag == 0 || remains <= 0 ) - break; - } - else - { - usleep(10000); - //printf("got.(%s) %d remains.%d of total.%d\n",jsonbuf,recvlen,remains,len); - //retstr = iguana_rpcparse(space,size,&postflag,jsonbuf); - if ( flag == 0 ) - break; } + recvlen += len; + remains -= len; + buf = &buf[len]; + if ( flag == 0 || remains <= 0 ) + break; + } + else + { + usleep(10000); + printf("got.(%s) %d remains.%d of total.%d\n",jsonbuf,recvlen,remains,len); + if ( flag == 0 ) + break; } } - content_type[0] = 0; - if ( recvlen > 0 ) + } + content_type[0] = 0; + if ( recvlen > 0 ) + { + jsonflag = postflag = 0; + portable_mutex_lock(&LP_commandmutex); + retstr = stats_rpcparse(space,size,&jsonflag,&postflag,jsonbuf,remoteaddr,filetype,req->port); + portable_mutex_unlock(&LP_commandmutex); + if ( filetype[0] != 0 ) + { + static cJSON *mimejson; char *tmp,*typestr=0; long tmpsize; + sprintf(helpname,"%s/mime.json",GLOBAL_HELPDIR); + if ( (tmp= OS_filestr(&tmpsize,helpname)) != 0 ) + { + mimejson = cJSON_Parse(tmp); + free(tmp); + } + if ( mimejson != 0 ) + { + if ( (typestr= jstr(mimejson,filetype)) != 0 ) + sprintf(content_type,"Content-Type: %s\r\n",typestr); + } else printf("parse error.(%s)\n",tmp); + //printf("filetype.(%s) json.%p type.%p tmp.%p [%s]\n",filetype,mimejson,typestr,tmp,content_type); + } + } + if ( retstr != 0 ) + { + char *response,hdrs[1024]; + //printf("RETURN.(%s) jsonflag.%d postflag.%d\n",retstr,jsonflag,postflag); + if ( jsonflag != 0 || postflag != 0 ) { - retstr = stats_rpcparse(space,size,&jsonflag,&postflag,jsonbuf,remoteaddr,filetype,port); - if ( filetype[0] != 0 ) + if ( retstr == 0 ) + retstr = clonestr("{}"); + response = malloc(strlen(retstr)+1024+1+1); + sprintf(hdrs,"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Credentials: true\r\nAccess-Control-Allow-Methods: GET, POST\r\nCache-Control : no-cache, no-store, must-revalidate\r\n%sContent-Length : %8d\r\n\r\n",content_type,(int32_t)strlen(retstr)); + response[0] = '\0'; + strcat(response,hdrs); + strcat(response,retstr); + strcat(response,"\n"); + if ( retstr != space ) + free(retstr); + retstr = response; + //printf("RET.(%s)\n",retstr); + } + remains = (int32_t)strlen(retstr); + i = 0; + while ( remains > 0 ) + { + if ( (numsent= (int32_t)send(sock,&retstr[i],remains,MSG_NOSIGNAL)) < 0 ) { - static cJSON *mimejson; char *tmp,*typestr=0; long tmpsize; - sprintf(helpname,"%s/mime.json",GLOBAL_HELPDIR); - if ( (tmp= OS_filestr(&tmpsize,helpname)) != 0 ) + if ( errno != EAGAIN && errno != EWOULDBLOCK ) { - mimejson = cJSON_Parse(tmp); - free(tmp); + //printf("%s: %s numsent.%d vs remains.%d len.%d errno.%d (%s) usock.%d\n",retstr,ipaddr,numsent,remains,recvlen,errno,strerror(errno),sock); + break; } - if ( mimejson != 0 ) - { - if ( (typestr= jstr(mimejson,filetype)) != 0 ) - sprintf(content_type,"Content-Type: %s\r\n",typestr); - } else printf("parse error.(%s)\n",tmp); - //printf("filetype.(%s) json.%p type.%p tmp.%p [%s]\n",filetype,mimejson,typestr,tmp,content_type); + } + else if ( remains > 0 ) + { + remains -= numsent; + i += numsent; + if ( remains > 0 ) + printf("iguana sent.%d remains.%d of recvlen.%d (%s)\n",numsent,remains,recvlen,jsonbuf); } } - if ( retstr != 0 ) + if ( retstr != space) + free(retstr); + } + free(space); + free(jsonbuf); + closesocket(sock); + portable_mutex_lock(&LP_gcmutex); + DL_APPEND(LP_garbage_collector,req); + spawned--; + portable_mutex_unlock(&LP_gcmutex); +} + +extern int32_t IAMLP; +//int32_t LP_bindsock_reset,LP_bindsock = -1; + +void stats_rpcloop(void *args) +{ + uint16_t port; int32_t retval,sock=-1,bindsock=-1; socklen_t clilen; struct sockaddr_in cli_addr; uint32_t ipbits,localhostbits; struct rpcrequest_info *req,*req2,*rtmp; + if ( (port= *(uint16_t *)args) == 0 ) + port = 7779; + printf("Start stats_rpcloop.%u\n",port); + localhostbits = (uint32_t)calc_ipbits("127.0.0.1"); + //initial_bindsock_reset = LP_bindsock_reset; + while ( 1 )//LP_bindsock_reset == initial_bindsock_reset ) + { + //printf("LP_bindsock.%d\n",LP_bindsock); + if ( bindsock < 0 ) { - char *response,hdrs[1024]; - //printf("RETURN.(%s) jsonflag.%d postflag.%d\n",retstr,jsonflag,postflag); - if ( jsonflag != 0 || postflag != 0 ) + while ( (bindsock= iguana_socket(1,"0.0.0.0",port)) < 0 ) + usleep(10000); +#ifndef _WIN32 + //fcntl(bindsock, F_SETFL, fcntl(bindsock, F_GETFL, 0) | O_NONBLOCK); +#endif + //if ( counter++ < 1 ) + printf(">>>>>>>>>> DEX stats 127.0.0.1:%d bind sock.%d DEX stats API enabled <<<<<<<<<\n",port,bindsock); + } + //printf("after sock.%d\n",sock); + clilen = sizeof(cli_addr); + sock = accept(bindsock,(struct sockaddr *)&cli_addr,&clilen); +//#ifdef _WIN32 + if ( sock < 0 ) + { + printf("iguana_rpcloop ERROR on accept port.%u usock.%d errno %d %s\n",port,sock,errno,strerror(errno)); + closesocket(bindsock); + bindsock = -1; + continue; + } +/*#else + if ( sock < 0 ) + { + //fprintf(stderr,"."); + if ( IAMLP == 0 ) + usleep(50000); + else usleep(2500); + continue; + } +#endif*/ + memcpy(&ipbits,&cli_addr.sin_addr.s_addr,sizeof(ipbits)); + if ( port == RPC_port && ipbits != localhostbits ) + { + closesocket(sock); + continue; + } + req = calloc(1,sizeof(*req)); + req->sock = sock; + req->ipbits = ipbits; + req->port = port; + LP_rpc_processreq(req); +continue; + // this leads to cant open file errors + if ( (retval= OS_thread_create(&req->T,NULL,(void *)LP_rpc_processreq,req)) != 0 ) + { + printf("error launching rpc handler on port %d, retval.%d\n",port,retval); + closesocket(sock); + sock = -1; + portable_mutex_lock(&LP_gcmutex); + DL_FOREACH_SAFE(LP_garbage_collector,req2,rtmp) { - if ( retstr == 0 ) - retstr = clonestr("{}"); - response = malloc(strlen(retstr)+1024+1+1); - sprintf(hdrs,"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Credentials: true\r\nAccess-Control-Allow-Methods: GET, POST\r\nCache-Control : no-cache, no-store, must-revalidate\r\n%sContent-Length : %8d\r\n\r\n",content_type,(int32_t)strlen(retstr)); - response[0] = '\0'; - strcat(response,hdrs); - strcat(response,retstr); - strcat(response,"\n"); - if ( retstr != space ) - free(retstr); - retstr = response; - //printf("RET.(%s)\n",retstr); + DL_DELETE(LP_garbage_collector,req2); + free(req2); } - remains = (int32_t)strlen(retstr); - i = 0; - while ( remains > 0 ) + portable_mutex_unlock(&LP_gcmutex); + if ( (retval= OS_thread_create(&req->T,NULL,(void *)LP_rpc_processreq,req)) != 0 ) { - if ( (numsent= (int32_t)send(sock,&retstr[i],remains,MSG_NOSIGNAL)) < 0 ) - { - if ( errno != EAGAIN && errno != EWOULDBLOCK ) - { - //printf("%s: %s numsent.%d vs remains.%d len.%d errno.%d (%s) usock.%d\n",retstr,ipaddr,numsent,remains,recvlen,errno,strerror(errno),sock); - break; - } - } - else if ( remains > 0 ) - { - remains -= numsent; - i += numsent; - if ( remains > 0 ) - printf("iguana sent.%d remains.%d of len.%d\n",numsent,remains,recvlen); - } + printf("error2 launching rpc handler on port %d, retval.%d\n",port,retval); + LP_rpc_processreq(req); } - if ( retstr != space) - free(retstr); - } - closesocket(sock); + } } + printf("i got killed\n"); } #ifndef FROM_MARKETMAKER + +portable_mutex_t LP_commandmutex; +uint16_t LP_RPCPORT; + void stats_kvjson(FILE *logfp,int32_t height,int32_t savedheight,uint32_t timestamp,char *key,cJSON *kvjson,bits256 pubkey,bits256 sigprev) { struct tai T; int32_t seconds,datenum,n; @@ -976,7 +1090,7 @@ int32_t komodo_parsestatefile(FILE *logfp,struct komodo_state *sp,FILE *fp,char int32_t stats_stateupdate(FILE *logfp,char *destdir,char *statefname,int32_t maxseconds,char *komodofile) { static long lastpos[2]; - char symbol[64],base[64]; int32_t iter,n; FILE *fp; uint32_t starttime; struct komodo_state *sp; + char symbol[65],base[65]; int32_t iter,n; FILE *fp; uint32_t starttime; struct komodo_state *sp; starttime = (uint32_t)time(NULL); strcpy(base,"KV"); strcpy(symbol,"KV"); @@ -1020,9 +1134,10 @@ char *stats_update(FILE *logfp,char *destdir,char *statefname,char *komodofname) return(jprint(retjson,1)); } +#ifndef FROM_PRIVATEBET int main(int argc, const char * argv[]) { - struct tai T; uint32_t timestamp; struct DEXstats_disp prices[365]; int32_t i,n,seconds,leftdatenum; FILE *fp,*logfp; char *filestr,*retstr,*statefname,logfname[512],komodofile[512]; uint16_t port = 7779; + struct tai T; uint32_t timestamp; struct DEXstats_disp prices[365]; int32_t i,n,seconds,leftdatenum; FILE *fp,*logfp; char *filestr,*retstr,*statefname,logfname[512],komodofile[512]; uint16_t port = LP_RPCPORT; if ( argc < 2 ) { statefname = "/root/.komodo/KV/komodostate"; @@ -1070,3 +1185,4 @@ int main(int argc, const char * argv[]) return 0; } #endif +#endif diff --git a/iguana/exchanges/statsdisp b/iguana/exchanges/statsdisp new file mode 100755 index 000000000..768c4e8b2 --- /dev/null +++ b/iguana/exchanges/statsdisp @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"statsdisp\",\"starttime\":0,\"endtime\":0}" diff --git a/iguana/exchanges/status b/iguana/exchanges/status index 7e7b4bb0e..0499bba6b 100755 --- a/iguana/exchanges/status +++ b/iguana/exchanges/status @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"swapstatus\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"swapstatus\"}" diff --git a/iguana/exchanges/stop b/iguana/exchanges/stop new file mode 100755 index 000000000..d13a70243 --- /dev/null +++ b/iguana/exchanges/stop @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"stop\"}" diff --git a/iguana/exchanges/swapstatus b/iguana/exchanges/swapstatus index e7ba89318..abc6dbb64 100755 --- a/iguana/exchanges/swapstatus +++ b/iguana/exchanges/swapstatus @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"swapstatus\",\"requestid\":2291973695,\"quoteid\":3387529385}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"swapstatus\",\"requestid\":2291973695,\"quoteid\":3387529385}" diff --git a/iguana/exchanges/trade b/iguana/exchanges/trade index cf7d9ec2f..1bad74aa9 100755 --- a/iguana/exchanges/trade +++ b/iguana/exchanges/trade @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"trade\",\"price\":1.234,\"base\":\"REVS\",\"rel\":\"KMD\",\"quote\":{}}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"trade\",\"price\":1.234,\"base\":\"REVS\",\"rel\":\"KMD\",\"quote\":{}}" diff --git a/iguana/exchanges/trust b/iguana/exchanges/trust new file mode 100755 index 000000000..6461f04c7 --- /dev/null +++ b/iguana/exchanges/trust @@ -0,0 +1,4 @@ +#!/bin/bash +echo "usage: ./trust " +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"$1\",\"method\":\"trust\",\"trust\":1}" diff --git a/iguana/exchanges/trusted b/iguana/exchanges/trusted new file mode 100755 index 000000000..fe96516e2 --- /dev/null +++ b/iguana/exchanges/trusted @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"trusted\"}" diff --git a/iguana/exchanges/userpass b/iguana/exchanges/userpass index 1a8a9ad5a..d097e0445 100644 --- a/iguana/exchanges/userpass +++ b/iguana/exchanges/userpass @@ -1 +1,2 @@ -export userpass="" +#export userpass="" +export userpass="c3d8c2a364b7d18c1f9d7321d017b92e9f9c791e4f5c741214fefdea8a071256" diff --git a/iguana/exchanges/utxos b/iguana/exchanges/utxos deleted file mode 100755 index a84c72fb0..000000000 --- a/iguana/exchanges/utxos +++ /dev/null @@ -1,2 +0,0 @@ -source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"getutxos\",\"coin\":\"REVS\"}" diff --git a/iguana/exchanges/withdraw b/iguana/exchanges/withdraw new file mode 100755 index 000000000..8a78fa5a1 --- /dev/null +++ b/iguana/exchanges/withdraw @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"withdraw\",\"coin\":\"KMD\",\"outputs\":[{\"RUgW6fLfVsLJ87Ng4zJTqNedJSKYQ9ToAf\":0.001}, {\"RUgW6fLfVsLJ87Ng4zJTqNedJSKYQ9ToAf\":0.002}]}" diff --git a/iguana/help/InstantDEX_DEXratio.json b/iguana/help/InstantDEX_DEXratio.json new file mode 100644 index 000000000..cc7bbd980 --- /dev/null +++ b/iguana/help/InstantDEX_DEXratio.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"DEXratio","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_DEXratio_test.py"}]} diff --git a/iguana/help/InstantDEX_accept.json b/iguana/help/InstantDEX_accept.json new file mode 100644 index 000000000..92c1d4521 --- /dev/null +++ b/iguana/help/InstantDEX_accept.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"accept","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_accept_test.py"}]} diff --git a/iguana/help/InstantDEX_allcoins.json b/iguana/help/InstantDEX_allcoins.json new file mode 100644 index 000000000..41d3a3ac3 --- /dev/null +++ b/iguana/help/InstantDEX_allcoins.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"allcoins","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_allcoins_test.py"}]} diff --git a/iguana/help/InstantDEX_allexchanges.json b/iguana/help/InstantDEX_allexchanges.json new file mode 100644 index 000000000..1d3e588fa --- /dev/null +++ b/iguana/help/InstantDEX_allexchanges.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"allexchanges","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_allexchanges_test.py"}]} diff --git a/iguana/help/InstantDEX_allpairs.json b/iguana/help/InstantDEX_allpairs.json new file mode 100644 index 000000000..80b71c2b9 --- /dev/null +++ b/iguana/help/InstantDEX_allpairs.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"allpairs","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_allpairs_test.py"}]} diff --git a/iguana/help/InstantDEX_apikeypair.json b/iguana/help/InstantDEX_apikeypair.json new file mode 100644 index 000000000..ed6a4d911 --- /dev/null +++ b/iguana/help/InstantDEX_apikeypair.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"apikeypair","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_apikeypair_test.py"}]} diff --git a/iguana/help/InstantDEX_automatched.json b/iguana/help/InstantDEX_automatched.json new file mode 100644 index 000000000..b9626ec23 --- /dev/null +++ b/iguana/help/InstantDEX_automatched.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"automatched","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_automatched_test.py"}]} diff --git a/iguana/help/InstantDEX_available.json b/iguana/help/InstantDEX_available.json new file mode 100644 index 000000000..18ed08484 --- /dev/null +++ b/iguana/help/InstantDEX_available.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"available","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_available_test.py"}]} diff --git a/iguana/help/InstantDEX_balance.json b/iguana/help/InstantDEX_balance.json new file mode 100644 index 000000000..c70d5b99f --- /dev/null +++ b/iguana/help/InstantDEX_balance.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"balance","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_balance_test.py"}]} diff --git a/iguana/help/InstantDEX_buy.json b/iguana/help/InstantDEX_buy.json new file mode 100644 index 000000000..1c3636e07 --- /dev/null +++ b/iguana/help/InstantDEX_buy.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"buy","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_buy_test.py"}]} diff --git a/iguana/help/InstantDEX_cancelorder.json b/iguana/help/InstantDEX_cancelorder.json new file mode 100644 index 000000000..ea397f36d --- /dev/null +++ b/iguana/help/InstantDEX_cancelorder.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"cancelorder","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_cancelorder_test.py"}]} diff --git a/iguana/help/InstantDEX_getswaplist.json b/iguana/help/InstantDEX_getswaplist.json new file mode 100644 index 000000000..59caa393b --- /dev/null +++ b/iguana/help/InstantDEX_getswaplist.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"getswaplist","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_getswaplist_test.py"}]} diff --git a/iguana/help/InstantDEX_incoming.json b/iguana/help/InstantDEX_incoming.json new file mode 100644 index 000000000..f698f45d7 --- /dev/null +++ b/iguana/help/InstantDEX_incoming.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"incoming","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_incoming_test.py"}]} diff --git a/iguana/help/InstantDEX_init.json b/iguana/help/InstantDEX_init.json new file mode 100644 index 000000000..1caaab76f --- /dev/null +++ b/iguana/help/InstantDEX_init.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"init","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_init_test.py"}]} diff --git a/iguana/help/InstantDEX_openorders.json b/iguana/help/InstantDEX_openorders.json new file mode 100644 index 000000000..dfd406ecd --- /dev/null +++ b/iguana/help/InstantDEX_openorders.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"openorders","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_openorders_test.py"}]} diff --git a/iguana/help/InstantDEX_orderbook.json b/iguana/help/InstantDEX_orderbook.json new file mode 100644 index 000000000..beff23123 --- /dev/null +++ b/iguana/help/InstantDEX_orderbook.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"orderbook","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_orderbook_test.py"}]} diff --git a/iguana/help/InstantDEX_orderstatus.json b/iguana/help/InstantDEX_orderstatus.json new file mode 100644 index 000000000..613e54400 --- /dev/null +++ b/iguana/help/InstantDEX_orderstatus.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"orderstatus","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_orderstatus_test.py"}]} diff --git a/iguana/help/InstantDEX_pollgap.json b/iguana/help/InstantDEX_pollgap.json new file mode 100644 index 000000000..b90628331 --- /dev/null +++ b/iguana/help/InstantDEX_pollgap.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"pollgap","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_pollgap_test.py"}]} diff --git a/iguana/help/InstantDEX_request.json b/iguana/help/InstantDEX_request.json new file mode 100644 index 000000000..9dde5538e --- /dev/null +++ b/iguana/help/InstantDEX_request.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"request","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_request_test.py"}]} diff --git a/iguana/help/InstantDEX_sell.json b/iguana/help/InstantDEX_sell.json new file mode 100644 index 000000000..57a939570 --- /dev/null +++ b/iguana/help/InstantDEX_sell.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"sell","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_sell_test.py"}]} diff --git a/iguana/help/InstantDEX_setuserid.json b/iguana/help/InstantDEX_setuserid.json new file mode 100644 index 000000000..0b2dd819c --- /dev/null +++ b/iguana/help/InstantDEX_setuserid.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"setuserid","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_setuserid_test.py"}]} diff --git a/iguana/help/InstantDEX_smartaddress.json b/iguana/help/InstantDEX_smartaddress.json new file mode 100644 index 000000000..18924dca4 --- /dev/null +++ b/iguana/help/InstantDEX_smartaddress.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"smartaddress","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_smartaddress_test.py"}]} diff --git a/iguana/help/InstantDEX_smartaddresses.json b/iguana/help/InstantDEX_smartaddresses.json new file mode 100644 index 000000000..39f3f1d20 --- /dev/null +++ b/iguana/help/InstantDEX_smartaddresses.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"smartaddresses","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_smartaddresses_test.py"}]} diff --git a/iguana/help/InstantDEX_supports.json b/iguana/help/InstantDEX_supports.json new file mode 100644 index 000000000..254fea7aa --- /dev/null +++ b/iguana/help/InstantDEX_supports.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"supports","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_supports_test.py"}]} diff --git a/iguana/help/InstantDEX_tradehistory.json b/iguana/help/InstantDEX_tradehistory.json new file mode 100644 index 000000000..5feba4639 --- /dev/null +++ b/iguana/help/InstantDEX_tradehistory.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"tradehistory","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_tradehistory_test.py"}]} diff --git a/iguana/help/InstantDEX_withdraw.json b/iguana/help/InstantDEX_withdraw.json new file mode 100644 index 000000000..45aa88599 --- /dev/null +++ b/iguana/help/InstantDEX_withdraw.json @@ -0,0 +1 @@ +{"agent":"InstantDEX","method":"withdraw","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"InstantDEX_withdraw_test.py"}]} diff --git a/iguana/help/SuperNET_activehandle.json b/iguana/help/SuperNET_activehandle.json new file mode 100644 index 000000000..1530b8c01 --- /dev/null +++ b/iguana/help/SuperNET_activehandle.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"activehandle","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_activehandle_test.py"}]} diff --git a/iguana/help/SuperNET_addr2rmd160.json b/iguana/help/SuperNET_addr2rmd160.json new file mode 100644 index 000000000..a3a40aac4 --- /dev/null +++ b/iguana/help/SuperNET_addr2rmd160.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"addr2rmd160","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_addr2rmd160_test.py"}]} diff --git a/iguana/help/SuperNET_bitcoinrpc.json b/iguana/help/SuperNET_bitcoinrpc.json new file mode 100644 index 000000000..46422d4d7 --- /dev/null +++ b/iguana/help/SuperNET_bitcoinrpc.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"bitcoinrpc","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_bitcoinrpc_test.py"}]} diff --git a/iguana/help/SuperNET_broadcastcipher.json b/iguana/help/SuperNET_broadcastcipher.json new file mode 100644 index 000000000..7d762494d --- /dev/null +++ b/iguana/help/SuperNET_broadcastcipher.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"broadcastcipher","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_broadcastcipher_test.py"}]} diff --git a/iguana/help/SuperNET_broadcastdecipher.json b/iguana/help/SuperNET_broadcastdecipher.json new file mode 100644 index 000000000..d0c9a482a --- /dev/null +++ b/iguana/help/SuperNET_broadcastdecipher.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"broadcastdecipher","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_broadcastdecipher_test.py"}]} diff --git a/iguana/help/SuperNET_cipher.json b/iguana/help/SuperNET_cipher.json new file mode 100644 index 000000000..fe40ca2b7 --- /dev/null +++ b/iguana/help/SuperNET_cipher.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"cipher","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_cipher_test.py"}]} diff --git a/iguana/help/SuperNET_decipher.json b/iguana/help/SuperNET_decipher.json new file mode 100644 index 000000000..e9f3afeb0 --- /dev/null +++ b/iguana/help/SuperNET_decipher.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"decipher","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_decipher_test.py"}]} diff --git a/iguana/help/SuperNET_decryptjson.json b/iguana/help/SuperNET_decryptjson.json new file mode 100644 index 000000000..99f744a30 --- /dev/null +++ b/iguana/help/SuperNET_decryptjson.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"decryptjson","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_decryptjson_test.py"}]} diff --git a/iguana/help/SuperNET_encryptjson.json b/iguana/help/SuperNET_encryptjson.json new file mode 100644 index 000000000..ab8e48167 --- /dev/null +++ b/iguana/help/SuperNET_encryptjson.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"encryptjson","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_encryptjson_test.py"}]} diff --git a/iguana/help/SuperNET_getpeers.json b/iguana/help/SuperNET_getpeers.json new file mode 100644 index 000000000..0b0668d7c --- /dev/null +++ b/iguana/help/SuperNET_getpeers.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"getpeers","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_getpeers_test.py"}]} diff --git a/iguana/help/SuperNET_help.json b/iguana/help/SuperNET_help.json new file mode 100644 index 000000000..6e15f801c --- /dev/null +++ b/iguana/help/SuperNET_help.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"help","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_help_test.py"}]} diff --git a/iguana/help/SuperNET_html.json b/iguana/help/SuperNET_html.json new file mode 100644 index 000000000..b964098e9 --- /dev/null +++ b/iguana/help/SuperNET_html.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"html","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_html_test.py"}]} diff --git a/iguana/help/SuperNET_keypair.json b/iguana/help/SuperNET_keypair.json new file mode 100644 index 000000000..cdd91ae55 --- /dev/null +++ b/iguana/help/SuperNET_keypair.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"keypair","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_keypair_test.py"}]} diff --git a/iguana/help/SuperNET_layer.json b/iguana/help/SuperNET_layer.json new file mode 100644 index 000000000..fe4ecf3d4 --- /dev/null +++ b/iguana/help/SuperNET_layer.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"layer","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_layer_test.py"}]} diff --git a/iguana/help/SuperNET_login.json b/iguana/help/SuperNET_login.json new file mode 100644 index 000000000..c95a70f88 --- /dev/null +++ b/iguana/help/SuperNET_login.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"login","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_login_test.py"}]} diff --git a/iguana/help/SuperNET_logout.json b/iguana/help/SuperNET_logout.json new file mode 100644 index 000000000..c81c52c82 --- /dev/null +++ b/iguana/help/SuperNET_logout.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"logout","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_logout_test.py"}]} diff --git a/iguana/help/SuperNET_multicastcipher.json b/iguana/help/SuperNET_multicastcipher.json new file mode 100644 index 000000000..f12acca5c --- /dev/null +++ b/iguana/help/SuperNET_multicastcipher.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"multicastcipher","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_multicastcipher_test.py"}]} diff --git a/iguana/help/SuperNET_multicastdecipher.json b/iguana/help/SuperNET_multicastdecipher.json new file mode 100644 index 000000000..6c7a28c63 --- /dev/null +++ b/iguana/help/SuperNET_multicastdecipher.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"multicastdecipher","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_multicastdecipher_test.py"}]} diff --git a/iguana/help/SuperNET_myipaddr.json b/iguana/help/SuperNET_myipaddr.json new file mode 100644 index 000000000..ca58efd1b --- /dev/null +++ b/iguana/help/SuperNET_myipaddr.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"myipaddr","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_myipaddr_test.py"}]} diff --git a/iguana/help/SuperNET_mypeers.json b/iguana/help/SuperNET_mypeers.json new file mode 100644 index 000000000..461a59d53 --- /dev/null +++ b/iguana/help/SuperNET_mypeers.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"mypeers","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_mypeers_test.py"}]} diff --git a/iguana/help/SuperNET_priv2pub.json b/iguana/help/SuperNET_priv2pub.json new file mode 100644 index 000000000..279268c76 --- /dev/null +++ b/iguana/help/SuperNET_priv2pub.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"priv2pub","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_priv2pub_test.py"}]} diff --git a/iguana/help/SuperNET_priv2wif.json b/iguana/help/SuperNET_priv2wif.json new file mode 100644 index 000000000..8fc080527 --- /dev/null +++ b/iguana/help/SuperNET_priv2wif.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"priv2wif","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_priv2wif_test.py"}]} diff --git a/iguana/help/SuperNET_rmd160conv.json b/iguana/help/SuperNET_rmd160conv.json new file mode 100644 index 000000000..831ff50f7 --- /dev/null +++ b/iguana/help/SuperNET_rmd160conv.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"rmd160conv","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_rmd160conv_test.py"}]} diff --git a/iguana/help/SuperNET_rosetta.json b/iguana/help/SuperNET_rosetta.json new file mode 100644 index 000000000..58c3ef933 --- /dev/null +++ b/iguana/help/SuperNET_rosetta.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"rosetta","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_rosetta_test.py"}]} diff --git a/iguana/help/SuperNET_saveconf.json b/iguana/help/SuperNET_saveconf.json new file mode 100644 index 000000000..e78fbf542 --- /dev/null +++ b/iguana/help/SuperNET_saveconf.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"saveconf","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_saveconf_test.py"}]} diff --git a/iguana/help/SuperNET_setmyipaddr.json b/iguana/help/SuperNET_setmyipaddr.json new file mode 100644 index 000000000..02a73f5d8 --- /dev/null +++ b/iguana/help/SuperNET_setmyipaddr.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"setmyipaddr","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_setmyipaddr_test.py"}]} diff --git a/iguana/help/SuperNET_stop.json b/iguana/help/SuperNET_stop.json new file mode 100644 index 000000000..29f40aadd --- /dev/null +++ b/iguana/help/SuperNET_stop.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"stop","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_stop_test.py"}]} diff --git a/iguana/help/SuperNET_utc2utime.json b/iguana/help/SuperNET_utc2utime.json new file mode 100644 index 000000000..f5fa3556f --- /dev/null +++ b/iguana/help/SuperNET_utc2utime.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"utc2utime","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_utc2utime_test.py"}]} diff --git a/iguana/help/SuperNET_utime2utc.json b/iguana/help/SuperNET_utime2utc.json new file mode 100644 index 000000000..000d81603 --- /dev/null +++ b/iguana/help/SuperNET_utime2utc.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"utime2utc","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_utime2utc_test.py"}]} diff --git a/iguana/help/SuperNET_wif2priv.json b/iguana/help/SuperNET_wif2priv.json new file mode 100644 index 000000000..e0447b36b --- /dev/null +++ b/iguana/help/SuperNET_wif2priv.json @@ -0,0 +1 @@ +{"agent":"SuperNET","method":"wif2priv","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"SuperNET_wif2priv_test.py"}]} diff --git a/iguana/help/basilisk_addrelay.json b/iguana/help/basilisk_addrelay.json new file mode 100644 index 000000000..a0faa2c84 --- /dev/null +++ b/iguana/help/basilisk_addrelay.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"addrelay","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_addrelay_test.py"}]} diff --git a/iguana/help/basilisk_balances.json b/iguana/help/basilisk_balances.json new file mode 100644 index 000000000..85bdf0f7f --- /dev/null +++ b/iguana/help/basilisk_balances.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"balances","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_balances_test.py"}]} diff --git a/iguana/help/basilisk_cancelrefresh.json b/iguana/help/basilisk_cancelrefresh.json new file mode 100644 index 000000000..1d2db83c9 --- /dev/null +++ b/iguana/help/basilisk_cancelrefresh.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"cancelrefresh","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_cancelrefresh_test.py"}]} diff --git a/iguana/help/basilisk_dispatch.json b/iguana/help/basilisk_dispatch.json new file mode 100644 index 000000000..395902152 --- /dev/null +++ b/iguana/help/basilisk_dispatch.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"dispatch","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_dispatch_test.py"}]} diff --git a/iguana/help/basilisk_forward.json b/iguana/help/basilisk_forward.json new file mode 100644 index 000000000..868424a14 --- /dev/null +++ b/iguana/help/basilisk_forward.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"forward","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_forward_test.py"}]} diff --git a/iguana/help/basilisk_geckoblock.json b/iguana/help/basilisk_geckoblock.json new file mode 100644 index 000000000..ed730f081 --- /dev/null +++ b/iguana/help/basilisk_geckoblock.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"geckoblock","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_geckoblock_test.py"}]} diff --git a/iguana/help/basilisk_geckoget.json b/iguana/help/basilisk_geckoget.json new file mode 100644 index 000000000..ddb097fab --- /dev/null +++ b/iguana/help/basilisk_geckoget.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"geckoget","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_geckoget_test.py"}]} diff --git a/iguana/help/basilisk_geckoheaders.json b/iguana/help/basilisk_geckoheaders.json new file mode 100644 index 000000000..30b600d6f --- /dev/null +++ b/iguana/help/basilisk_geckoheaders.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"geckoheaders","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_geckoheaders_test.py"}]} diff --git a/iguana/help/basilisk_geckotx.json b/iguana/help/basilisk_geckotx.json new file mode 100644 index 000000000..b55cf8582 --- /dev/null +++ b/iguana/help/basilisk_geckotx.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"geckotx","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_geckotx_test.py"}]} diff --git a/iguana/help/basilisk_genesis_opreturn.json b/iguana/help/basilisk_genesis_opreturn.json new file mode 100644 index 000000000..25c7e3277 --- /dev/null +++ b/iguana/help/basilisk_genesis_opreturn.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"genesis_opreturn","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_genesis_opreturn_test.py"}]} diff --git a/iguana/help/basilisk_getmessage.json b/iguana/help/basilisk_getmessage.json new file mode 100644 index 000000000..e4dbd9cdd --- /dev/null +++ b/iguana/help/basilisk_getmessage.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"getmessage","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_getmessage_test.py"}]} diff --git a/iguana/help/basilisk_history.json b/iguana/help/basilisk_history.json new file mode 100644 index 000000000..fd91aa8bc --- /dev/null +++ b/iguana/help/basilisk_history.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"history","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_history_test.py"}]} diff --git a/iguana/help/basilisk_mailbox.json b/iguana/help/basilisk_mailbox.json new file mode 100644 index 000000000..4eceaf50a --- /dev/null +++ b/iguana/help/basilisk_mailbox.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"mailbox","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_mailbox_test.py"}]} diff --git a/iguana/help/basilisk_paxfiats.json b/iguana/help/basilisk_paxfiats.json new file mode 100644 index 000000000..26a27c6cb --- /dev/null +++ b/iguana/help/basilisk_paxfiats.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"paxfiats","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_paxfiats_test.py"}]} diff --git a/iguana/help/basilisk_publish.json b/iguana/help/basilisk_publish.json new file mode 100644 index 000000000..1c0d9469c --- /dev/null +++ b/iguana/help/basilisk_publish.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"publish","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_publish_test.py"}]} diff --git a/iguana/help/basilisk_rawtx.json b/iguana/help/basilisk_rawtx.json new file mode 100644 index 000000000..73682aa14 --- /dev/null +++ b/iguana/help/basilisk_rawtx.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"rawtx","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_rawtx_test.py"}]} diff --git a/iguana/help/basilisk_refresh.json b/iguana/help/basilisk_refresh.json new file mode 100644 index 000000000..fc3ee50a8 --- /dev/null +++ b/iguana/help/basilisk_refresh.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"refresh","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_refresh_test.py"}]} diff --git a/iguana/help/basilisk_sendmessage.json b/iguana/help/basilisk_sendmessage.json new file mode 100644 index 000000000..96a8fab9e --- /dev/null +++ b/iguana/help/basilisk_sendmessage.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"sendmessage","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_sendmessage_test.py"}]} diff --git a/iguana/help/basilisk_subscribe.json b/iguana/help/basilisk_subscribe.json new file mode 100644 index 000000000..2369fefb9 --- /dev/null +++ b/iguana/help/basilisk_subscribe.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"subscribe","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_subscribe_test.py"}]} diff --git a/iguana/help/basilisk_utxocombine.json b/iguana/help/basilisk_utxocombine.json new file mode 100644 index 000000000..4ef0423ec --- /dev/null +++ b/iguana/help/basilisk_utxocombine.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"utxocombine","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_utxocombine_test.py"}]} diff --git a/iguana/help/basilisk_utxorawtx.json b/iguana/help/basilisk_utxorawtx.json new file mode 100644 index 000000000..f44828007 --- /dev/null +++ b/iguana/help/basilisk_utxorawtx.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"utxorawtx","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_utxorawtx_test.py"}]} diff --git a/iguana/help/basilisk_value.json b/iguana/help/basilisk_value.json new file mode 100644 index 000000000..2f3575ad8 --- /dev/null +++ b/iguana/help/basilisk_value.json @@ -0,0 +1 @@ +{"agent":"basilisk","method":"value","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"basilisk_value_test.py"}]} diff --git a/iguana/help/bitcoinrpc_addmultisigaddress.json b/iguana/help/bitcoinrpc_addmultisigaddress.json new file mode 100644 index 000000000..453eedab1 --- /dev/null +++ b/iguana/help/bitcoinrpc_addmultisigaddress.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"addmultisigaddress","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_addmultisigaddress_test.py"}]} diff --git a/iguana/help/bitcoinrpc_backupwallet.json b/iguana/help/bitcoinrpc_backupwallet.json new file mode 100644 index 000000000..49d4977f6 --- /dev/null +++ b/iguana/help/bitcoinrpc_backupwallet.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"backupwallet","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_backupwallet_test.py"}]} diff --git a/iguana/help/bitcoinrpc_checkwallet.json b/iguana/help/bitcoinrpc_checkwallet.json new file mode 100644 index 000000000..7873ec3e3 --- /dev/null +++ b/iguana/help/bitcoinrpc_checkwallet.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"checkwallet","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_checkwallet_test.py"}]} diff --git a/iguana/help/bitcoinrpc_createmultisig.json b/iguana/help/bitcoinrpc_createmultisig.json new file mode 100644 index 000000000..1fc0af008 --- /dev/null +++ b/iguana/help/bitcoinrpc_createmultisig.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"createmultisig","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_createmultisig_test.py"}]} diff --git a/iguana/help/bitcoinrpc_createrawtransaction.json b/iguana/help/bitcoinrpc_createrawtransaction.json new file mode 100644 index 000000000..36a955996 --- /dev/null +++ b/iguana/help/bitcoinrpc_createrawtransaction.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"createrawtransaction","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_createrawtransaction_test.py"}]} diff --git a/iguana/help/bitcoinrpc_decoderawtransaction.json b/iguana/help/bitcoinrpc_decoderawtransaction.json new file mode 100644 index 000000000..772f96900 --- /dev/null +++ b/iguana/help/bitcoinrpc_decoderawtransaction.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"decoderawtransaction","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_decoderawtransaction_test.py"}]} diff --git a/iguana/help/bitcoinrpc_decodescript.json b/iguana/help/bitcoinrpc_decodescript.json new file mode 100644 index 000000000..9be4a77bf --- /dev/null +++ b/iguana/help/bitcoinrpc_decodescript.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"decodescript","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_decodescript_test.py"}]} diff --git a/iguana/help/bitcoinrpc_dumpprivkey.json b/iguana/help/bitcoinrpc_dumpprivkey.json new file mode 100644 index 000000000..b28fe7185 --- /dev/null +++ b/iguana/help/bitcoinrpc_dumpprivkey.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"dumpprivkey","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_dumpprivkey_test.py"}]} diff --git a/iguana/help/bitcoinrpc_dumpwallet.json b/iguana/help/bitcoinrpc_dumpwallet.json new file mode 100644 index 000000000..d0f3ed4f1 --- /dev/null +++ b/iguana/help/bitcoinrpc_dumpwallet.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"dumpwallet","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_dumpwallet_test.py"}]} diff --git a/iguana/help/bitcoinrpc_encryptwallet.json b/iguana/help/bitcoinrpc_encryptwallet.json new file mode 100644 index 000000000..3919c40a4 --- /dev/null +++ b/iguana/help/bitcoinrpc_encryptwallet.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"encryptwallet","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_encryptwallet_test.py"}]} diff --git a/iguana/help/bitcoinrpc_getaccount.json b/iguana/help/bitcoinrpc_getaccount.json new file mode 100644 index 000000000..b0ecd2a9e --- /dev/null +++ b/iguana/help/bitcoinrpc_getaccount.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"getaccount","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_getaccount_test.py"}]} diff --git a/iguana/help/bitcoinrpc_getaccountaddress.json b/iguana/help/bitcoinrpc_getaccountaddress.json new file mode 100644 index 000000000..cf3842825 --- /dev/null +++ b/iguana/help/bitcoinrpc_getaccountaddress.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"getaccountaddress","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_getaccountaddress_test.py"}]} diff --git a/iguana/help/bitcoinrpc_getaddressesbyaccount.json b/iguana/help/bitcoinrpc_getaddressesbyaccount.json new file mode 100644 index 000000000..12d42c814 --- /dev/null +++ b/iguana/help/bitcoinrpc_getaddressesbyaccount.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"getaddressesbyaccount","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_getaddressesbyaccount_test.py"}]} diff --git a/iguana/help/bitcoinrpc_getbalance.json b/iguana/help/bitcoinrpc_getbalance.json new file mode 100644 index 000000000..22f234744 --- /dev/null +++ b/iguana/help/bitcoinrpc_getbalance.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"getbalance","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_getbalance_test.py"}]} diff --git a/iguana/help/bitcoinrpc_getbestblockhash.json b/iguana/help/bitcoinrpc_getbestblockhash.json new file mode 100644 index 000000000..e2c5fd0a7 --- /dev/null +++ b/iguana/help/bitcoinrpc_getbestblockhash.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"getbestblockhash","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_getbestblockhash_test.py"}]} diff --git a/iguana/help/bitcoinrpc_getblock.json b/iguana/help/bitcoinrpc_getblock.json new file mode 100644 index 000000000..2f23841f5 --- /dev/null +++ b/iguana/help/bitcoinrpc_getblock.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"getblock","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_getblock_test.py"}]} diff --git a/iguana/help/bitcoinrpc_getblockcount.json b/iguana/help/bitcoinrpc_getblockcount.json new file mode 100644 index 000000000..1c1a14959 --- /dev/null +++ b/iguana/help/bitcoinrpc_getblockcount.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"getblockcount","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_getblockcount_test.py"}]} diff --git a/iguana/help/bitcoinrpc_getblockhash.json b/iguana/help/bitcoinrpc_getblockhash.json new file mode 100644 index 000000000..4c7877840 --- /dev/null +++ b/iguana/help/bitcoinrpc_getblockhash.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"getblockhash","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_getblockhash_test.py"}]} diff --git a/iguana/help/bitcoinrpc_getdifficulty.json b/iguana/help/bitcoinrpc_getdifficulty.json new file mode 100644 index 000000000..5950fb6f5 --- /dev/null +++ b/iguana/help/bitcoinrpc_getdifficulty.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"getdifficulty","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_getdifficulty_test.py"}]} diff --git a/iguana/help/bitcoinrpc_getinfo.json b/iguana/help/bitcoinrpc_getinfo.json new file mode 100644 index 000000000..22be35c69 --- /dev/null +++ b/iguana/help/bitcoinrpc_getinfo.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"getinfo","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_getinfo_test.py"}]} diff --git a/iguana/help/bitcoinrpc_getnewaddress.json b/iguana/help/bitcoinrpc_getnewaddress.json new file mode 100644 index 000000000..3d6875a2a --- /dev/null +++ b/iguana/help/bitcoinrpc_getnewaddress.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"getnewaddress","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_getnewaddress_test.py"}]} diff --git a/iguana/help/bitcoinrpc_getrawchangeaddress.json b/iguana/help/bitcoinrpc_getrawchangeaddress.json new file mode 100644 index 000000000..3d4128a2f --- /dev/null +++ b/iguana/help/bitcoinrpc_getrawchangeaddress.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"getrawchangeaddress","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_getrawchangeaddress_test.py"}]} diff --git a/iguana/help/bitcoinrpc_getrawtransaction.json b/iguana/help/bitcoinrpc_getrawtransaction.json new file mode 100644 index 000000000..93c727b87 --- /dev/null +++ b/iguana/help/bitcoinrpc_getrawtransaction.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"getrawtransaction","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_getrawtransaction_test.py"}]} diff --git a/iguana/help/bitcoinrpc_getreceivedbyaccount.json b/iguana/help/bitcoinrpc_getreceivedbyaccount.json new file mode 100644 index 000000000..defd762d9 --- /dev/null +++ b/iguana/help/bitcoinrpc_getreceivedbyaccount.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"getreceivedbyaccount","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_getreceivedbyaccount_test.py"}]} diff --git a/iguana/help/bitcoinrpc_getreceivedbyaddress.json b/iguana/help/bitcoinrpc_getreceivedbyaddress.json new file mode 100644 index 000000000..edb272cb7 --- /dev/null +++ b/iguana/help/bitcoinrpc_getreceivedbyaddress.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"getreceivedbyaddress","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_getreceivedbyaddress_test.py"}]} diff --git a/iguana/help/bitcoinrpc_gettransaction.json b/iguana/help/bitcoinrpc_gettransaction.json new file mode 100644 index 000000000..480f1e86f --- /dev/null +++ b/iguana/help/bitcoinrpc_gettransaction.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"gettransaction","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_gettransaction_test.py"}]} diff --git a/iguana/help/bitcoinrpc_gettxout.json b/iguana/help/bitcoinrpc_gettxout.json new file mode 100644 index 000000000..98324561b --- /dev/null +++ b/iguana/help/bitcoinrpc_gettxout.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"gettxout","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_gettxout_test.py"}]} diff --git a/iguana/help/bitcoinrpc_gettxoutsetinfo.json b/iguana/help/bitcoinrpc_gettxoutsetinfo.json new file mode 100644 index 000000000..3d1926383 --- /dev/null +++ b/iguana/help/bitcoinrpc_gettxoutsetinfo.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"gettxoutsetinfo","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_gettxoutsetinfo_test.py"}]} diff --git a/iguana/help/bitcoinrpc_importaddress.json b/iguana/help/bitcoinrpc_importaddress.json new file mode 100644 index 000000000..37e9c4a0d --- /dev/null +++ b/iguana/help/bitcoinrpc_importaddress.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"importaddress","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_importaddress_test.py"}]} diff --git a/iguana/help/bitcoinrpc_importprivkey.json b/iguana/help/bitcoinrpc_importprivkey.json new file mode 100644 index 000000000..4efae987e --- /dev/null +++ b/iguana/help/bitcoinrpc_importprivkey.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"importprivkey","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_importprivkey_test.py"}]} diff --git a/iguana/help/bitcoinrpc_importwallet.json b/iguana/help/bitcoinrpc_importwallet.json new file mode 100644 index 000000000..8bf5ce1ae --- /dev/null +++ b/iguana/help/bitcoinrpc_importwallet.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"importwallet","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_importwallet_test.py"}]} diff --git a/iguana/help/bitcoinrpc_listaccounts.json b/iguana/help/bitcoinrpc_listaccounts.json new file mode 100644 index 000000000..635508cf5 --- /dev/null +++ b/iguana/help/bitcoinrpc_listaccounts.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"listaccounts","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_listaccounts_test.py"}]} diff --git a/iguana/help/bitcoinrpc_listaddressgroupings.json b/iguana/help/bitcoinrpc_listaddressgroupings.json new file mode 100644 index 000000000..21f7d8b3e --- /dev/null +++ b/iguana/help/bitcoinrpc_listaddressgroupings.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"listaddressgroupings","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_listaddressgroupings_test.py"}]} diff --git a/iguana/help/bitcoinrpc_listlockunspent.json b/iguana/help/bitcoinrpc_listlockunspent.json new file mode 100644 index 000000000..23ee5ccb9 --- /dev/null +++ b/iguana/help/bitcoinrpc_listlockunspent.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"listlockunspent","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_listlockunspent_test.py"}]} diff --git a/iguana/help/bitcoinrpc_listreceivedbyaccount.json b/iguana/help/bitcoinrpc_listreceivedbyaccount.json new file mode 100644 index 000000000..a7f59f51f --- /dev/null +++ b/iguana/help/bitcoinrpc_listreceivedbyaccount.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"listreceivedbyaccount","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_listreceivedbyaccount_test.py"}]} diff --git a/iguana/help/bitcoinrpc_listreceivedbyaddress.json b/iguana/help/bitcoinrpc_listreceivedbyaddress.json new file mode 100644 index 000000000..6150f1a3b --- /dev/null +++ b/iguana/help/bitcoinrpc_listreceivedbyaddress.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"listreceivedbyaddress","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_listreceivedbyaddress_test.py"}]} diff --git a/iguana/help/bitcoinrpc_listsinceblock.json b/iguana/help/bitcoinrpc_listsinceblock.json new file mode 100644 index 000000000..66beb661a --- /dev/null +++ b/iguana/help/bitcoinrpc_listsinceblock.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"listsinceblock","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_listsinceblock_test.py"}]} diff --git a/iguana/help/bitcoinrpc_listtransactions.json b/iguana/help/bitcoinrpc_listtransactions.json new file mode 100644 index 000000000..ddb55511c --- /dev/null +++ b/iguana/help/bitcoinrpc_listtransactions.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"listtransactions","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_listtransactions_test.py"}]} diff --git a/iguana/help/bitcoinrpc_listunspent.json b/iguana/help/bitcoinrpc_listunspent.json new file mode 100644 index 000000000..0c11033b4 --- /dev/null +++ b/iguana/help/bitcoinrpc_listunspent.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"listunspent","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_listunspent_test.py"}]} diff --git a/iguana/help/bitcoinrpc_lockunspent.json b/iguana/help/bitcoinrpc_lockunspent.json new file mode 100644 index 000000000..61c9d7db8 --- /dev/null +++ b/iguana/help/bitcoinrpc_lockunspent.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"lockunspent","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_lockunspent_test.py"}]} diff --git a/iguana/help/bitcoinrpc_move.json b/iguana/help/bitcoinrpc_move.json new file mode 100644 index 000000000..b96af5b84 --- /dev/null +++ b/iguana/help/bitcoinrpc_move.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"move","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_move_test.py"}]} diff --git a/iguana/help/bitcoinrpc_repairwallet.json b/iguana/help/bitcoinrpc_repairwallet.json new file mode 100644 index 000000000..4b6f7f080 --- /dev/null +++ b/iguana/help/bitcoinrpc_repairwallet.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"repairwallet","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_repairwallet_test.py"}]} diff --git a/iguana/help/bitcoinrpc_sendfrom.json b/iguana/help/bitcoinrpc_sendfrom.json new file mode 100644 index 000000000..6cec10d79 --- /dev/null +++ b/iguana/help/bitcoinrpc_sendfrom.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"sendfrom","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_sendfrom_test.py"}]} diff --git a/iguana/help/bitcoinrpc_sendmany.json b/iguana/help/bitcoinrpc_sendmany.json new file mode 100644 index 000000000..5115347f4 --- /dev/null +++ b/iguana/help/bitcoinrpc_sendmany.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"sendmany","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_sendmany_test.py"}]} diff --git a/iguana/help/bitcoinrpc_sendrawtransaction.json b/iguana/help/bitcoinrpc_sendrawtransaction.json new file mode 100644 index 000000000..fa9c4182f --- /dev/null +++ b/iguana/help/bitcoinrpc_sendrawtransaction.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"sendrawtransaction","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_sendrawtransaction_test.py"}]} diff --git a/iguana/help/bitcoinrpc_sendtoaddress.json b/iguana/help/bitcoinrpc_sendtoaddress.json new file mode 100644 index 000000000..0553170c9 --- /dev/null +++ b/iguana/help/bitcoinrpc_sendtoaddress.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"sendtoaddress","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_sendtoaddress_test.py"}]} diff --git a/iguana/help/bitcoinrpc_setaccount.json b/iguana/help/bitcoinrpc_setaccount.json new file mode 100644 index 000000000..e73220bf2 --- /dev/null +++ b/iguana/help/bitcoinrpc_setaccount.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"setaccount","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_setaccount_test.py"}]} diff --git a/iguana/help/bitcoinrpc_settxfee.json b/iguana/help/bitcoinrpc_settxfee.json new file mode 100644 index 000000000..d3cc05812 --- /dev/null +++ b/iguana/help/bitcoinrpc_settxfee.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"settxfee","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_settxfee_test.py"}]} diff --git a/iguana/help/bitcoinrpc_signmessage.json b/iguana/help/bitcoinrpc_signmessage.json new file mode 100644 index 000000000..c5e335545 --- /dev/null +++ b/iguana/help/bitcoinrpc_signmessage.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"signmessage","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_signmessage_test.py"}]} diff --git a/iguana/help/bitcoinrpc_signrawtransaction.json b/iguana/help/bitcoinrpc_signrawtransaction.json new file mode 100644 index 000000000..5f693247a --- /dev/null +++ b/iguana/help/bitcoinrpc_signrawtransaction.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"signrawtransaction","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_signrawtransaction_test.py"}]} diff --git a/iguana/help/bitcoinrpc_submitblock.json b/iguana/help/bitcoinrpc_submitblock.json new file mode 100644 index 000000000..03e5c711e --- /dev/null +++ b/iguana/help/bitcoinrpc_submitblock.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"submitblock","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_submitblock_test.py"}]} diff --git a/iguana/help/bitcoinrpc_validateaddress.json b/iguana/help/bitcoinrpc_validateaddress.json new file mode 100644 index 000000000..2226a7767 --- /dev/null +++ b/iguana/help/bitcoinrpc_validateaddress.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"validateaddress","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_validateaddress_test.py"}]} diff --git a/iguana/help/bitcoinrpc_validatepubkey.json b/iguana/help/bitcoinrpc_validatepubkey.json new file mode 100644 index 000000000..bfd1d8c5b --- /dev/null +++ b/iguana/help/bitcoinrpc_validatepubkey.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"validatepubkey","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_validatepubkey_test.py"}]} diff --git a/iguana/help/bitcoinrpc_validaterawtransaction.json b/iguana/help/bitcoinrpc_validaterawtransaction.json new file mode 100644 index 000000000..ffcec8df8 --- /dev/null +++ b/iguana/help/bitcoinrpc_validaterawtransaction.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"validaterawtransaction","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_validaterawtransaction_test.py"}]} diff --git a/iguana/help/bitcoinrpc_verifymessage.json b/iguana/help/bitcoinrpc_verifymessage.json new file mode 100644 index 000000000..9cc4a7ee7 --- /dev/null +++ b/iguana/help/bitcoinrpc_verifymessage.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"verifymessage","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_verifymessage_test.py"}]} diff --git a/iguana/help/bitcoinrpc_walletlock.json b/iguana/help/bitcoinrpc_walletlock.json new file mode 100644 index 000000000..d3375ba94 --- /dev/null +++ b/iguana/help/bitcoinrpc_walletlock.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"walletlock","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_walletlock_test.py"}]} diff --git a/iguana/help/bitcoinrpc_walletpassphrase.json b/iguana/help/bitcoinrpc_walletpassphrase.json new file mode 100644 index 000000000..e196e4171 --- /dev/null +++ b/iguana/help/bitcoinrpc_walletpassphrase.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"walletpassphrase","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_walletpassphrase_test.py"}]} diff --git a/iguana/help/bitcoinrpc_walletpassphrasechange.json b/iguana/help/bitcoinrpc_walletpassphrasechange.json new file mode 100644 index 000000000..c18bc1a12 --- /dev/null +++ b/iguana/help/bitcoinrpc_walletpassphrasechange.json @@ -0,0 +1 @@ +{"agent":"bitcoinrpc","method":"walletpassphrasechange","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"bitcoinrpc_walletpassphrasechange_test.py"}]} diff --git a/iguana/help/dex_alladdresses.json b/iguana/help/dex_alladdresses.json new file mode 100644 index 000000000..71b30968d --- /dev/null +++ b/iguana/help/dex_alladdresses.json @@ -0,0 +1 @@ +{"agent":"dex","method":"alladdresses","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_alladdresses_test.py"}]} diff --git a/iguana/help/dex_checkaddress.json b/iguana/help/dex_checkaddress.json new file mode 100644 index 000000000..c651f71f9 --- /dev/null +++ b/iguana/help/dex_checkaddress.json @@ -0,0 +1 @@ +{"agent":"dex","method":"checkaddress","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_checkaddress_test.py"}]} diff --git a/iguana/help/dex_explorer.json b/iguana/help/dex_explorer.json new file mode 100644 index 000000000..f48b9eb44 --- /dev/null +++ b/iguana/help/dex_explorer.json @@ -0,0 +1 @@ +{"agent":"dex","method":"explorer","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_explorer_test.py"}]} diff --git a/iguana/help/dex_getbalance.json b/iguana/help/dex_getbalance.json new file mode 100644 index 000000000..39c086891 --- /dev/null +++ b/iguana/help/dex_getbalance.json @@ -0,0 +1 @@ +{"agent":"dex","method":"getbalance","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_getbalance_test.py"}]} diff --git a/iguana/help/dex_getbestblockhash.json b/iguana/help/dex_getbestblockhash.json new file mode 100644 index 000000000..ab3625a38 --- /dev/null +++ b/iguana/help/dex_getbestblockhash.json @@ -0,0 +1 @@ +{"agent":"dex","method":"getbestblockhash","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_getbestblockhash_test.py"}]} diff --git a/iguana/help/dex_getblock.json b/iguana/help/dex_getblock.json new file mode 100644 index 000000000..9f74e1ba6 --- /dev/null +++ b/iguana/help/dex_getblock.json @@ -0,0 +1 @@ +{"agent":"dex","method":"getblock","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_getblock_test.py"}]} diff --git a/iguana/help/dex_getblockhash.json b/iguana/help/dex_getblockhash.json new file mode 100644 index 000000000..87fbff94d --- /dev/null +++ b/iguana/help/dex_getblockhash.json @@ -0,0 +1 @@ +{"agent":"dex","method":"getblockhash","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_getblockhash_test.py"}]} diff --git a/iguana/help/dex_getinfo.json b/iguana/help/dex_getinfo.json new file mode 100644 index 000000000..89b6f79fa --- /dev/null +++ b/iguana/help/dex_getinfo.json @@ -0,0 +1 @@ +{"agent":"dex","method":"getinfo","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_getinfo_test.py"}]} diff --git a/iguana/help/dex_getmessage.json b/iguana/help/dex_getmessage.json new file mode 100644 index 000000000..4b0aa5d4e --- /dev/null +++ b/iguana/help/dex_getmessage.json @@ -0,0 +1 @@ +{"agent":"dex","method":"getmessage","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_getmessage_test.py"}]} diff --git a/iguana/help/dex_getnotaries.json b/iguana/help/dex_getnotaries.json new file mode 100644 index 000000000..b3280498e --- /dev/null +++ b/iguana/help/dex_getnotaries.json @@ -0,0 +1 @@ +{"agent":"dex","method":"getnotaries","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_getnotaries_test.py"}]} diff --git a/iguana/help/dex_gettransaction.json b/iguana/help/dex_gettransaction.json new file mode 100644 index 000000000..4b3df0094 --- /dev/null +++ b/iguana/help/dex_gettransaction.json @@ -0,0 +1 @@ +{"agent":"dex","method":"gettransaction","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_gettransaction_test.py"}]} diff --git a/iguana/help/dex_gettxin.json b/iguana/help/dex_gettxin.json new file mode 100644 index 000000000..868ffd753 --- /dev/null +++ b/iguana/help/dex_gettxin.json @@ -0,0 +1 @@ +{"agent":"dex","method":"gettxin","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_gettxin_test.py"}]} diff --git a/iguana/help/dex_gettxout.json b/iguana/help/dex_gettxout.json new file mode 100644 index 000000000..13169702d --- /dev/null +++ b/iguana/help/dex_gettxout.json @@ -0,0 +1 @@ +{"agent":"dex","method":"gettxout","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_gettxout_test.py"}]} diff --git a/iguana/help/dex_importaddress.json b/iguana/help/dex_importaddress.json new file mode 100644 index 000000000..c0961635f --- /dev/null +++ b/iguana/help/dex_importaddress.json @@ -0,0 +1 @@ +{"agent":"dex","method":"importaddress","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_importaddress_test.py"}]} diff --git a/iguana/help/dex_kvsearch.json b/iguana/help/dex_kvsearch.json new file mode 100644 index 000000000..3b3f22ac5 --- /dev/null +++ b/iguana/help/dex_kvsearch.json @@ -0,0 +1 @@ +{"agent":"dex","method":"kvsearch","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_kvsearch_test.py"}]} diff --git a/iguana/help/dex_kvupdate.json b/iguana/help/dex_kvupdate.json new file mode 100644 index 000000000..8303eaad1 --- /dev/null +++ b/iguana/help/dex_kvupdate.json @@ -0,0 +1 @@ +{"agent":"dex","method":"kvupdate","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_kvupdate_test.py"}]} diff --git a/iguana/help/dex_listspent.json b/iguana/help/dex_listspent.json new file mode 100644 index 000000000..22767b773 --- /dev/null +++ b/iguana/help/dex_listspent.json @@ -0,0 +1 @@ +{"agent":"dex","method":"listspent","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_listspent_test.py"}]} diff --git a/iguana/help/dex_listtransactions.json b/iguana/help/dex_listtransactions.json new file mode 100644 index 000000000..be95c75ff --- /dev/null +++ b/iguana/help/dex_listtransactions.json @@ -0,0 +1 @@ +{"agent":"dex","method":"listtransactions","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_listtransactions_test.py"}]} diff --git a/iguana/help/dex_listtransactions2.json b/iguana/help/dex_listtransactions2.json new file mode 100644 index 000000000..234b9b8df --- /dev/null +++ b/iguana/help/dex_listtransactions2.json @@ -0,0 +1 @@ +{"agent":"dex","method":"listtransactions2","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_listtransactions2_test.py"}]} diff --git a/iguana/help/dex_listunspent.json b/iguana/help/dex_listunspent.json new file mode 100644 index 000000000..0f50ca06e --- /dev/null +++ b/iguana/help/dex_listunspent.json @@ -0,0 +1 @@ +{"agent":"dex","method":"listunspent","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_listunspent_test.py"}]} diff --git a/iguana/help/dex_listunspent2.json b/iguana/help/dex_listunspent2.json new file mode 100644 index 000000000..9ccc2a1e4 --- /dev/null +++ b/iguana/help/dex_listunspent2.json @@ -0,0 +1 @@ +{"agent":"dex","method":"listunspent2","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_listunspent2_test.py"}]} diff --git a/iguana/help/dex_psock.json b/iguana/help/dex_psock.json new file mode 100644 index 000000000..74a3a8dfa --- /dev/null +++ b/iguana/help/dex_psock.json @@ -0,0 +1 @@ +{"agent":"dex","method":"psock","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_psock_test.py"}]} diff --git a/iguana/help/dex_send.json b/iguana/help/dex_send.json new file mode 100644 index 000000000..ccd3cc2bd --- /dev/null +++ b/iguana/help/dex_send.json @@ -0,0 +1 @@ +{"agent":"dex","method":"send","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_send_test.py"}]} diff --git a/iguana/help/dex_sendrawtransaction.json b/iguana/help/dex_sendrawtransaction.json new file mode 100644 index 000000000..20261d219 --- /dev/null +++ b/iguana/help/dex_sendrawtransaction.json @@ -0,0 +1 @@ +{"agent":"dex","method":"sendrawtransaction","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_sendrawtransaction_test.py"}]} diff --git a/iguana/help/dex_validateaddress.json b/iguana/help/dex_validateaddress.json new file mode 100644 index 000000000..7387dc024 --- /dev/null +++ b/iguana/help/dex_validateaddress.json @@ -0,0 +1 @@ +{"agent":"dex","method":"validateaddress","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dex_validateaddress_test.py"}]} diff --git a/iguana/help/dpow_active.json b/iguana/help/dpow_active.json new file mode 100644 index 000000000..b639a3ada --- /dev/null +++ b/iguana/help/dpow_active.json @@ -0,0 +1 @@ +{"agent":"dpow","method":"active","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dpow_active_test.py"}]} diff --git a/iguana/help/dpow_bindaddr.json b/iguana/help/dpow_bindaddr.json new file mode 100644 index 000000000..65f0052f7 --- /dev/null +++ b/iguana/help/dpow_bindaddr.json @@ -0,0 +1 @@ +{"agent":"dpow","method":"bindaddr","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dpow_bindaddr_test.py"}]} diff --git a/iguana/help/dpow_cancelratify.json b/iguana/help/dpow_cancelratify.json new file mode 100644 index 000000000..33a872463 --- /dev/null +++ b/iguana/help/dpow_cancelratify.json @@ -0,0 +1 @@ +{"agent":"dpow","method":"cancelratify","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dpow_cancelratify_test.py"}]} diff --git a/iguana/help/dpow_fundnotaries.json b/iguana/help/dpow_fundnotaries.json new file mode 100644 index 000000000..4e2854714 --- /dev/null +++ b/iguana/help/dpow_fundnotaries.json @@ -0,0 +1 @@ +{"agent":"dpow","method":"fundnotaries","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dpow_fundnotaries_test.py"}]} diff --git a/iguana/help/dpow_notarychains.json b/iguana/help/dpow_notarychains.json new file mode 100644 index 000000000..daee37348 --- /dev/null +++ b/iguana/help/dpow_notarychains.json @@ -0,0 +1 @@ +{"agent":"dpow","method":"notarychains","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dpow_notarychains_test.py"}]} diff --git a/iguana/help/dpow_pending.json b/iguana/help/dpow_pending.json new file mode 100644 index 000000000..1a524af58 --- /dev/null +++ b/iguana/help/dpow_pending.json @@ -0,0 +1 @@ +{"agent":"dpow","method":"pending","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dpow_pending_test.py"}]} diff --git a/iguana/help/dpow_ratify.json b/iguana/help/dpow_ratify.json new file mode 100644 index 000000000..c449a8888 --- /dev/null +++ b/iguana/help/dpow_ratify.json @@ -0,0 +1 @@ +{"agent":"dpow","method":"ratify","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"dpow_ratify_test.py"}]} diff --git a/iguana/help/hash_NXT.json b/iguana/help/hash_NXT.json new file mode 100644 index 000000000..85fae7d76 --- /dev/null +++ b/iguana/help/hash_NXT.json @@ -0,0 +1 @@ +{"agent":"hash","method":"NXT","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_NXT_test.py"}]} diff --git a/iguana/help/hash_base64_decode.json b/iguana/help/hash_base64_decode.json new file mode 100644 index 000000000..eadde2571 --- /dev/null +++ b/iguana/help/hash_base64_decode.json @@ -0,0 +1 @@ +{"agent":"hash","method":"base64_decode","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_base64_decode_test.py"}]} diff --git a/iguana/help/hash_base64_encode.json b/iguana/help/hash_base64_encode.json new file mode 100644 index 000000000..171e50200 --- /dev/null +++ b/iguana/help/hash_base64_encode.json @@ -0,0 +1 @@ +{"agent":"hash","method":"base64_encode","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_base64_encode_test.py"}]} diff --git a/iguana/help/hash_crc32.json b/iguana/help/hash_crc32.json new file mode 100644 index 000000000..3891c7bdf --- /dev/null +++ b/iguana/help/hash_crc32.json @@ -0,0 +1 @@ +{"agent":"hash","method":"crc32","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_crc32_test.py"}]} diff --git a/iguana/help/hash_curve25519.json b/iguana/help/hash_curve25519.json new file mode 100644 index 000000000..c9205f92b --- /dev/null +++ b/iguana/help/hash_curve25519.json @@ -0,0 +1 @@ +{"agent":"hash","method":"curve25519","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_curve25519_test.py"}]} diff --git a/iguana/help/hash_curve25519_pair.json b/iguana/help/hash_curve25519_pair.json new file mode 100644 index 000000000..f1e183ead --- /dev/null +++ b/iguana/help/hash_curve25519_pair.json @@ -0,0 +1 @@ +{"agent":"hash","method":"curve25519_pair","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_curve25519_pair_test.py"}]} diff --git a/iguana/help/hash_hex.json b/iguana/help/hash_hex.json new file mode 100644 index 000000000..467d9579b --- /dev/null +++ b/iguana/help/hash_hex.json @@ -0,0 +1 @@ +{"agent":"hash","method":"hex","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_hex_test.py"}]} diff --git a/iguana/help/hash_md2.json b/iguana/help/hash_md2.json new file mode 100644 index 000000000..995e6bb7f --- /dev/null +++ b/iguana/help/hash_md2.json @@ -0,0 +1 @@ +{"agent":"hash","method":"md2","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_md2_test.py"}]} diff --git a/iguana/help/hash_md4.json b/iguana/help/hash_md4.json new file mode 100644 index 000000000..696b4a22b --- /dev/null +++ b/iguana/help/hash_md4.json @@ -0,0 +1 @@ +{"agent":"hash","method":"md4","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_md4_test.py"}]} diff --git a/iguana/help/hash_md5.json b/iguana/help/hash_md5.json new file mode 100644 index 000000000..cd50b763a --- /dev/null +++ b/iguana/help/hash_md5.json @@ -0,0 +1 @@ +{"agent":"hash","method":"md5","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_md5_test.py"}]} diff --git a/iguana/help/hash_rmd128.json b/iguana/help/hash_rmd128.json new file mode 100644 index 000000000..c1fe35027 --- /dev/null +++ b/iguana/help/hash_rmd128.json @@ -0,0 +1 @@ +{"agent":"hash","method":"rmd128","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_rmd128_test.py"}]} diff --git a/iguana/help/hash_rmd160.json b/iguana/help/hash_rmd160.json new file mode 100644 index 000000000..448febe13 --- /dev/null +++ b/iguana/help/hash_rmd160.json @@ -0,0 +1 @@ +{"agent":"hash","method":"rmd160","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_rmd160_test.py"}]} diff --git a/iguana/help/hash_rmd160_sha256.json b/iguana/help/hash_rmd160_sha256.json new file mode 100644 index 000000000..d20a37caa --- /dev/null +++ b/iguana/help/hash_rmd160_sha256.json @@ -0,0 +1 @@ +{"agent":"hash","method":"rmd160_sha256","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_rmd160_sha256_test.py"}]} diff --git a/iguana/help/hash_rmd256.json b/iguana/help/hash_rmd256.json new file mode 100644 index 000000000..7b5476766 --- /dev/null +++ b/iguana/help/hash_rmd256.json @@ -0,0 +1 @@ +{"agent":"hash","method":"rmd256","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_rmd256_test.py"}]} diff --git a/iguana/help/hash_rmd320.json b/iguana/help/hash_rmd320.json new file mode 100644 index 000000000..d710f49d8 --- /dev/null +++ b/iguana/help/hash_rmd320.json @@ -0,0 +1 @@ +{"agent":"hash","method":"rmd320","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_rmd320_test.py"}]} diff --git a/iguana/help/hash_sha1.json b/iguana/help/hash_sha1.json new file mode 100644 index 000000000..03a4fe9a3 --- /dev/null +++ b/iguana/help/hash_sha1.json @@ -0,0 +1 @@ +{"agent":"hash","method":"sha1","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_sha1_test.py"}]} diff --git a/iguana/help/hash_sha224.json b/iguana/help/hash_sha224.json new file mode 100644 index 000000000..a3b3f0840 --- /dev/null +++ b/iguana/help/hash_sha224.json @@ -0,0 +1 @@ +{"agent":"hash","method":"sha224","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_sha224_test.py"}]} diff --git a/iguana/help/hash_sha256.json b/iguana/help/hash_sha256.json new file mode 100644 index 000000000..f7350d129 --- /dev/null +++ b/iguana/help/hash_sha256.json @@ -0,0 +1 @@ +{"agent":"hash","method":"sha256","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_sha256_test.py"}]} diff --git a/iguana/help/hash_sha256_sha256.json b/iguana/help/hash_sha256_sha256.json new file mode 100644 index 000000000..7f750db03 --- /dev/null +++ b/iguana/help/hash_sha256_sha256.json @@ -0,0 +1 @@ +{"agent":"hash","method":"sha256_sha256","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_sha256_sha256_test.py"}]} diff --git a/iguana/help/hash_sha384.json b/iguana/help/hash_sha384.json new file mode 100644 index 000000000..9c3a29487 --- /dev/null +++ b/iguana/help/hash_sha384.json @@ -0,0 +1 @@ +{"agent":"hash","method":"sha384","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_sha384_test.py"}]} diff --git a/iguana/help/hash_sha512.json b/iguana/help/hash_sha512.json new file mode 100644 index 000000000..1b43f3a27 --- /dev/null +++ b/iguana/help/hash_sha512.json @@ -0,0 +1 @@ +{"agent":"hash","method":"sha512","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_sha512_test.py"}]} diff --git a/iguana/help/hash_tiger192_3.json b/iguana/help/hash_tiger192_3.json new file mode 100644 index 000000000..e48f284fb --- /dev/null +++ b/iguana/help/hash_tiger192_3.json @@ -0,0 +1 @@ +{"agent":"hash","method":"tiger192_3","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_tiger192_3_test.py"}]} diff --git a/iguana/help/hash_unhex.json b/iguana/help/hash_unhex.json new file mode 100644 index 000000000..860f3c3c8 --- /dev/null +++ b/iguana/help/hash_unhex.json @@ -0,0 +1 @@ +{"agent":"hash","method":"unhex","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_unhex_test.py"}]} diff --git a/iguana/help/hash_whirlpool.json b/iguana/help/hash_whirlpool.json new file mode 100644 index 000000000..6c84f55b0 --- /dev/null +++ b/iguana/help/hash_whirlpool.json @@ -0,0 +1 @@ +{"agent":"hash","method":"whirlpool","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hash_whirlpool_test.py"}]} diff --git a/iguana/help/hmac_md2.json b/iguana/help/hmac_md2.json new file mode 100644 index 000000000..3a39c448b --- /dev/null +++ b/iguana/help/hmac_md2.json @@ -0,0 +1 @@ +{"agent":"hmac","method":"md2","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hmac_md2_test.py"}]} diff --git a/iguana/help/hmac_md4.json b/iguana/help/hmac_md4.json new file mode 100644 index 000000000..fdb646593 --- /dev/null +++ b/iguana/help/hmac_md4.json @@ -0,0 +1 @@ +{"agent":"hmac","method":"md4","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hmac_md4_test.py"}]} diff --git a/iguana/help/hmac_md5.json b/iguana/help/hmac_md5.json new file mode 100644 index 000000000..cd9021def --- /dev/null +++ b/iguana/help/hmac_md5.json @@ -0,0 +1 @@ +{"agent":"hmac","method":"md5","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hmac_md5_test.py"}]} diff --git a/iguana/help/hmac_rmd128.json b/iguana/help/hmac_rmd128.json new file mode 100644 index 000000000..a5c10722b --- /dev/null +++ b/iguana/help/hmac_rmd128.json @@ -0,0 +1 @@ +{"agent":"hmac","method":"rmd128","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hmac_rmd128_test.py"}]} diff --git a/iguana/help/hmac_rmd160.json b/iguana/help/hmac_rmd160.json new file mode 100644 index 000000000..114d560d9 --- /dev/null +++ b/iguana/help/hmac_rmd160.json @@ -0,0 +1 @@ +{"agent":"hmac","method":"rmd160","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hmac_rmd160_test.py"}]} diff --git a/iguana/help/hmac_rmd256.json b/iguana/help/hmac_rmd256.json new file mode 100644 index 000000000..836887c38 --- /dev/null +++ b/iguana/help/hmac_rmd256.json @@ -0,0 +1 @@ +{"agent":"hmac","method":"rmd256","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hmac_rmd256_test.py"}]} diff --git a/iguana/help/hmac_rmd320.json b/iguana/help/hmac_rmd320.json new file mode 100644 index 000000000..a7f0a94f8 --- /dev/null +++ b/iguana/help/hmac_rmd320.json @@ -0,0 +1 @@ +{"agent":"hmac","method":"rmd320","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hmac_rmd320_test.py"}]} diff --git a/iguana/help/hmac_sha1.json b/iguana/help/hmac_sha1.json new file mode 100644 index 000000000..beef6ef79 --- /dev/null +++ b/iguana/help/hmac_sha1.json @@ -0,0 +1 @@ +{"agent":"hmac","method":"sha1","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hmac_sha1_test.py"}]} diff --git a/iguana/help/hmac_sha224.json b/iguana/help/hmac_sha224.json new file mode 100644 index 000000000..e665184e1 --- /dev/null +++ b/iguana/help/hmac_sha224.json @@ -0,0 +1 @@ +{"agent":"hmac","method":"sha224","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hmac_sha224_test.py"}]} diff --git a/iguana/help/hmac_sha256.json b/iguana/help/hmac_sha256.json new file mode 100644 index 000000000..ae082aa6d --- /dev/null +++ b/iguana/help/hmac_sha256.json @@ -0,0 +1 @@ +{"agent":"hmac","method":"sha256","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hmac_sha256_test.py"}]} diff --git a/iguana/help/hmac_sha384.json b/iguana/help/hmac_sha384.json new file mode 100644 index 000000000..cadfef49d --- /dev/null +++ b/iguana/help/hmac_sha384.json @@ -0,0 +1 @@ +{"agent":"hmac","method":"sha384","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hmac_sha384_test.py"}]} diff --git a/iguana/help/hmac_sha512.json b/iguana/help/hmac_sha512.json new file mode 100644 index 000000000..c2aed013b --- /dev/null +++ b/iguana/help/hmac_sha512.json @@ -0,0 +1 @@ +{"agent":"hmac","method":"sha512","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hmac_sha512_test.py"}]} diff --git a/iguana/help/hmac_tiger192_3.json b/iguana/help/hmac_tiger192_3.json new file mode 100644 index 000000000..c7b776d69 --- /dev/null +++ b/iguana/help/hmac_tiger192_3.json @@ -0,0 +1 @@ +{"agent":"hmac","method":"tiger192_3","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hmac_tiger192_3_test.py"}]} diff --git a/iguana/help/hmac_whirlpool.json b/iguana/help/hmac_whirlpool.json new file mode 100644 index 000000000..b85e3940e --- /dev/null +++ b/iguana/help/hmac_whirlpool.json @@ -0,0 +1 @@ +{"agent":"hmac","method":"whirlpool","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"hmac_whirlpool_test.py"}]} diff --git a/iguana/help/iguana_PoSweights.json b/iguana/help/iguana_PoSweights.json new file mode 100644 index 000000000..d5597f13c --- /dev/null +++ b/iguana/help/iguana_PoSweights.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"PoSweights","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_PoSweights_test.py"}]} diff --git a/iguana/help/iguana_addcoin.json b/iguana/help/iguana_addcoin.json new file mode 100644 index 000000000..0bfaaf6de --- /dev/null +++ b/iguana/help/iguana_addcoin.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"addcoin","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_addcoin_test.py"}]} diff --git a/iguana/help/iguana_addnode.json b/iguana/help/iguana_addnode.json new file mode 100644 index 000000000..1dcf66ce8 --- /dev/null +++ b/iguana/help/iguana_addnode.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"addnode","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_addnode_test.py"}]} diff --git a/iguana/help/iguana_addnotary.json b/iguana/help/iguana_addnotary.json new file mode 100644 index 000000000..c57b97435 --- /dev/null +++ b/iguana/help/iguana_addnotary.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"addnotary","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_addnotary_test.py"}]} diff --git a/iguana/help/iguana_balance.json b/iguana/help/iguana_balance.json new file mode 100644 index 000000000..b84a65f42 --- /dev/null +++ b/iguana/help/iguana_balance.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"balance","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_balance_test.py"}]} diff --git a/iguana/help/iguana_bundleaddresses.json b/iguana/help/iguana_bundleaddresses.json new file mode 100644 index 000000000..f80caee90 --- /dev/null +++ b/iguana/help/iguana_bundleaddresses.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"bundleaddresses","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_bundleaddresses_test.py"}]} diff --git a/iguana/help/iguana_bundlehashes.json b/iguana/help/iguana_bundlehashes.json new file mode 100644 index 000000000..2eddf7a38 --- /dev/null +++ b/iguana/help/iguana_bundlehashes.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"bundlehashes","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_bundlehashes_test.py"}]} diff --git a/iguana/help/iguana_dividends.json b/iguana/help/iguana_dividends.json new file mode 100644 index 000000000..222489389 --- /dev/null +++ b/iguana/help/iguana_dividends.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"dividends","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_dividends_test.py"}]} diff --git a/iguana/help/iguana_dpow.json b/iguana/help/iguana_dpow.json new file mode 100644 index 000000000..6e54c8629 --- /dev/null +++ b/iguana/help/iguana_dpow.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"dpow","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_dpow_test.py"}]} diff --git a/iguana/help/iguana_getconnectioncount.json b/iguana/help/iguana_getconnectioncount.json new file mode 100644 index 000000000..4b3ee5ad7 --- /dev/null +++ b/iguana/help/iguana_getconnectioncount.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"getconnectioncount","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_getconnectioncount_test.py"}]} diff --git a/iguana/help/iguana_initfastfind.json b/iguana/help/iguana_initfastfind.json new file mode 100644 index 000000000..1de530d85 --- /dev/null +++ b/iguana/help/iguana_initfastfind.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"initfastfind","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_initfastfind_test.py"}]} diff --git a/iguana/help/iguana_makekeypair.json b/iguana/help/iguana_makekeypair.json new file mode 100644 index 000000000..1d70e412e --- /dev/null +++ b/iguana/help/iguana_makekeypair.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"makekeypair","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_makekeypair_test.py"}]} diff --git a/iguana/help/iguana_maxpeers.json b/iguana/help/iguana_maxpeers.json new file mode 100644 index 000000000..0f67ebfe4 --- /dev/null +++ b/iguana/help/iguana_maxpeers.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"maxpeers","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_maxpeers_test.py"}]} diff --git a/iguana/help/iguana_nodestatus.json b/iguana/help/iguana_nodestatus.json new file mode 100644 index 000000000..e3937827a --- /dev/null +++ b/iguana/help/iguana_nodestatus.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"nodestatus","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_nodestatus_test.py"}]} diff --git a/iguana/help/iguana_oneshot.json b/iguana/help/iguana_oneshot.json new file mode 100644 index 000000000..5157a0be7 --- /dev/null +++ b/iguana/help/iguana_oneshot.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"oneshot","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_oneshot_test.py"}]} diff --git a/iguana/help/iguana_passthru.json b/iguana/help/iguana_passthru.json new file mode 100644 index 000000000..a7203ba08 --- /dev/null +++ b/iguana/help/iguana_passthru.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"passthru","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_passthru_test.py"}]} diff --git a/iguana/help/iguana_pausecoin.json b/iguana/help/iguana_pausecoin.json new file mode 100644 index 000000000..ada16880b --- /dev/null +++ b/iguana/help/iguana_pausecoin.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"pausecoin","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_pausecoin_test.py"}]} diff --git a/iguana/help/iguana_peers.json b/iguana/help/iguana_peers.json new file mode 100644 index 000000000..75a498b7e --- /dev/null +++ b/iguana/help/iguana_peers.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"peers","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_peers_test.py"}]} diff --git a/iguana/help/iguana_persistent.json b/iguana/help/iguana_persistent.json new file mode 100644 index 000000000..14953397f --- /dev/null +++ b/iguana/help/iguana_persistent.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"persistent","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_persistent_test.py"}]} diff --git a/iguana/help/iguana_prices.json b/iguana/help/iguana_prices.json new file mode 100644 index 000000000..a1b02f625 --- /dev/null +++ b/iguana/help/iguana_prices.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"prices","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_prices_test.py"}]} diff --git a/iguana/help/iguana_rate.json b/iguana/help/iguana_rate.json new file mode 100644 index 000000000..94cfec4ab --- /dev/null +++ b/iguana/help/iguana_rate.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"rate","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_rate_test.py"}]} diff --git a/iguana/help/iguana_rates.json b/iguana/help/iguana_rates.json new file mode 100644 index 000000000..678f86b90 --- /dev/null +++ b/iguana/help/iguana_rates.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"rates","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_rates_test.py"}]} diff --git a/iguana/help/iguana_removecoin.json b/iguana/help/iguana_removecoin.json new file mode 100644 index 000000000..e33676b7f --- /dev/null +++ b/iguana/help/iguana_removecoin.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"removecoin","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_removecoin_test.py"}]} diff --git a/iguana/help/iguana_removenode.json b/iguana/help/iguana_removenode.json new file mode 100644 index 000000000..9af62606d --- /dev/null +++ b/iguana/help/iguana_removenode.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"removenode","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_removenode_test.py"}]} diff --git a/iguana/help/iguana_snapshot.json b/iguana/help/iguana_snapshot.json new file mode 100644 index 000000000..c5bd5c3c9 --- /dev/null +++ b/iguana/help/iguana_snapshot.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"snapshot","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_snapshot_test.py"}]} diff --git a/iguana/help/iguana_spendmsig.json b/iguana/help/iguana_spendmsig.json new file mode 100644 index 000000000..7e987d790 --- /dev/null +++ b/iguana/help/iguana_spendmsig.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"spendmsig","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_spendmsig_test.py"}]} diff --git a/iguana/help/iguana_splitfunds.json b/iguana/help/iguana_splitfunds.json new file mode 100644 index 000000000..bdea50ac5 --- /dev/null +++ b/iguana/help/iguana_splitfunds.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"splitfunds","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_splitfunds_test.py"}]} diff --git a/iguana/help/iguana_stakers.json b/iguana/help/iguana_stakers.json new file mode 100644 index 000000000..8fb613dd6 --- /dev/null +++ b/iguana/help/iguana_stakers.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"stakers","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_stakers_test.py"}]} diff --git a/iguana/help/iguana_startcoin.json b/iguana/help/iguana_startcoin.json new file mode 100644 index 000000000..b0a52eaf7 --- /dev/null +++ b/iguana/help/iguana_startcoin.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"startcoin","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_startcoin_test.py"}]} diff --git a/iguana/help/iguana_stopcoin.json b/iguana/help/iguana_stopcoin.json new file mode 100644 index 000000000..802470c20 --- /dev/null +++ b/iguana/help/iguana_stopcoin.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"stopcoin","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_stopcoin_test.py"}]} diff --git a/iguana/help/iguana_validate.json b/iguana/help/iguana_validate.json new file mode 100644 index 000000000..555ed8534 --- /dev/null +++ b/iguana/help/iguana_validate.json @@ -0,0 +1 @@ +{"agent":"iguana","method":"validate","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"iguana_validate_test.py"}]} diff --git a/iguana/help/jumblr_runsilent.json b/iguana/help/jumblr_runsilent.json new file mode 100644 index 000000000..071654a08 --- /dev/null +++ b/iguana/help/jumblr_runsilent.json @@ -0,0 +1 @@ +{"agent":"jumblr","method":"runsilent","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"jumblr_runsilent_test.py"}]} diff --git a/iguana/help/jumblr_setpassphrase.json b/iguana/help/jumblr_setpassphrase.json new file mode 100644 index 000000000..abb67bed0 --- /dev/null +++ b/iguana/help/jumblr_setpassphrase.json @@ -0,0 +1 @@ +{"agent":"jumblr","method":"setpassphrase","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"jumblr_setpassphrase_test.py"}]} diff --git a/iguana/help/jumblr_status.json b/iguana/help/jumblr_status.json new file mode 100644 index 000000000..a245ba5db --- /dev/null +++ b/iguana/help/jumblr_status.json @@ -0,0 +1 @@ +{"agent":"jumblr","method":"status","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"jumblr_status_test.py"}]} diff --git a/iguana/help/jumblr_totransparent.json b/iguana/help/jumblr_totransparent.json new file mode 100644 index 000000000..22d1f678d --- /dev/null +++ b/iguana/help/jumblr_totransparent.json @@ -0,0 +1 @@ +{"agent":"jumblr","method":"totransparent","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"jumblr_totransparent_test.py"}]} diff --git a/iguana/help/keyboard_key.json b/iguana/help/keyboard_key.json new file mode 100644 index 000000000..941a0517f --- /dev/null +++ b/iguana/help/keyboard_key.json @@ -0,0 +1 @@ +{"agent":"keyboard","method":"key","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"keyboard_key_test.py"}]} diff --git a/iguana/help/komodo_passthru.json b/iguana/help/komodo_passthru.json new file mode 100644 index 000000000..91e0fc86c --- /dev/null +++ b/iguana/help/komodo_passthru.json @@ -0,0 +1 @@ +{"agent":"komodo","method":"passthru","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"komodo_passthru_test.py"}]} diff --git a/iguana/help/mouse_change.json b/iguana/help/mouse_change.json new file mode 100644 index 000000000..e94100130 --- /dev/null +++ b/iguana/help/mouse_change.json @@ -0,0 +1 @@ +{"agent":"mouse","method":"change","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"mouse_change_test.py"}]} diff --git a/iguana/help/mouse_click.json b/iguana/help/mouse_click.json new file mode 100644 index 000000000..5400603ea --- /dev/null +++ b/iguana/help/mouse_click.json @@ -0,0 +1 @@ +{"agent":"mouse","method":"click","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"mouse_click_test.py"}]} diff --git a/iguana/help/mouse_close.json b/iguana/help/mouse_close.json new file mode 100644 index 000000000..465a680c4 --- /dev/null +++ b/iguana/help/mouse_close.json @@ -0,0 +1 @@ +{"agent":"mouse","method":"close","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"mouse_close_test.py"}]} diff --git a/iguana/help/mouse_image.json b/iguana/help/mouse_image.json new file mode 100644 index 000000000..0fe91b3b0 --- /dev/null +++ b/iguana/help/mouse_image.json @@ -0,0 +1 @@ +{"agent":"mouse","method":"image","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"mouse_image_test.py"}]} diff --git a/iguana/help/mouse_leave.json b/iguana/help/mouse_leave.json new file mode 100644 index 000000000..0102f7c1e --- /dev/null +++ b/iguana/help/mouse_leave.json @@ -0,0 +1 @@ +{"agent":"mouse","method":"leave","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"mouse_leave_test.py"}]} diff --git a/iguana/help/passthru_paxfiats.json b/iguana/help/passthru_paxfiats.json new file mode 100644 index 000000000..48b2d7b57 --- /dev/null +++ b/iguana/help/passthru_paxfiats.json @@ -0,0 +1 @@ +{"agent":"passthru","method":"paxfiats","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"passthru_paxfiats_test.py"}]} diff --git a/iguana/help/pax_start.json b/iguana/help/pax_start.json new file mode 100644 index 000000000..1f053e4f3 --- /dev/null +++ b/iguana/help/pax_start.json @@ -0,0 +1 @@ +{"agent":"pax","method":"start","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"pax_start_test.py"}]} diff --git a/iguana/help/tradebot_accumulate.json b/iguana/help/tradebot_accumulate.json new file mode 100644 index 000000000..e46ec03c3 --- /dev/null +++ b/iguana/help/tradebot_accumulate.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"accumulate","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_accumulate_test.py"}]} diff --git a/iguana/help/tradebot_activebots.json b/iguana/help/tradebot_activebots.json new file mode 100644 index 000000000..1eb5e73e3 --- /dev/null +++ b/iguana/help/tradebot_activebots.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"activebots","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_activebots_test.py"}]} diff --git a/iguana/help/tradebot_allbalances.json b/iguana/help/tradebot_allbalances.json new file mode 100644 index 000000000..93c51ec2b --- /dev/null +++ b/iguana/help/tradebot_allbalances.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"allbalances","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_allbalances_test.py"}]} diff --git a/iguana/help/tradebot_amlp.json b/iguana/help/tradebot_amlp.json new file mode 100644 index 000000000..35f83ec0d --- /dev/null +++ b/iguana/help/tradebot_amlp.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"amlp","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_amlp_test.py"}]} diff --git a/iguana/help/tradebot_anchor.json b/iguana/help/tradebot_anchor.json new file mode 100644 index 000000000..22a7256ae --- /dev/null +++ b/iguana/help/tradebot_anchor.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"anchor","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_anchor_test.py"}]} diff --git a/iguana/help/tradebot_aveprice.json b/iguana/help/tradebot_aveprice.json new file mode 100644 index 000000000..74f8bc1ab --- /dev/null +++ b/iguana/help/tradebot_aveprice.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"aveprice","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_aveprice_test.py"}]} diff --git a/iguana/help/tradebot_divest.json b/iguana/help/tradebot_divest.json new file mode 100644 index 000000000..013d6b795 --- /dev/null +++ b/iguana/help/tradebot_divest.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"divest","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_divest_test.py"}]} diff --git a/iguana/help/tradebot_gensvm.json b/iguana/help/tradebot_gensvm.json new file mode 100644 index 000000000..445aad5db --- /dev/null +++ b/iguana/help/tradebot_gensvm.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"gensvm","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_gensvm_test.py"}]} diff --git a/iguana/help/tradebot_goals.json b/iguana/help/tradebot_goals.json new file mode 100644 index 000000000..eadeab3f1 --- /dev/null +++ b/iguana/help/tradebot_goals.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"goals","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_goals_test.py"}]} diff --git a/iguana/help/tradebot_liquidity.json b/iguana/help/tradebot_liquidity.json new file mode 100644 index 000000000..dc1461790 --- /dev/null +++ b/iguana/help/tradebot_liquidity.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"liquidity","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_liquidity_test.py"}]} diff --git a/iguana/help/tradebot_monitor.json b/iguana/help/tradebot_monitor.json new file mode 100644 index 000000000..31df1db48 --- /dev/null +++ b/iguana/help/tradebot_monitor.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"monitor","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_monitor_test.py"}]} diff --git a/iguana/help/tradebot_monitorall.json b/iguana/help/tradebot_monitorall.json new file mode 100644 index 000000000..16ea650ae --- /dev/null +++ b/iguana/help/tradebot_monitorall.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"monitorall","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_monitorall_test.py"}]} diff --git a/iguana/help/tradebot_notlp.json b/iguana/help/tradebot_notlp.json new file mode 100644 index 000000000..ed462ecf4 --- /dev/null +++ b/iguana/help/tradebot_notlp.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"notlp","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_notlp_test.py"}]} diff --git a/iguana/help/tradebot_openliquidity.json b/iguana/help/tradebot_openliquidity.json new file mode 100644 index 000000000..961e6f424 --- /dev/null +++ b/iguana/help/tradebot_openliquidity.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"openliquidity","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_openliquidity_test.py"}]} diff --git a/iguana/help/tradebot_pause.json b/iguana/help/tradebot_pause.json new file mode 100644 index 000000000..81c641f28 --- /dev/null +++ b/iguana/help/tradebot_pause.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"pause","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_pause_test.py"}]} diff --git a/iguana/help/tradebot_portfolio.json b/iguana/help/tradebot_portfolio.json new file mode 100644 index 000000000..50b646579 --- /dev/null +++ b/iguana/help/tradebot_portfolio.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"portfolio","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_portfolio_test.py"}]} diff --git a/iguana/help/tradebot_resume.json b/iguana/help/tradebot_resume.json new file mode 100644 index 000000000..745666320 --- /dev/null +++ b/iguana/help/tradebot_resume.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"resume","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_resume_test.py"}]} diff --git a/iguana/help/tradebot_status.json b/iguana/help/tradebot_status.json new file mode 100644 index 000000000..1289541a5 --- /dev/null +++ b/iguana/help/tradebot_status.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"status","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_status_test.py"}]} diff --git a/iguana/help/tradebot_stop.json b/iguana/help/tradebot_stop.json new file mode 100644 index 000000000..d948d48c6 --- /dev/null +++ b/iguana/help/tradebot_stop.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"stop","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_stop_test.py"}]} diff --git a/iguana/help/tradebot_unmonitor.json b/iguana/help/tradebot_unmonitor.json new file mode 100644 index 000000000..992a768ef --- /dev/null +++ b/iguana/help/tradebot_unmonitor.json @@ -0,0 +1 @@ +{"agent":"tradebot","method":"unmonitor","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"tradebot_unmonitor_test.py"}]} diff --git a/iguana/help/zcash_passthru.json b/iguana/help/zcash_passthru.json new file mode 100644 index 000000000..657b16dfd --- /dev/null +++ b/iguana/help/zcash_passthru.json @@ -0,0 +1 @@ +{"agent":"zcash","method":"passthru","field0":"put in helpful info field0","field1":"put in helpful info for field1","help":"put helpful info here","teststatus":[{"tester":"bob","result":"put result here","notes":"put useful notes here","automated":"notyet","sourcefile":"zcash_passthru_test.py"}]} diff --git a/iguana/iguana_exchanges.c b/iguana/iguana_exchanges.c index d7445f681..d2cd1c267 100755 --- a/iguana/iguana_exchanges.c +++ b/iguana/iguana_exchanges.c @@ -784,7 +784,8 @@ void exchanges777_loop(void *ptr) printf("exchanges loop.(%s)\n",exchange->name); while ( 1 ) { - PAX_idle(myinfo); + if ( strcmp("bitcoin",exchange->name) == 0 ) + PAX_idle(myinfo); flag = retval = 0; retstr = 0; if ( (req= queue_dequeue(&exchange->requestQ)) != 0 ) diff --git a/iguana/iguana_mofn.c b/iguana/iguana_mofn.c index 2756def45..b4d34230d 100755 --- a/iguana/iguana_mofn.c +++ b/iguana/iguana_mofn.c @@ -238,6 +238,15 @@ int32_t gfshare_test(struct supernet_info *myinfo,int32_t M,int32_t N,int32_t da return ok!=1; } +void *bitcoin_ctx() +{ + void *ptr; + ptr = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + secp256k1_pedersen_context_initialize(ptr); + secp256k1_rangeproof_context_initialize(ptr); + return(ptr); +} + void iguana_fixsecp(struct supernet_info *myinfo) { myinfo->ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); diff --git a/iguana/iguana_notary.c b/iguana/iguana_notary.c index fe9d14c60..c8808191b 100755 --- a/iguana/iguana_notary.c +++ b/iguana/iguana_notary.c @@ -58,9 +58,84 @@ void dpow_checkpointset(struct supernet_info *myinfo,struct dpow_checkpoint *che checkpoint->blockhash.height = height; } +int32_t dpow_txhasnotarization(struct supernet_info *myinfo,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= dpow_gettransaction(myinfo,coin,txid)) != 0 ) + { + if ( (vins= jarray(&numvins,txobj,"vin")) != 0 ) + { + if ( numvins >= DPOW_MIN_ASSETCHAIN_SIGS ) + { + notarymask = numnotaries = 0; + for (i=0; i>= 1; + decode_hex(script,len,hexstr); + if ( script[0] == 33 && script[34] == 0xac ) + { + for (j=0; j 0 ) + { + if ( numnotaries >= DPOW_MIN_ASSETCHAIN_SIGS ) + hasnotarization = 1; + printf("numnotaries.%d %s hasnotarization.%d\n",numnotaries,coin->symbol,hasnotarization); + } + } + } + free_json(txobj); + } + return(hasnotarization); +} + +int32_t dpow_hasnotarization(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *blockjson) +{ + int32_t i,n,hasnotarization = 0; bits256 txid; cJSON *txarray; + if ( (txarray= jarray(&n,blockjson,"tx")) != 0 ) + { + for (i=0; ilast,height,hash,timestamp,blocktime); checkpoint = dp->srcfifo[dp->srcconfirms]; if ( strcmp("BTC",dp->dest) == 0 ) @@ -70,25 +145,64 @@ void dpow_srcupdate(struct supernet_info *myinfo,struct dpow_info *dp,int32_t he } else { - freq = 1; - //minsigs = 7;//(komodo_notaries(dp->symbol,pubkeys,height) >> 1) + 1; - //if ( minsigs < DPOW_MINSIGS ) - minsigs = DPOW_MINSIGS; + minsigs = DPOW_MIN_ASSETCHAIN_SIGS; + if ( strcmp("CHIPS",dp->symbol) == 0 ) + freq = 100; + else freq = 1; } - printf("%s/%s src ht.%d dest.%u nonz.%d %s minsigs.%d\n",dp->symbol,dp->dest,checkpoint.blockhash.height,dp->destupdated,bits256_nonz(checkpoint.blockhash.hash),bits256_str(str,dp->last.blockhash.hash),minsigs); dpow_fifoupdate(myinfo,dp->srcfifo,dp->last); - if ( dp->SRCREALTIME == 0 && strcmp(dp->dest,"KMD") == 0 ) - return; + if ( strcmp(dp->dest,"KMD") == 0 ) + { + //if ( dp->SRCREALTIME == 0 ) + // return; + if ( (coin= iguana_coinfind(dp->symbol)) != 0 ) + { + hash = dpow_getbestblockhash(myinfo,coin); + if ( bits256_nonz(hash) != 0 ) + { + if ( (blockjson= dpow_getblock(myinfo,coin,hash)) != 0 ) + { + if ( dpow_hasnotarization(myinfo,coin,blockjson) <= 0 ) + { + height = jint(blockjson,"height"); + blocktime = juint(blockjson,"time"); + free_json(blockjson); + if ( height > 0 && blocktime > 0 ) + { + dpow_checkpointset(myinfo,&dp->last,height,hash,timestamp,blocktime); + //printf("dynamic set %s/%s %s <- height.%d\n",dp->symbol,dp->dest,bits256_str(str,hash),height); + checkpoint = dp->last; + } else return; + if ( bits256_nonz(dp->activehash) != 0 && bits256_cmp(dp->activehash,checkpoint.blockhash.hash) == 0 ) + { + printf("activehash.(%s) is current checkpoint, skip\n",bits256_str(str,dp->activehash)); + return; + } + else if ( bits256_nonz(dp->lastnotarized) != 0 && bits256_cmp(dp->lastnotarized,checkpoint.blockhash.hash) == 0 ) + { + printf("lastnotarized.(%s) is current checkpoint, skip\n",bits256_str(str,dp->lastnotarized)); + return; + } + //printf("checkpoint.(%s) is not active and not lastnotarized\n",bits256_str(str,checkpoint.blockhash.hash)); + } else return; + } else return; + } else return; + } else return; + } if ( bits256_nonz(checkpoint.blockhash.hash) != 0 && (checkpoint.blockhash.height % freq) == 0 ) { + //printf("%s/%s src ht.%d dest.%u nonz.%d %s minsigs.%d\n",dp->symbol,dp->dest,checkpoint.blockhash.height,dp->destupdated,bits256_nonz(checkpoint.blockhash.hash),bits256_str(str,dp->last.blockhash.hash),minsigs); dpow_heightfind(myinfo,dp,checkpoint.blockhash.height + 1000); ptrs = calloc(1,sizeof(void *)*5 + sizeof(struct dpow_checkpoint)); ptrs[0] = (void *)myinfo; ptrs[1] = (void *)dp; ptrs[2] = (void *)(uint64_t)minsigs; - ptrs[3] = (void *)DPOW_DURATION; + if ( strcmp(dp->dest,"KMD") == 0 ) + ptrs[3] = (void *)(DPOW_DURATION * 60); // essentially try forever for assetchains + else ptrs[3] = (void *)DPOW_DURATION; ptrs[4] = 0; memcpy(&ptrs[5],&checkpoint,sizeof(checkpoint)); + dp->activehash = checkpoint.blockhash.hash; if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)dpow_statemachinestart,(void *)ptrs) != 0 ) { } @@ -160,7 +274,7 @@ void iguana_dPoWupdate(struct supernet_info *myinfo,struct dpow_info *dp) if ( (height= dpow_getchaintip(myinfo,&blockhash,&blocktime,dp->desttx,&dp->numdesttx,dest)) != dp->destchaintip.blockhash.height && height >= 0 ) { char str[65]; - if ( strcmp(dp->symbol,"KMD") == 0 || height != dp->destchaintip.blockhash.height+1 ) + if ( strcmp(dp->symbol,"KMD") == 0 )//|| height != dp->destchaintip.blockhash.height+1 ) printf("[%s].%d %s %s height.%d vs last.%d\n",dp->symbol,dp->SRCHEIGHT,dp->dest,bits256_str(str,blockhash),height,dp->destchaintip.blockhash.height); if ( height <= dp->destchaintip.blockhash.height ) { @@ -178,7 +292,7 @@ void iguana_dPoWupdate(struct supernet_info *myinfo,struct dpow_info *dp) } if ( (height= dpow_getchaintip(myinfo,&blockhash,&blocktime,dp->srctx,&dp->numsrctx,src)) != dp->last.blockhash.height && height >= 0 ) { - char str[65]; printf("[%s].%d %s %s height.%d vs last.%d\n",dp->dest,dp->SRCHEIGHT,dp->symbol,bits256_str(str,blockhash),height,dp->last.blockhash.height); + //char str[65]; printf("[%s].%d %s %s height.%d vs last.%d\n",dp->dest,dp->SRCHEIGHT,dp->symbol,bits256_str(str,blockhash),height,dp->last.blockhash.height); if ( dp->lastheight == 0 ) dp->lastheight = height-1; if ( height < dp->last.blockhash.height ) @@ -198,7 +312,7 @@ void iguana_dPoWupdate(struct supernet_info *myinfo,struct dpow_info *dp) } } } - else + else if ( strcmp(dp->symbol,"KMD") == 0 ) { while ( dp->lastheight <= height ) { @@ -206,6 +320,13 @@ void iguana_dPoWupdate(struct supernet_info *myinfo,struct dpow_info *dp) dpow_srcupdate(myinfo,dp,dp->lastheight++,blockhash,(uint32_t)time(NULL),blocktime); } } + else if ( time(NULL) > dp->lastsrcupdate+60 || height != dp->lastheight ) + { + dp->lastsrcupdate = (uint32_t)time(NULL); + dp->lastheight = height; + blockhash = dpow_getblockhash(myinfo,src,dp->lastheight); + dpow_srcupdate(myinfo,dp,dp->lastheight,blockhash,(uint32_t)time(NULL),blocktime); + } } //else printf("error getchaintip for %s\n",dp->symbol); } else printf("iguana_dPoWupdate missing src.(%s) %p or dest.(%s) %p\n",dp->symbol,src,dp->dest,dest); } @@ -437,7 +558,7 @@ STRING_ARG(iguana,addnotary,ipaddr) char NOTARY_CURRENCIES[][16] = { "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", "CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", - "REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "SHARK", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "LTC" }; + "REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "SHARK", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "MNZ", "CHIPS" }; // "LTC", ZERO_ARGS(dpow,notarychains) { diff --git a/iguana/iguana_payments.c b/iguana/iguana_payments.c index a5b2876cf..cbc23aa6c 100755 --- a/iguana/iguana_payments.c +++ b/iguana/iguana_payments.c @@ -344,7 +344,8 @@ bits256 iguana_sendrawtransaction(struct supernet_info *myinfo,struct iguana_inf uint64_t _iguana_interest(uint32_t now,int32_t txheight,uint32_t txlocktime,uint64_t value) { int32_t minutes; uint64_t numerator=0,denominator=0,interest=0; uint32_t activation = 1491350400; - + if ( txheight >= 7777777 ) + return(0); if ( (minutes= ((uint32_t)time(NULL) - 60 - txlocktime) / 60) >= 60 ) { if ( minutes > 365 * 24 * 60 ) diff --git a/iguana/iguana_peers.c b/iguana/iguana_peers.c index c5ed454bd..8fd57e8a7 100755 --- a/iguana/iguana_peers.c +++ b/iguana/iguana_peers.c @@ -488,6 +488,7 @@ int32_t iguana_socket(int32_t bindflag,char *hostname,uint16_t port) { sleep(1); printf("ERROR BINDING PORT.%d. this is normal tcp timeout, unless another process is using port\n",port); + fflush(stdout); sleep(3); printf("%s(%s) port.%d try again: %s sock.%d. errno.%d\n",bindflag!=0?"bind":"connect",hostname,port,strerror(errno),sock,errno); if ( bindflag == 1 ) diff --git a/iguana/iguana_rpc.c b/iguana/iguana_rpc.c index 554624dc2..d79aefe24 100755 --- a/iguana/iguana_rpc.c +++ b/iguana/iguana_rpc.c @@ -1170,6 +1170,7 @@ void iguana_rpcloop(void *args) sleep(3); } printf(">>>>>>>>>> iguana_rpcloop 127.0.0.1:%d bind sock.%d iguana API enabled <<<<<<<<<\n",port,bindsock); + fflush(stdout); space = calloc(1,size); while ( bindsock >= 0 ) { diff --git a/iguana/kmd_lookup.h b/iguana/kmd_lookup.h index 61f7f60b0..05cb91ad4 100755 --- a/iguana/kmd_lookup.h +++ b/iguana/kmd_lookup.h @@ -668,7 +668,7 @@ int32_t _kmd_bitcoinscan(struct iguana_info *coin) { if ( bits256_cmp(txid,jbits256(txjson,"txid")) != 0 ) { - printf("txid mismatch error ht.%d i.%d\n",loadheight,i); + printf("%s txid mismatch error ht.%d i.%d\n",coin->symbol,loadheight,i); continue; } vouts = jarray(&numvouts,txjson,"vout"); diff --git a/iguana/m_mm b/iguana/m_mm index b5ba405ca..36a0acad1 100755 --- a/iguana/m_mm +++ b/iguana/m_mm @@ -1,3 +1,3 @@ cd secp256k1; ./m_unix; cd .. cd ../crypto777; ./m_LP; cd ../iguana -gcc -g -o marketmaker -I../crypto777 exchanges/mm.c mini-gmp.c secp256k1.o ../agents/libcrypto777.a -lnanomsg -lcurl -lpthread -lm +gcc -g -o marketmaker -I../crypto777 exchanges/mm.c ../crypto777/cJSON.c mini-gmp.c secp256k1.o ../agents/libcrypto777.a -lnanomsg -lcurl -lpthread -lm diff --git a/iguana/m_notary b/iguana/m_notary index d2c82c7c0..9a4fbb305 100755 --- a/iguana/m_notary +++ b/iguana/m_notary @@ -22,6 +22,7 @@ tests/addnotarys_7776 coins/btc_7776 coins/ltc_7776 coins/kmd_7776 +coins/chips_7776 ./wp_7776 coins/revs_7776 @@ -41,6 +42,7 @@ coins/wlc_7776 coins/kv_7776 coins/ceal_7776 coins/mesh_7776 +coins/mnz_7776 curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"passthru\",\"method\":\"paxfiats\",\"timeout\":900000}" #curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"$myip\"}" diff --git a/iguana/m_splitfund b/iguana/m_splitfund index dbaf4cb51..342f8e6de 100755 --- a/iguana/m_splitfund +++ b/iguana/m_splitfund @@ -22,6 +22,7 @@ curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"WLC\",\"agent\":\"iguana\ curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"KV\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CEAL\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MESH\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MNZ\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"USD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"EUR\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" diff --git a/iguana/main.c b/iguana/main.c index 335d68baa..85510c3fb 100755 --- a/iguana/main.c +++ b/iguana/main.c @@ -71,13 +71,17 @@ int32_t SuperNET_str2hex(uint8_t *hex,char *str) void SuperNET_hex2str(char *str,uint8_t *hex,int32_t len) { - init_hexbytes_noT(str,hex,len); + init_hexbytes_noT(str,hex,len); } +void *bitcoin_ctx(); struct supernet_info *SuperNET_MYINFO(char *passphrase) { + //int32_t i; if ( MYINFO.ctx == 0 ) { + //for (i=0; iallcoins,coin,tmp) { if ( coin != 0 && coin->symbol[0] != 0 ) diff --git a/includes/cJSON.h b/includes/cJSON.h index 77e0752e6..3ecdadc69 100755 --- a/includes/cJSON.h +++ b/includes/cJSON.h @@ -73,6 +73,7 @@ extern "C" double valuedouble; /* The item's number, if type==cJSON_Number */ char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ + uint32_t cjsonid; } cJSON; typedef struct cJSON_Hooks { @@ -218,6 +219,8 @@ extern "C" char *nxt64str2(uint64_t nxt64bits); cJSON *addrs_jsonarray(uint64_t *addrs,int32_t num); int32_t myatoi(char *str,int32_t range); + void cJSON_register(cJSON *item); + void cJSON_unregister(cJSON *item); char *stringifyM(char *str); #define replace_backslashquotes unstringify diff --git a/includes/iguana_structs.h b/includes/iguana_structs.h index 3becc3b26..e9fd52383 100755 --- a/includes/iguana_structs.h +++ b/includes/iguana_structs.h @@ -252,7 +252,7 @@ struct iguana_counts struct iguana_blocks { - char coin[8]; + char coin[16]; struct iguanakv *db; struct iguana_block *hash; int32_t maxblocks,initblocks,hashblocks,pending,issuedblocks,recvblocks,emitblocks,parsedblocks,dirty; @@ -414,7 +414,7 @@ struct basilisk_spend { bits256 txid,spentfrom; uint64_t relaymask,value; uint32 struct basilisk_unspent { bits256 txid; uint64_t value,relaymask; uint32_t unspentind,timestamp; int32_t RTheight,height,spentheight; int16_t status,hdrsi,vout,spendlen; char symbol[16]; uint8_t script[256]; }; -struct iguana_waddress { UT_hash_handle hh; uint64_t balance; uint16_t scriptlen; uint8_t rmd160[20],pubkey[33],wiftype,addrtype; bits256 privkey; char symbol[8],coinaddr[36],wifstr[54]; uint8_t redeemScript[]; }; +struct iguana_waddress { UT_hash_handle hh; uint64_t balance; uint16_t scriptlen; uint8_t rmd160[20],pubkey[33],wiftype,addrtype; bits256 privkey; char symbol[16],coinaddr[36],wifstr[54]; uint8_t redeemScript[]; }; struct iguana_waccount { UT_hash_handle hh; struct iguana_waddress *waddr,*current; char account[]; }; struct iguana_wallet { UT_hash_handle hh; struct iguana_waccount *wacct; }; diff --git a/marketmaker.sln b/marketmaker.sln new file mode 100644 index 000000000..98097205c --- /dev/null +++ b/marketmaker.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "marketmaker", "marketmaker.vcxproj", "{BE4A118A-115D-44B5-B9D9-AD17C1C1AAE8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BE4A118A-115D-44B5-B9D9-AD17C1C1AAE8}.Debug|x64.ActiveCfg = Debug|x64 + {BE4A118A-115D-44B5-B9D9-AD17C1C1AAE8}.Debug|x64.Build.0 = Debug|x64 + {BE4A118A-115D-44B5-B9D9-AD17C1C1AAE8}.Debug|x86.ActiveCfg = Debug|Win32 + {BE4A118A-115D-44B5-B9D9-AD17C1C1AAE8}.Debug|x86.Build.0 = Debug|Win32 + {BE4A118A-115D-44B5-B9D9-AD17C1C1AAE8}.Release|x64.ActiveCfg = Release|x64 + {BE4A118A-115D-44B5-B9D9-AD17C1C1AAE8}.Release|x64.Build.0 = Release|x64 + {BE4A118A-115D-44B5-B9D9-AD17C1C1AAE8}.Release|x86.ActiveCfg = Release|Win32 + {BE4A118A-115D-44B5-B9D9-AD17C1C1AAE8}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/marketmaker.vcxproj b/marketmaker.vcxproj new file mode 100644 index 000000000..7d3862568 --- /dev/null +++ b/marketmaker.vcxproj @@ -0,0 +1,258 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {BE4A118A-115D-44B5-B9D9-AD17C1C1AAE8} + Win32Proj + + + + Application + true + v140 + + + Application + false + v140 + + + Application + true + v140 + + + Application + false + v140 + + + + + + + + + + + + + + + + + + + + + true + $(ProjectDir)\includes;$(ProjectDir)\includes\curl;$(IncludePath) + $(ProjectDir)\OSlibs\win;$(LibraryPath) + + + true + $(SolutionDir)/includes;$(SolutionDir)/includes/curl;$(IncludePath) + + + false + $(ProjectDir)\includes;$(ProjectDir)\includes\curl;$(IncludePath) + $(ProjectDir)\OSlibs\win;$(LibraryPath) + + + false + false + $(ProjectDir)\includes;$(ProjectDir)\includes\curl;$(IncludePath) + + + + + + Level2 + Disabled + _CRT_SECURE_NO_WARNINGS;NATIVE_WINDOWS;WIN32;_DEBUG;_CONSOLE;IGUANA_LOG2PACKETSIZE=20;IGUANA_MAXPACKETSIZE=1572864;%(PreprocessorDefinitions) + 8Bytes + .\iguana;%(AdditionalIncludeDirectories) + + + Console + true + Ws2_32.lib;pthreadVC2.lib;nanomsg.lib;libcurl.lib;%(AdditionalDependencies) + .\iguana;.\OSlibs\win;%(AdditionalLibraryDirectories) + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;NATIVE_WINDOWS;WIN32;IGUANA_LOG2PACKETSIZE=20;IGUANA_MAXPACKETSIZE=1572864;%(PreprocessorDefinitions) + 8Bytes + + + Console + true + .\OSlibs\win\x64;%(AdditionalLibraryDirectories) + pthread_lib.lib;Ws2_32.lib;nanomsg.lib;libcurl.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NATIVE_WINDOWS;WIN32;_CONSOLE;NDEBUG;IGUANA_LOG2PACKETSIZE=20;IGUANA_MAXPACKETSIZE=1572864;%(PreprocessorDefinitions) + 8Bytes + + + MachineX86 + true + Console + true + true + Ws2_32.lib;Advapi32.lib;$(SolutionDir)OSlibs\win\release\pthreadVC2.lib;libcurl.lib;nanomsg.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;_WIN64;_CRT_SECURE_NO_WARNINGS;NATIVE_WINDOWS;WIN32;WIN32_LEAN_AND_MEAN;_CONSOLE;NDEBUG;IGUANA_LOG2PACKETSIZE=20;IGUANA_MAXPACKETSIZE=1572864;%(PreprocessorDefinitions) + 8Bytes + MultiThreaded + + + Console + true + true + true + Ws2_32.lib;Advapi32.lib;$(SolutionDir)OSlibs\win\x64\pthread_lib.lib;libcurl.lib;nanomsg.lib;%(AdditionalDependencies) + .\OSlibs\win\x64\release;%(AdditionalLibraryDirectories) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/marketmaker.vcxproj.filters b/marketmaker.vcxproj.filters new file mode 100644 index 000000000..7875d7cf3 --- /dev/null +++ b/marketmaker.vcxproj.filters @@ -0,0 +1,297 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + + \ No newline at end of file diff --git a/marketmaker_build_32_64.cmd b/marketmaker_build_32_64.cmd new file mode 100644 index 000000000..730081702 --- /dev/null +++ b/marketmaker_build_32_64.cmd @@ -0,0 +1,82 @@ +@echo off + +@REM Check for Visual Studio +call set "VSPATH=" +if defined VS140COMNTOOLS ( if not defined VSPATH ( + call set "VSPATH=%%VS140COMNTOOLS%%" +) ) + +@REM check if we already have the tools in the environment +if exist "%VCINSTALLDIR%" ( + goto compile +) + +if not defined VSPATH ( + echo You need Microsoft Visual Studio 15 installed + pause + exit +) + +@REM set up the environment +if exist "%VSPATH%..\..\vc\vcvarsall.bat" ( + call "%%VSPATH%%..\..\vc\vcvarsall.bat" amd64 + goto compile +) + +echo Unable to set up the environment +pause +exit + +:compile +rem MSBuild /help +MSBuild marketmaker.sln /t:Rebuild /p:Configuration=Release /p:Platform=x64 +MSBuild marketmaker.sln /t:Rebuild /p:Configuration=Release /p:Platform=x86 + +rem Obtain version number and latest git commit number + +FOR /F "tokens=* USEBACKQ" %%F IN (`find /i "LP_MAJOR_VERSION" "iguana\exchanges\LP_include.h"`) DO ( +SET LP_MAJOR_VERSION_STR=%%F +) +FOR /F "tokens=* USEBACKQ" %%F IN (`find /i "LP_MINOR_VERSION" "iguana\exchanges\LP_include.h"`) DO ( +SET LP_MINOR_VERSION_STR=%%F +) +FOR /F "tokens=* USEBACKQ" %%F IN (`find /i "LP_BUILD_NUMBER" "iguana\exchanges\LP_include.h"`) DO ( +SET LP_BUILD_NUMBER_STR=%%F +) + +for /f delims^=^"^ tokens^=2 %%a in ('echo %LP_MAJOR_VERSION_STR%') do ( +set LP_MAJOR_VERSION=%%a +) +for /f delims^=^"^ tokens^=2 %%a in ('echo %LP_MINOR_VERSION_STR%') do ( +set LP_MINOR_VERSION=%%a +) +for /f delims^=^"^ tokens^=2 %%a in ('echo %LP_BUILD_NUMBER_STR%') do ( +set LP_BUILD_NUMBER=%%a +) + +rem Check if git command exist and if does - receive latest GIT_COMMIT +git --version >nul 2>&1 && ( + for /f "tokens=1" %%a in ('git rev-parse --short HEAD') do ( + set GIT_COMMIT=_%%a + ) +) || ( + set GIT_COMMIT= +) + +rem echo Marketmaker_%LP_MAJOR_VERSION%.%LP_MINOR_VERSION%_%LP_BUILD_NUMBER%%GIT_COMMIT% + +rem Using to add in marketmaker_release.7z +set host=%COMPUTERNAME% +IF "%host%"=="VM-81" ( + mkdir package_content\win32 + mkdir package_content\win64 + copy /y Release\marketmaker.exe package_content\win32 + copy /y x64\Release\marketmaker.exe package_content\win64 + echo Marketmaker_%LP_MAJOR_VERSION%.%LP_MINOR_VERSION%_%LP_BUILD_NUMBER%%GIT_COMMIT% > package_content\version.txt + cd package_content + "C:\Program Files\7-Zip\7z.exe" a C:\komodo\marketmaker_release\marketmaker_release.7z win32\marketmaker.exe + "C:\Program Files\7-Zip\7z.exe" a C:\komodo\marketmaker_release\marketmaker_release.7z win64\marketmaker.exe + "C:\Program Files\7-Zip\7z.exe" a C:\komodo\marketmaker_release\marketmaker_release.7z version.txt + cd .. + rd package_content /s /q + )