diff --git a/.gitignore b/.gitignore index f6a9cbe17..c7962cf39 100755 --- a/.gitignore +++ b/.gitignore @@ -489,3 +489,7 @@ iguana/DB/PRICES/.tmpmarker iguana/DB/KMD/0/.tmpmarker *.swp + +iguana/myipaddr + +iguana/DB/UNSPENTS/.tmpmarker diff --git a/OSlibs/win/mingw.h b/OSlibs/win/mingw.h index 76802c56e..2c35aa78c 100755 --- a/OSlibs/win/mingw.h +++ b/OSlibs/win/mingw.h @@ -61,13 +61,18 @@ * @remarks - #if (defined(_M_X64) || defined(__amd64__)) && defined(WIN32) * is equivalent to #if defined(_M_X64) as _M_X64 is defined for MSVC only */ -#if !defined(_M_X64) -struct pollfd { - SOCKET fd; /* file descriptor */ - short events; /* requested events */ - short revents; /* returned events */ -}; -#endif + + +// [Decker] pollfs is already defined in winsock2.h + +//#if !defined(_M_X64) +//struct pollfd { + //SOCKET fd; /* file descriptor */ + //short events; /* requested events */ + //short revents; /* returned events */ +//}; +//#endif + #if defined(_M_X64) /* diff --git a/crypto777/OS_portable.h b/crypto777/OS_portable.h index 77e6ec5bc..8c109e5d0 100755 --- a/crypto777/OS_portable.h +++ b/crypto777/OS_portable.h @@ -143,6 +143,15 @@ typedef struct queue char name[64],initflag; } queue_t; +struct rpcrequest_info +{ + struct rpcrequest_info *next,*prev; + pthread_t T; + int32_t sock; + uint32_t ipbits; + uint16_t port,pad; +}; + struct OS_mappedptr { char fname[512]; @@ -267,6 +276,7 @@ void *queue_delete(queue_t *queue,struct queueitem *copy,int32_t copysize,int32_ void *queue_free(queue_t *queue); void *queue_clone(queue_t *clone,queue_t *queue,int32_t size); int32_t queue_size(queue_t *queue); +char *mbstr(char *str,double n); void iguana_memreset(struct OS_memspace *mem); void iguana_mempurge(struct OS_memspace *mem); @@ -316,6 +326,7 @@ int32_t btc_convaddr(char *hexaddr,char *addr58); uint64_t RS_decode(char *rs); int32_t RS_encode(char *rsaddr,uint64_t id); +char *cmc_ticker(char *base); void calc_sha1(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); void calc_md2(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); diff --git a/crypto777/OS_time.c b/crypto777/OS_time.c index b5d2efc09..2a1279730 100755 --- a/crypto777/OS_time.c +++ b/crypto777/OS_time.c @@ -21,7 +21,7 @@ #define TAI_PACK 8 #define TAI_UTC_DIFF ((uint64_t)4611686018427387914ULL) -//#define UTC_ADJUST -36 +//#define UTC_ADJUST -37 #define tai_approx(t) ((double) ((t)->x)) #define tai_less(t,u) ((t)->x < (u)->x) @@ -300,7 +300,7 @@ void tai_add(struct tai *t,struct tai *u,struct tai *v) { t->x = u->x + v->x; } void tai_sub(struct tai *t,struct tai *u,struct tai *v) { t->x = u->x - v->x; } // {"leapseconds":["+1972-06-30", "+1972-12-31", "+1973-12-31", "+1974-12-31", "+1975-12-31", "+1976-12-31", "+1977-12-31", "+1982-06-30", "+1983-06-30", "+1985-06-30", "+1987-12-31", "+1989-12-31", "+1990-12-31", "+1992-06-30", "+1993-06-30", "+1994-06-30", "+1995-12-31", "+1997-06-30", "+1998-12-31", "+2005-12-31", "+2008-12-31", "+2012-06-30", "+2015-06-30"]} -char *leapseconds[] = { "+1972-06-30", "+1972-12-31", "+1973-12-31", "+1974-12-31", "+1975-12-31", "+1976-12-31", "+1977-12-31", "+1982-06-30", "+1983-06-30", "+1985-06-30", "+1987-12-31", "+1989-12-31", "+1990-12-31", "+1992-06-30", "+1993-06-30", "+1994-06-30", "+1995-12-31", "+1997-06-30", "+1998-12-31", "+2005-12-31", "+2008-12-31", "+2012-06-30", "+2015-06-30" }; +char *leapseconds[] = { "+1972-06-30", "+1972-12-31", "+1973-12-31", "+1974-12-31", "+1975-12-31", "+1976-12-31", "+1977-12-31", "+1982-06-30", "+1983-06-30", "+1985-06-30", "+1987-12-31", "+1989-12-31", "+1990-12-31", "+1992-06-30", "+1993-06-30", "+1994-06-30", "+1995-12-31", "+1997-06-30", "+1998-12-31", "+2005-12-31", "+2008-12-31", "+2012-06-30", "+2015-06-30", "+2016-12-31" }; struct tai leaptais[sizeof(leapseconds)/sizeof(*leapseconds)]; char *dayname[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" } ; @@ -355,7 +355,7 @@ struct tai tai_now() { First_TAI = t, First_utc = (uint32_t)now; #ifndef DISABLE_LEAPS - UTC_ADJUST = -36; + UTC_ADJUST = -37; #endif //printf("TAINOW.%llu %03.3f UTC.%u vs %u [diff %d]\n",(long long)t.x,t.millis,First_utc,tai2utc(t),UTC_ADJUST); } diff --git a/crypto777/bitcoind_RPC.c b/crypto777/bitcoind_RPC.c index bc87b61f2..f669f04ca 100755 --- a/crypto777/bitcoind_RPC.c +++ b/crypto777/bitcoind_RPC.c @@ -13,10 +13,24 @@ * * ******************************************************************************/ + + #ifndef FROM_JS #include "OS_portable.h" #define LIQUIDITY_PROVIDER 1 +/*#define malloc(n) LP_alloc(n) +#define realloc(ptr,n) LP_realloc(ptr,n) +#define calloc(a,b) LP_alloc((uint64_t)(a) * (b)) +#define free(ptr) LP_free(ptr) +#define clonestr(str) LP_clonestr(str) + +void *LP_realloc(void *ptr,uint64_t len); +void *LP_alloc(uint64_t len); +void LP_free(void *ptr); +char *LP_clonestr(char *str);*/ + + #if LIQUIDITY_PROVIDER #include #include @@ -31,8 +45,11 @@ struct return_string { size_t len; }; +struct MemoryStruct { char *memory; size_t size,allocsize; }; + size_t accumulate(void *ptr, size_t size, size_t nmemb, struct return_string *s); void init_string(struct return_string *s); +static size_t WriteMemoryCallback(void *ptr,size_t size,size_t nmemb,void *data); /************************************************************************ @@ -55,7 +72,9 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char * long i,j,len; char *retstr = 0; cJSON *json,*result,*error; - usleep(2500); +#ifdef FROM_MARKETMAKER + //usleep(3000); +#endif //printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr); if ( command == 0 || rpcstr == 0 || rpcstr[0] == 0 ) { @@ -76,7 +95,8 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char * { if ( (error->type&0xff) == cJSON_NULL && (result->type&0xff) != cJSON_NULL ) { - retstr = cJSON_Print(result); + retstr = jprint(result,0); + //printf("%s %s rpc retstr.%p\n",command,params,retstr); len = strlen(retstr); if ( retstr[0] == '"' && retstr[len-1] == '"' ) { @@ -93,7 +113,10 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char * rpcstr = 0; } if ( rpcstr != 0 ) + { + //printf("free rpcstr.%p\n",rpcstr); free(rpcstr); + } } else retstr = rpcstr; free_json(json); //fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: postprocess returns.(%s)\n",retstr); @@ -120,8 +143,9 @@ char *Jay_NXTrequest(char *command,char *params) char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params,int32_t timeout) { static int didinit,count,count2; static double elapsedsum,elapsedsum2; extern int32_t USE_JAY; + struct MemoryStruct chunk; struct curl_slist *headers = NULL; struct return_string s; CURLcode res; CURL *curl_handle; - char *bracket0,*bracket1,*databuf = 0; long len; int32_t specialcase,numretries; double starttime; + char *bracket0,*bracket1,*retstr,*databuf = 0; long len; int32_t specialcase,numretries; double starttime; if ( didinit == 0 ) { didinit = 1; @@ -145,14 +169,24 @@ try_again: *retstrp = 0; starttime = OS_milliseconds(); curl_handle = curl_easy_init(); - init_string(&s); headers = curl_slist_append(0,"Expect:"); curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )"); curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl_handle,CURLOPT_URL, url); - curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION, (void *)accumulate); // send all data to this function - curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback + if ( (0) ) + { + init_string(&s); + curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION, (void *)accumulate); // send all data to this function + curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback + } + else + { + memset(&chunk,0,sizeof(chunk)); + curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION,WriteMemoryCallback); + curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA,(void *)&chunk); + + } curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback if ( timeout > 0 ) @@ -201,23 +235,24 @@ try_again: free(databuf); databuf = 0; } + retstr = chunk.memory; // retstr = s.ptr; if ( res != CURLE_OK ) { numretries++; if ( specialcase != 0 || timeout != 0 ) { - //printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res); - free(s.ptr); + //printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,retstr,res); + free(retstr); return(0); } else if ( numretries >= 4 ) { printf( "curl_easy_perform() failed: %s %s.(%s %s), retries: %d\n",curl_easy_strerror(res),debugstr,url,command,numretries); //printf("Maximum number of retries exceeded!\n"); - free(s.ptr); + free(retstr); return(0); } - free(s.ptr); + free(retstr); sleep((1< (%s)\n",params,s.ptr); + fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: BTCD.(%s) -> (%s)\n",params,retstr); count2++; elapsedsum2 += (OS_milliseconds() - starttime); if ( (count2 % 10000) == 0) printf("%d: ave %9.6f | elapsed %.3f millis | NXT calls.(%s) cmd.(%s)\n",count2,elapsedsum2/count2,(double)(OS_milliseconds() - starttime),url,command); - return(s.ptr); + return(retstr); } } - //printf("bitcoind_RPC: impossible case\n"); - //free(s.ptr); - //return(0); } /************************************************************************ @@ -292,13 +324,24 @@ size_t accumulate(void *ptr,size_t size,size_t nmemb,struct return_string *s) return(size * nmemb); } -struct MemoryStruct { char *memory; size_t size; }; - static size_t WriteMemoryCallback(void *ptr,size_t size,size_t nmemb,void *data) { - size_t realsize = (size * nmemb); + size_t needed,realsize = (size * nmemb); struct MemoryStruct *mem = (struct MemoryStruct *)data; - mem->memory = (ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1); + needed = mem->size + realsize + 1; + if ( ptr == 0 && needed < 256 ) + { + mem->allocsize = 256; + mem->memory = malloc(mem->allocsize); + } + if ( mem->allocsize < needed ) + { + //printf("curl needs %d more\n",(int32_t)realsize); + mem->memory = (ptr != 0) ? realloc(mem->memory,needed) : malloc(needed); + //printf("mem->memory.%p len.%d\n",mem->memory,(int32_t)needed); + mem->allocsize = needed; + } + //mem->memory = (ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1); if ( mem->memory != 0 ) { if ( ptr != 0 ) 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/iguana_OS.c b/crypto777/iguana_OS.c index c8a7c888f..d08756752 100755 --- a/crypto777/iguana_OS.c +++ b/crypto777/iguana_OS.c @@ -877,7 +877,7 @@ void *OS_loadfile(char *fname,char **bufp,long *lenp,long *allocsizep) { fclose(fp); *lenp = 0; - printf("OS_loadfile null size.(%s)\n",fname); + //printf("OS_loadfile null size.(%s)\n",fname); return(0); } if ( filesize > buflen-1 ) @@ -901,11 +901,15 @@ void *OS_loadfile(char *fname,char **bufp,long *lenp,long *allocsizep) return(buf); } -void *OS_filestr(long *allocsizep,char *fname) +void *OS_filestr(long *allocsizep,char *_fname) { - long filesize = 0; char *buf = 0; + long filesize = 0; char *fname,*buf = 0; void *retptr; *allocsizep = 0; - return(OS_loadfile(fname,&buf,&filesize,allocsizep)); + fname = malloc(strlen(_fname)+1); + strcpy(fname,_fname); + retptr = OS_loadfile(fname,&buf,&filesize,allocsizep); + free(fname); + return(retptr); } // following functions cant be fully implemented in one or more OS diff --git a/crypto777/iguana_utils.c b/crypto777/iguana_utils.c index 5b0ce5743..5f978e305 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 @@ -992,6 +992,7 @@ int32_t RS_encode(char *rsaddr,uint64_t id) rsaddr[j++] = '-'; } rsaddr[j] = 0; + //printf("%llu -> NXT RS (%s)\n",(long long)id,rsaddr); return(0); } @@ -1122,6 +1123,7 @@ void calc_NXTaddr(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len) { uint8_t mysecret[32]; uint64_t nxt64bits; nxt64bits = conv_NXTpassword(mysecret,buf,msg,len); + //printf("call RSencode with %llu\n",(long long)nxt64bits); RS_encode(hexstr,nxt64bits); } diff --git a/iguana/coins/basilisk/mshark b/iguana/coins/basilisk/mshark new file mode 100644 index 000000000..c664fe0b5 --- /dev/null +++ b/iguana/coins/basilisk/mshark @@ -0,0 +1,2 @@ +curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"SHARK.conf\",\"path\":\"${HOME#"/"}/.komodo/SHARK\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":0,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"SHARK\",\"name\":\"SHARK\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"54a5e30c\",\"p2p\":14103,\"rpc\":14104,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}" + diff --git a/iguana/coins/chips_7776 b/iguana/coins/chips_7776 index e09f9c87c..38f1e5f1c 100755 --- a/iguana/coins/chips_7776 +++ b/iguana/coins/chips_7776 @@ -1,2 +1,2 @@ #!/bin/bash -curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"chips.conf\",\"path\":\"${HOME#"/"}/.chips\",\"prefetchlag\":-1,\"poll\":1,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"newcoin\":\"CHIPS\",\"startpend\":64,\"endpend\":64,\"services\":0,\"maxpeers\":512,\"RELAY\":-1,\"VALIDATE\":0,\"portp2p\":57777,\"minconfirms\":1}" +curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"chips.conf\",\"path\":\"${HOME#"/"}/.chips\",\"prefetchlag\":-1,\"poll\":1,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"newcoin\":\"CHIPS\",\"startpend\":64,\"endpend\":64,\"services\":0,\"maxpeers\":512,\"RELAY\":-1,\"VALIDATE\":0,\"portp2p\":57777,\"minconfirms\":1,\"pubval\":60,\"p2shval\":85,\"wifval\":188}" diff --git a/iguana/coins/genshark b/iguana/coins/genshark index f1f98346c..941fc20ed 100755 --- a/iguana/coins/genshark +++ b/iguana/coins/genshark @@ -1,2 +1,2 @@ -curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"SHARK.conf\",\"path\":\"${HOME#"/"}/.komodo/SHARK\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":1,\"VALIDATE\":1,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"SHARK\",\"name\":\"SHARK\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"54a5e30c\",\"p2p\":10113,\"rpc\":10114,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}" +curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"SHARK.conf\",\"path\":\"${HOME#"/"}/.komodo/SHARK\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":1,\"VALIDATE\":1,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"SHARK\",\"name\":\"SHARK\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"54a5e30c\",\"p2p\":14103,\"rpc\":14104,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}" diff --git a/iguana/coins/mshark_7776 b/iguana/coins/mshark_7776 new file mode 100755 index 000000000..e1d4e05fd --- /dev/null +++ b/iguana/coins/mshark_7776 @@ -0,0 +1,2 @@ +curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"MSHARK.conf\",\"path\":\"${HOME#"/"}/.komodo/MSHARK\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"MSHARK\",\"name\":\"MSHARK\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"54a5e30c\",\"p2p\":8845,\"rpc\":8846,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}" + diff --git a/iguana/coins/shark_7776 b/iguana/coins/shark_7776 index 16e4378bf..d1a7bc525 100755 --- a/iguana/coins/shark_7776 +++ b/iguana/coins/shark_7776 @@ -1,2 +1,2 @@ -curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"SHARK.conf\",\"path\":\"${HOME#"/"}/.komodo/SHARK\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"SHARK\",\"name\":\"SHARK\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"54a5e30c\",\"p2p\":10113,\"rpc\":10114,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}" +curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"SHARK.conf\",\"path\":\"${HOME#"/"}/.komodo/SHARK\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"SHARK\",\"name\":\"SHARK\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"54a5e30c\",\"p2p\":14103,\"rpc\":14104,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}" 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_network.c b/iguana/dpow/dpow_network.c index 9899b9cac..c7e5d311a 100755 --- a/iguana/dpow/dpow_network.c +++ b/iguana/dpow/dpow_network.c @@ -584,6 +584,8 @@ char *dex_response(int32_t *broadcastflagp,struct supernet_info *myinfo,struct d { char buf[65],*retstr = 0; int32_t i,datalen; bits256 hash2; cJSON *retjson=0; struct iguana_info *coin; struct dex_request dexreq; *broadcastflagp = 0; +return(clonestr("{\"error\":\"basilisk disabled\"}")); + if ( strcmp(dexp->handler,"request") == 0 ) { datalen = dex_rwrequest(0,dexp->packet,&dexreq); diff --git a/iguana/dpow/dpow_rpc.c b/iguana/dpow/dpow_rpc.c index 6da004617..5f695f84a 100755 --- a/iguana/dpow/dpow_rpc.c +++ b/iguana/dpow/dpow_rpc.c @@ -820,7 +820,7 @@ int32_t dpow_haveutxo(struct supernet_info *myinfo,struct iguana_info *coin,bits } } if ( haveutxo == 0 ) - printf("no utxo: need to fund address.(%s) or wait for splitfund to confirm\n",coinaddr); + printf("no %s utxo: need to fund address.(%s) or wait for splitfund to confirm\n",coin->symbol,coinaddr); } //else printf("null utxo array size\n"); free_json(unspents); } else printf("null return from dpow_listunspent\n"); diff --git a/iguana/exchanges/DB/PRICES/.tmpmarker b/iguana/exchanges/DB/PRICES/.tmpmarker new file mode 100644 index 000000000..e69de29bb diff --git a/iguana/exchanges/DEXstats.h b/iguana/exchanges/DEXstats.h index e31ff68e3..dc1f89864 100644 --- a/iguana/exchanges/DEXstats.h +++ b/iguana/exchanges/DEXstats.h @@ -51,7 +51,7 @@ struct DEXstats_pricepoint struct DEXstats_pairinfo { - char dest[16]; + char dest[128]; int32_t numprices; struct DEXstats_pricepoint *prices; }; @@ -64,7 +64,7 @@ struct DEXstats_datenuminfo struct DEXstats_priceinfo { - char symbol[16]; + char symbol[128]; int32_t firstdatenum,numdates; struct DEXstats_datenuminfo *dates; } Prices[1024]; @@ -927,6 +927,7 @@ char *stats_prices(char *symbol,char *dest,struct DEXstats_disp *prices,int32_t } #ifndef FROM_MARKETMAKER +#ifndef FROM_PRIVATEBET char *stats_JSON(void *ctx,char *myipaddr,int32_t mypubsock,cJSON *argjson,char *remoteaddr,uint16_t port) { char *method,*agent,*retstr,*source,*dest; struct tai T; uint32_t endtimestamp; struct DEXstats_disp prices[365]; int32_t leftdatenum,seconds,numdates; @@ -953,5 +954,6 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t mypubsock,cJSON *argjson,char return(clonestr(jprint(argjson,0))); } #endif +#endif #endif /* DEXstats_h */ diff --git a/iguana/exchanges/LP_NXT.c b/iguana/exchanges/LP_NXT.c new file mode 100644 index 000000000..8ea588733 --- /dev/null +++ b/iguana/exchanges/LP_NXT.c @@ -0,0 +1,342 @@ + +/****************************************************************************** + * Copyright © 2014-2017 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ +// +// LP_NXT.c +// marketmaker +// + + +char *NXTnodes[] = { "62.75.159.113", "91.44.203.238", "82.114.88.225", "78.63.207.76", "188.174.110.224", "91.235.72.49", "213.144.130.91", "209.222.98.250", "216.155.128.10", "178.33.203.157", "162.243.122.251", "69.163.47.173", "193.151.106.129", "78.94.2.74", "192.3.196.10", "173.33.112.87", "104.198.173.28", "35.184.154.126", "174.140.167.239", "23.88.113.131", "198.71.84.173", "178.150.207.53", "23.88.61.53", "192.157.233.106", "192.157.241.212", "23.89.192.88", "23.89.200.27", "192.157.241.139", "23.89.200.63", "23.89.192.98", "163.172.214.102", "176.9.85.5", "80.150.243.88", "80.150.243.92", "80.150.243.98", "109.70.186.198", "146.148.84.237", "104.155.56.82", "104.197.157.140", "37.48.73.249", "146.148.77.226", "84.57.170.200", "107.161.145.131", "80.150.243.97", "80.150.243.93", "80.150.243.100", "80.150.243.95", "80.150.243.91", "80.150.243.99", "80.150.243.96", "93.231.187.177", "212.237.23.85", "35.158.179.254", "46.36.66.41", "185.170.113.79", "163.172.68.112", "78.47.35.210", "77.90.90.75", "94.177.196.134", "212.237.22.215", "94.177.234.11", "167.160.180.199", "54.68.189.9", "94.159.62.14", "195.181.221.89", "185.33.145.94", "195.181.209.245", "195.181.221.38", "195.181.221.162", "185.33.145.12", "185.33.145.176", "178.79.128.235", "94.177.214.120", "94.177.199.41", "94.177.214.200", "94.177.213.201", "212.237.13.162", "195.181.221.236", "195.181.221.185", "185.28.103.187", "185.33.146.244", "217.61.123.71", "195.181.214.45", "195.181.212.99", "195.181.214.46", "195.181.214.215", "195.181.214.68", "217.61.123.118", "195.181.214.79", "217.61.123.14", "217.61.124.100", "195.181.214.111", "85.255.0.176", "81.2.254.116", "217.61.123.184", "195.181.212.231", "94.177.214.110", "195.181.209.164", "104.129.56.238", "85.255.13.64", "167.160.180.206", "217.61.123.226", "167.160.180.208", "93.186.253.127", "212.237.6.208", "94.177.207.190", "217.61.123.119", "85.255.1.245", "217.61.124.157", "37.59.57.141", "167.160.180.58", "104.223.53.14", "217.61.124.69", "195.181.212.103", "85.255.13.141", "104.207.133.204", "71.90.7.107", "107.150.18.108", "23.94.134.161", "80.150.243.13", "80.150.243.11", "185.81.165.52", "80.150.243.8" }; + +static char *assetids[][4] = +{ + { "13502152099823770958", "SUPERNETx2", "10000", "10000" }, + { "12071612744977229797", "SUPERNET", "10000", "10000" }, + { "12071612744977229797", "UNITY", "10000", "10000" }, + { "15344649963748848799", "DEX", "1", "100000000" }, + { "6883271355794806507", "PANGEA", "10000", "10000" }, + { "17911762572811467637", "JUMBLR", "10000", "10000" }, + { "17083334802666450484", "BET", "10000", "10000" }, + { "13476425053110940554", "CRYPTO", "1000", "100000" }, + { "6932037131189568014", "HODL", "1", "100000000" }, + //{ "3006420581923704757", "SHARK", "10000", "10000" }, + { "3006420581923704757", "MSHARK", "10", "10000000" }, + { "17571711292785902558", "BOTS", "1", "100000000" }, + { "10524562908394749924", "MGW", "1", "100000000" }, + { "8217222248380501882", "MESH", "10000", "10000" }, + { "15641806960898178066", "TOKEN", "1", "100000000" }, +}; + +void LP_sendtoaddress_line(char *validaddress,char *assetname,uint64_t satoshis,uint64_t txnum) +{ + char line[1024],lowerstr[64]; + if ( strcmp(assetname,"SUPERNETx2") == 0 ) + { + sprintf(line,"fiat/supernet sendtoaddress %s %.8f # txnum.%llu",validaddress,dstr(satoshis),(long long)txnum); + printf("%s\n",line); + sprintf(line,"fiat/revs sendtoaddress %s %.8f # txnum.%llu",validaddress,dstr(satoshis),(long long)txnum); + } + else + { + if ( strcmp(assetname,"TOKEN") == 0 ) + strcpy(lowerstr,"supernet"); + else strcpy(lowerstr,assetname); + tolowercase(lowerstr); + sprintf(line,"sleep 1; fiat/%s sendtoaddress %s %.8f # txnum.%llu",lowerstr,validaddress,dstr(satoshis),(long long)txnum); + } + printf("%s\n",line); +} + +uint64_t LP_assetid_mult(int32_t *assetindp,char *name,uint64_t assetid) +{ + int32_t i; uint64_t mult = 0; + name[0] = 0; + *assetindp = -1; + for (i=0; i= 1 ) + { + if ( strcmp(account,"NXT-XRK4-5HYK-5965-9FH4Z") != 0 ) + { + sum += (long long)(qtyA * ratio); + sprintf(url,"requestType=transferAsset&secretPhrase=%s&recipient=%s&asset=%llu&quantityQNT=%llu&feeNQT=100000000&deadline=60",passphrase,account,(long long)assetid,(long long)(qtyA * ratio)); + if ( (retstr2= curl_post(&cHandle,"http://127.0.0.1:7876/nxt","",url,"","","","")) != 0 ) + { + if ( (retjson2= cJSON_Parse(retstr2)) != 0 ) + { + txid = j64bits(retjson2,"transaction"); + printf("%s %.6f %8llu QNT %s -> %llu %.8f txid %llu\n",account,ratio,(long long)qtyA,assetids[j][2],(long long)(qtyA * ratio),((double)(long long)(qtyA * ratio))/decimals,(long long)txid); + free_json(retjson2); + } + free(retstr2); + } + usleep(250000); + } + } + } + printf("%s distribution total %llu QNT %.8f\n",assetids[j][2],(long long)sum,(double)sum/decimals); + } + } + free_json(retjson); + } + printf("NXTventure assethodlers.%d\n",n); + free(retstr); + } +} + +cJSON *LP_NXT_redeems() +{ + char url[1024],*retstr,*recv,*method,*msgstr,assetname[128]; uint64_t totals[2][sizeof(assetids)/sizeof(*assetids)],mult,txnum,assetid,qty; int32_t i,ind,numtx=0,past_marker=0; cJSON *item,*attach,*decjson,*array,*msgjson,*encjson,*retjson=0; + uint64_t txnum_marker = calc_nxt64bits("5509605741355242617"); + uint64_t txnum_marker2 = calc_nxt64bits("7256847492742571143"); + char *passphrase = ""; + char *account = "NXT-MRBN-8DFH-PFMK-A4DBM"; + memset(totals,0,sizeof(totals)); + sprintf(url,"http://127.0.0.1:7876/nxt?requestType=getBlockchainTransactions&account=%s",account); + //printf("calling (%s)\n",url); + if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( (array= jarray(&numtx,retjson,"transactions")) != 0 ) + { + for (i=0; i= 0 ) + totals[past_marker][ind] += qty * mult; + if ( msgstr != 0 && assetname[0] != 0 && qty != 0 ) + { + char validaddress[64]; int32_t z,n; + n = (int32_t)strlen(msgstr); + for (z=0; z= 34 ) + strncpy(validaddress,&msgstr[z],34); + if ( txnum == calc_nxt64bits("4545341872872347590") ) + strcpy(validaddress,"RKuwq4oi4mqQ2V4r54mPEthn3TBrEwu2Ni"); + if ( past_marker == 0 ) + { + if ( strlen(validaddress) == 34 || strlen(validaddress) == 33 ) + { + //printf("%-4d: (%34s) <- %13.5f %10s tx.%llu past_marker.%d\n",i,validaddress,dstr(qty * mult),assetname,(long long)txnum,past_marker); + LP_sendtoaddress_line(validaddress,assetname,(qty * mult),txnum); + } else printf("%-4d: (%34s) <- %13.5f %10s tx.%llu\n",i,msgstr!=0?msgstr:jprint(item,0),dstr(qty * mult),assetname,(long long)txnum); + } + } + if ( msgjson != 0 ) + free_json(msgjson); + if ( decjson != 0 ) + free_json(decjson); + } + if ( txnum == txnum_marker2 ) + break; + } + } + //free_json(retjson); + } + free(retstr); + } + printf("\nTotal redeemed.%d\n",numtx); + for (past_marker=0; past_marker<2; past_marker++) + { + for (i=0; i>>>>>>>>> already processed:\n"); + } + return(retjson); +} + +cJSON *LP_assethbla(char *assetid) +{ + char url[1024],*retstr; int32_t n; cJSON *array,*bid=0,*ask=0,*retjson; + sprintf(url,"http://%s:7876/nxt?requestType=getBidOrders&asset=%s&firstIndex=0&lastIndex=0",NXTnodes[LP_rand() % (sizeof(NXTnodes)/sizeof(*NXTnodes))],assetid); + if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 ) + { + bid = cJSON_Parse(retstr); + free(retstr); + } + sprintf(url,"http://%s:7876/nxt?requestType=getAskOrders&asset=%s&firstIndex=0&lastIndex=0",NXTnodes[LP_rand() % (sizeof(NXTnodes)/sizeof(*NXTnodes))],assetid); + if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 ) + { + ask = cJSON_Parse(retstr); + free(retstr); + } + retjson = cJSON_CreateObject(); + if ( bid != 0 && ask != 0 ) + { + if ( (array= jarray(&n,bid,"bidOrders")) != 0 ) + jadd(retjson,"bid",jduplicate(jitem(array,0))); + if ( (array= jarray(&n,ask,"askOrders")) != 0 ) + jadd(retjson,"ask",jduplicate(jitem(array,0))); + } + if ( bid != 0 ) + free_json(bid); + if ( ask != 0 ) + free_json(ask); + return(retjson); +} + diff --git a/iguana/exchanges/LP_RTmetrics.c b/iguana/exchanges/LP_RTmetrics.c index c44c86dbe..3d37c8a2e 100644 --- a/iguana/exchanges/LP_RTmetrics.c +++ b/iguana/exchanges/LP_RTmetrics.c @@ -27,11 +27,13 @@ struct LP_metricinfo int32_t ind,numutxos,age,pendingswaps; }; +#define LP_NUMRT 1024 struct LP_RTmetrics_pendings { - char refbase[16],refrel[16]; - int32_t numswaps,numavoidtxids,numwhitelist,numblacklist,numpendings,pending_swaps[1024]; - bits256 avoidtxids[8192],whitelist[1024],blacklist[1024],pending_pubkeys[1024]; + char refbase[128],refrel[128]; + int64_t pending_kmdvalue[LP_NUMRT]; + int32_t numswaps,numavoidtxids,numwhitelist,numblacklist,numpendings,pending_swaps[LP_NUMRT]; + bits256 avoidtxids[8192],whitelist[LP_NUMRT],blacklist[LP_NUMRT],pending_pubkeys[LP_NUMRT]; } LP_RTmetrics; int32_t LP_bits256_find(bits256 *list,int32_t num,bits256 val) @@ -72,11 +74,14 @@ int32_t LP_RTmetrics_blacklistadd(bits256 pubkey) return(LP_bits256_add("LP_RTmetrics_blacklistadd blacklist",LP_RTmetrics.blacklist,&LP_RTmetrics.numblacklist,(int32_t)(sizeof(LP_RTmetrics.blacklist)/sizeof(*LP_RTmetrics.blacklist)),pubkey)); } -int32_t LP_RTmetrics_pendingswap(bits256 pubkey) +int32_t LP_RTmetrics_pendingswap(bits256 pubkey,int64_t kmdvalue) { int32_t ind; if ( (ind= LP_bits256_add("LP_RTmetrics_pendingswap",LP_RTmetrics.pending_pubkeys,&LP_RTmetrics.numpendings,(int32_t)(sizeof(LP_RTmetrics.pending_pubkeys)/sizeof(*LP_RTmetrics.pending_pubkeys)),pubkey)) >= 0 ) + { LP_RTmetrics.pending_swaps[ind]++; + LP_RTmetrics.pending_kmdvalue[ind] += kmdvalue; + } return(ind); } @@ -113,7 +118,9 @@ void LP_RTmetrics_swapsinfo(char *refbase,char *refrel,cJSON *swaps,int32_t nums base = ""; if ( (rel= jstr(item,"rel")) == 0 ) rel = ""; - if ( strcmp(base,refbase) != 0 && strcmp(base,refrel) != 0 && strcmp(rel,refbase) != 0 && strcmp(rel,refrel) != 0 ) + if ( refbase[0] != 0 && strcmp(base,refbase) != 0 && strcmp(base,refrel) != 0 ) + continue; + if ( refrel[0] != 0 && strcmp(rel,refbase) != 0 && strcmp(rel,refrel) != 0 ) continue; aliceid = j64bits(item,"aliceid"); basesatoshis = SATOSHIDEN * jdouble(item,"basevol"); @@ -123,9 +130,9 @@ void LP_RTmetrics_swapsinfo(char *refbase,char *refrel,cJSON *swaps,int32_t nums price = jdouble(item,"price"); requestid = juint(item,"requestid"); quoteid = juint(item,"quoteid"); - LP_RTmetrics_pendingswap(srcpub); - LP_RTmetrics_pendingswap(destpub); - if ( 0 && (retstr= basilisk_swapentry(requestid,quoteid)) != 0 ) // no need for this + LP_RTmetrics_pendingswap(srcpub,LP_kmdvalue(base,basesatoshis)); + LP_RTmetrics_pendingswap(destpub,LP_kmdvalue(rel,relsatoshis)); + if ( 0 && (retstr= basilisk_swapentry(requestid,quoteid,0)) != 0 ) // no need for this { if ( (swapjson= cJSON_Parse(retstr)) != 0 ) { @@ -142,9 +149,9 @@ void LP_RTmetrics_swapsinfo(char *refbase,char *refrel,cJSON *swaps,int32_t nums } } -void LP_RTmetrics_update(char *base,char *rel) +/*void LP_RTmetrics_init() { - struct LP_pubkeyinfo *pubp,*tmp; uint32_t futuretime; int32_t i,numswaps; bits256 zero; char *retstr; cJSON *statsjson,*swaps; + struct LP_pubkey_info *pubp,*tmp; uint32_t futuretime; int32_t i,numswaps; bits256 pubkey,zero; cJSON *statsjson,*swaps; memset(&LP_RTmetrics,0,sizeof(LP_RTmetrics)); HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) { @@ -152,31 +159,38 @@ void LP_RTmetrics_update(char *base,char *rel) LP_RTmetrics_whitelistadd(pubp->pubkey); else if ( pubp->istrusted < 0 ) LP_RTmetrics_blacklistadd(pubp->pubkey); + pubp->swaps_kmdvalue = 0; } futuretime = (uint32_t)time(NULL) + 3600*100; memset(zero.bytes,0,sizeof(zero)); - if ( (retstr= LP_statslog_disp(100,futuretime,futuretime,"",zero)) != 0 ) + if ( (statsjson= LP_statslog_disp(futuretime,futuretime,"",zero,0,0)) != 0 ) { - if ( (statsjson= cJSON_Parse(retstr)) != 0 ) + if ( (swaps= jarray(&numswaps,statsjson,"swaps")) != 0 ) { - if ( (swaps= jarray(&numswaps,statsjson,"swaps")) != 0 ) - { - printf("LP_RTmetrics_update for (%s)\n",jprint(swaps,0)); - if ( numswaps > 0 ) - LP_RTmetrics_swapsinfo(base,rel,swaps,numswaps); - } - free_json(statsjson); + //printf("LP_RTmetrics_update for (%s)\n",jprint(swaps,0)); + if ( numswaps > 0 ) + LP_RTmetrics_swapsinfo("","",swaps,numswaps); } - free(retstr); + free_json(statsjson); } for (i=0; i LP_MAXPENDING_SWAPS ) { - char str[65]; printf("%s has %d pending swaps! which is more than %d\n",bits256_str(str,LP_RTmetrics.pending_pubkeys[i]),LP_RTmetrics.pending_swaps[i],LP_MAXPENDING_SWAPS); - LP_RTmetrics_blacklistadd(LP_RTmetrics.pending_pubkeys[i]); + char str[65]; printf("%s has %d pending swaps! which is more than %d\n",bits256_str(str,pubkey),LP_RTmetrics.pending_swaps[i],LP_MAXPENDING_SWAPS); + LP_RTmetrics_blacklistadd(pubkey); } - printf("%d pubkeys have pending swaps, whitelist.%d blacklist.%d avoidtxids.%d\n",LP_RTmetrics.numpendings,LP_RTmetrics.numwhitelist,LP_RTmetrics.numblacklist,LP_RTmetrics.numavoidtxids); -} + else if ( (pubp= LP_pubkeyfind(pubkey)) != 0 ) + { + char str[65]; printf("%s has %d pending swaps %.8f kmdvalue\n",bits256_str(str,pubkey),LP_RTmetrics.pending_swaps[i],dstr(LP_RTmetrics.pending_kmdvalue[i])); + pubp->swaps_kmdvalue = LP_RTmetrics.pending_kmdvalue[i]; + } + } + //printf("%d pubkeys have pending swaps, whitelist.%d blacklist.%d avoidtxids.%d\n",LP_RTmetrics.numpendings,LP_RTmetrics.numwhitelist,LP_RTmetrics.numblacklist,LP_RTmetrics.numavoidtxids); +}*/ + + double _LP_RTmetric_calc(struct LP_metricinfo *mp,double bestprice,double maxprice,double relvolume) { @@ -184,24 +198,28 @@ double _LP_RTmetric_calc(struct LP_metricinfo *mp,double bestprice,double maxpri metric = origmetric; if ( mp->numutxos == 0 || relvolume == 0. || mp->maxvol == 0. || mp->balance == 0. ) { - printf("skip i.%d as no info\n",mp->ind); + //printf("skip i.%d as no info\n",mp->ind); return(metric * 100.); } if ( relvolume < mp->minvol ) { metric *= (mp->minvol / relvolume); + //printf("relvolume < minvol %.8f\n",(mp->minvol / relvolume)); } else if ( relvolume > mp->maxvol ) { metric *= (relvolume / mp->maxvol); + //printf("relvolume > minvol %.8f\n",(relvolume / mp->maxvol)); } if ( relvolume < mp->balance/LP_MINVOL ) { metric *= (mp->balance / relvolume); + //printf("relvolume < balance %.8f\n",(mp->balance / relvolume)); } else if ( relvolume > mp->balance/mp->numutxos ) { metric *= (relvolume / (mp->balance/mp->numutxos)); + //printf("relvolume < ave %.8f\n",(relvolume / (mp->balance/mp->numutxos))); } if ( mp->age > LP_ORDERBOOK_DURATION*0.8 ) metric *= 2; @@ -229,6 +247,19 @@ void LP_RTmetric_calc(struct LP_metricinfo *sortbuf,int32_t ind,cJSON *item,doub sortbuf[ind].metric = _LP_RTmetric_calc(&sortbuf[ind],bestprice,maxprice,relvolume); } +int _increasing_metrics(const void *a,const void *b) +{ +#define ptr_a ((struct LP_metricinfo *)a) +#define ptr_b ((struct LP_metricinfo *)b) + if ( ptr_b->metric > ptr_a->metric ) + return(-1); + else if ( ptr_b->metric < ptr_a->metric ) + return(1); + return(0); +#undef ptr_a +#undef ptr_b +} + cJSON *LP_RTmetrics_sort(char *base,char *rel,cJSON *rawasks,int32_t numasks,double maxprice,double relvolume) { cJSON *array=rawasks,*item; int32_t i,num,groupi; double price,prevdepth,bestprice; struct LP_metricinfo *sortbuf; @@ -255,12 +286,13 @@ cJSON *LP_RTmetrics_sort(char *base,char *rel,cJSON *rawasks,int32_t numasks,dou item = jitem(rawasks,i); LP_RTmetric_calc(sortbuf,i,item,bestprice,maxprice,relvolume,prevdepth); prevdepth = jdouble(item,"depth"); + //printf("%.8f ",sortbuf[i].metric); } - revsortds(&sortbuf[0].metric,groupi+1,sizeof(*sortbuf)); + qsort(&sortbuf[0].metric,groupi+1,sizeof(*sortbuf),_increasing_metrics); array = cJSON_CreateArray(); for (i=0; i<=groupi; i++) { - printf("(%d -> %d %.3f) ",i,sortbuf[i].ind,sortbuf[i].metric); + printf("(%d <- %d %.3f) ",i,sortbuf[i].ind,sortbuf[i].metric); item = jitem(rawasks,sortbuf[i].ind); jaddi(array,jduplicate(item)); } diff --git a/iguana/exchanges/LP_bitcoin.c b/iguana/exchanges/LP_bitcoin.c index 1c2c5d0c5..e4fb09e5d 100644 --- a/iguana/exchanges/LP_bitcoin.c +++ b/iguana/exchanges/LP_bitcoin.c @@ -1959,6 +1959,18 @@ int32_t bitcoin_timelockspend(uint8_t *script,int32_t n,uint8_t rmd160[20],uint3 return(n); } +int32_t bitcoin_performancebond(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,uint32_t unlocktimestamp,uint8_t *cltvpub33,uint8_t *elsepub33) +{ + script[n++] = SCRIPT_OP_IF; + n = bitcoin_checklocktimeverify(script,n,unlocktimestamp); + n = bitcoin_pubkeyspend(script,n,cltvpub33); + script[n++] = SCRIPT_OP_ELSE; + n = bitcoin_pubkeyspend(script,n,elsepub33); + script[n++] = SCRIPT_OP_ENDIF; + calc_rmd160_sha256(p2sh_rmd160,script,n); + return(n); +} + int32_t bitcoin_MofNspendscript(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,const struct vin_info *vp) { int32_t i,plen; @@ -1996,6 +2008,8 @@ int32_t bitcoin_p2shscript(uint8_t *script,int32_t n,const uint8_t *p2shscript,c char *bitcoind_passthru(char *coinstr,char *serverport,char *userpass,char *method,char *params) { + if ( userpass[0] == 0 ) + return(clonestr("{\"error\":\"no rpcusername rpcpassword in coin.conf\"}")); return(bitcoind_RPC(0,coinstr,serverport,userpass,method,params,4)); } @@ -2328,20 +2342,20 @@ int32_t iguana_scriptgen(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,int32_t return(scriptlen); } -int32_t bitcoin_scriptget(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,int32_t *hashtypep,uint32_t *sigsizep,uint32_t *pubkeysizep,uint8_t **userdatap,uint32_t *userdatalenp,struct vin_info *vp,uint8_t *scriptsig,int32_t len,int32_t spendtype) +int32_t bitcoin_scriptget(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint32_t *hashtypep,uint32_t *sigsizep,uint32_t *pubkeysizep,uint8_t **userdatap,uint32_t *userdatalenp,struct vin_info *vp,uint8_t *scriptsig,int32_t len,int32_t spendtype,int32_t zcash) { int32_t j,n,siglen,plen; uint8_t *p2shscript; j = n = 0; *userdatap = 0; *userdatalenp = *pubkeysizep = *sigsizep = 0; - *hashtypep = SIGHASH_ALL; + *hashtypep = LP_sighash(symbol,zcash); while ( (siglen= scriptsig[n]) >= 70 && siglen <= 73 && n+siglen < len && j < 16 ) { vp->signers[j].siglen = siglen; memcpy(vp->signers[j].sig,&scriptsig[n+1],siglen); if ( j == 0 ) *hashtypep = vp->signers[j].sig[siglen-1]; - else if ( vp->signers[j].sig[siglen-1] != *hashtypep ) + else if ( vp->signers[j].sig[siglen-1] != (*hashtypep & (~SIGHASH_FORKID)) ) { //printf("SIGHASH.%d mismatch %d vs %d\n",j,vp->signers[j].sig[siglen-1],*hashtypep); break; @@ -2396,14 +2410,7 @@ int32_t bitcoin_scriptget(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,int32_t } if ( *userdatap == p2shscript ) *userdatap = 0; - /*if ( len == 0 ) - { - // txid.(eccf7e3034189b851985d871f91384b8ee357cd47c3024736e5676eb2debb3f2).v1 - decode_hex(vp->rmd160,20,"010966776006953d5567439e5e39f86a0d273bee");//3564a74f9ddb4372301c49154605573d7d1a88fe"); - vp->type = IGUANA_SCRIPT_76A988AC; - }*/ vp->spendlen = iguana_scriptgen(taddr,pubtype,p2shtype,&vp->M,&vp->N,vp->coinaddr,vp->spendscript,0,vp->rmd160,vp->type,(const struct vin_info *)vp,vp->vin.prev_vout); - //printf("type.%d asmstr.(%s) spendlen.%d\n",vp->type,asmstr,vp->spendlen); return(vp->spendlen); } @@ -2571,6 +2578,39 @@ int32_t iguana_calcrmd160(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,char *a return(vp->type); } +/*uint32_t iguana_vinscriptparse(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,struct vin_info *vp,uint32_t *sigsizep,uint32_t *pubkeysizep,uint32_t *p2shsizep,uint32_t *userdatalenp,uint8_t *vinscript,int32_t scriptlen,int32_t zcash) +{ + uint32_t hashtype; uint8_t *userdata = 0; + *sigsizep = *pubkeysizep = *p2shsizep = *userdatalenp = 0; + if ( bitcoin_scriptget(symbol,taddr,pubtype,p2shtype,&hashtype,sigsizep,pubkeysizep,&userdata,userdatalenp,vp,vinscript,scriptlen,0,zcash) < 0 ) + { + printf("iguana_vinscriptparse: error parsing vinscript?\n"); + return(-1); + } + if ( userdata != 0 && *userdatalenp > 0 ) + memcpy(vp->userdata,userdata,*userdatalenp); + if ( vp->type == IGUANA_SCRIPT_P2SH ) + { + *p2shsizep = vp->p2shlen + 1 + (vp->p2shlen >= 0xfd)*2; + //printf("P2SHSIZE.%d\n",*p2shsizep); + } + return(hashtype); +}*/ + +/*char *iguana_scriptget(struct iguana_info *coin,char *scriptstr,char *asmstr,int32_t max,int32_t hdrsi,uint32_t unspentind,bits256 txid,int32_t vout,uint8_t *rmd160,int32_t type,uint8_t *pubkey33) +{ + int32_t scriptlen; uint8_t script[IGUANA_MAXSCRIPTSIZE]; struct vin_info V,*vp = &V; + memset(vp,0,sizeof(*vp)); + scriptstr[0] = 0; + if ( asmstr != 0 ) + asmstr[0] = 0; + if ( pubkey33 != 0 && bitcoin_pubkeylen(pubkey33) > 0 ) + memcpy(vp->signers[0].pubkey,pubkey33,33); + scriptlen = iguana_scriptgen(coin,&vp->M,&vp->N,vp->coinaddr,script,asmstr,rmd160,type,(const struct vin_info *)vp,vout); + init_hexbytes_noT(scriptstr,script,scriptlen); + return(scriptstr); +}*/ + cJSON *bitcoin_txscript(char *asmstr,char **vardata,int32_t numvars) { int32_t i; cJSON *scriptjson,*array; @@ -2995,7 +3035,7 @@ int32_t iguana_parsevinobj(uint8_t *serialized,int32_t maxsize,struct iguana_msg siglen = serialized[len + m++]; //if ( i == 0 && m == 1 && siglen == 0 ) // multisig backward compatible // continue; - if ( serialized[len + m + siglen - 1] == SIGHASH_ALL ) + if ( ((serialized[len + m + siglen - 1] & ~SIGHASH_FORKID) & 0xff) == SIGHASH_ALL ) memcpy(V->signers[i++].sig,&serialized[len + m],siglen); if ( (0) ) { @@ -3186,6 +3226,7 @@ cJSON *iguana_voutjson(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,struct igu jadd(json,"scriptPubKey",skey); } } + free(vp); return(json); } @@ -3233,9 +3274,9 @@ int32_t iguana_vinarray_check(cJSON *vinarray,bits256 txid,int32_t vout) return(-1); } -int32_t iguana_rwmsgtx(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,int32_t rwflag,cJSON *json,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,bits256 *txidp,char *vpnstr,uint8_t *extraspace,int32_t extralen,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash); +int32_t iguana_rwmsgtx(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,int32_t rwflag,cJSON *json,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,bits256 *txidp,char *vpnstr,uint8_t *extraspace,int32_t extralen,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash); -bits256 bitcoin_sigtxid(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,uint8_t *serialized,int32_t maxlen,struct iguana_msgtx *msgtx,int32_t vini,uint8_t *spendscript,int32_t spendlen,int32_t hashtype,char *vpnstr,int32_t suppress_pubkeys,int32_t zcash) +bits256 bitcoin_sigtxid(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,uint8_t *serialized,int32_t maxlen,struct iguana_msgtx *msgtx,int32_t vini,uint8_t *spendscript,int32_t spendlen,uint64_t spendamount,uint32_t hashtype,char *vpnstr,int32_t suppress_pubkeys,int32_t zcash) { int32_t i,len; bits256 sigtxid,txid,revsigtxid; struct iguana_msgtx dest; dest = *msgtx; @@ -3244,47 +3285,82 @@ bits256 bitcoin_sigtxid(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t i memcpy(dest.vins,msgtx->vins,dest.tx_in * sizeof(*dest.vins)); memcpy(dest.vouts,msgtx->vouts,dest.tx_out * sizeof(*dest.vouts)); memset(sigtxid.bytes,0,sizeof(sigtxid)); - if ( (hashtype & ~SIGHASH_FORKID) != SIGHASH_ALL ) + if ( ((hashtype & ~SIGHASH_FORKID) & 0xff) != SIGHASH_ALL ) { printf("currently only SIGHASH_ALL supported, not %d\n",hashtype); return(sigtxid); } - for (i=0; i 0 ) { - dest.vins[i].vinscript = (uint8_t *)""; - dest.vins[i].scriptlen = 0; +#ifdef BTC2_VERSION + if ( height >= BTC2_HARDFORK_HEIGHT ) + hashtype |= (0x777 << 20); +#endif + len += iguana_rwnum(1,&serialized[len],sizeof(hashtype),&hashtype); } - dest.vins[i].p2shlen = 0; - dest.vins[i].redeemscript = 0; - dest.vins[i].userdata = 0; - dest.vins[i].userdatalen = 0; } - len = iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,1,0,serialized,maxlen,&dest,&txid,vpnstr,0,0,0,suppress_pubkeys,zcash); - //for (i=0; i 0 ) // (dest.tx_in != 1 || bits256_nonz(dest.vins[0].prev_hash) != 0) && dest.vins[0].scriptlen > 0 && + else { -#ifdef BTC2_VERSION - if ( height >= BTC2_HARDFORK_HEIGHT ) - hashtype |= (0x777 << 20); -#endif + bits256 prevouthash,seqhash,outputhash; + for (i=len=0; iversion),&msg->version); if ( json != 0 ) @@ -3338,6 +3428,22 @@ int32_t iguana_rwmsgtx(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t is if ( json != 0 ) jaddnum(json,"timestamp",msg->timestamp); } + if ( rwflag == 0 && zcash == 0 ) + { + /* + normal: nVersion|txins|txouts|nLockTime. + segwit + nVersion|marker|flag|txins|txouts|witness|nLockTime + Format of nVersion, txins, txouts, and nLockTime are same as the original format + The marker MUST be 0x00 + The flag MUST be 0x01 + */ + if ( serialized[len] == 0x00 && (segwitflag= serialized[len+1]) == 0x01 ) + { + len += 2; + //printf("SEGWIT transaction\n"); + } + } len += iguana_rwvarint32(rwflag,&serialized[len],&msg->tx_in); if ( rwflag == 0 ) { @@ -3405,6 +3511,40 @@ int32_t iguana_rwmsgtx(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t is if ( voutarray != 0 ) jaddi(voutarray,iguana_voutjson(taddr,pubtype,p2shtype,&msg->vouts[i],i,*txidp)); } + if ( segwitflag != 0 ) + { + segtxlen = len - 2 + sizeof(msg->lock_time); + segtx = malloc(segtxlen); + memcpy(segtx,serialized,sizeof(int32_t)); + memcpy(&segtx[sizeof(int32_t)],&serialized[sizeof(int32_t)+2],len-2-sizeof(int32_t)); + + //printf("tx_out %d, tx_in %d %02x %02x %02x\n",msg->tx_out,msg->tx_in,serialized[len],serialized[len+1],serialized[len+2]); + if ( rwflag != 0 ) + printf("unsupported rwflag.%d when segwitflag\n",rwflag); + else + { + for (i=0; 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)); + } + } len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->lock_time),&msg->lock_time); //printf("lock_time.%08x len.%d\n",msg->lock_time,len); if ( zcash == LP_IS_ZCASHPROTOCOL && msg->version > 1 ) @@ -3437,8 +3577,11 @@ int32_t iguana_rwmsgtx(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t is memset(sigtxid.bytes,0,sizeof(sigtxid)); if ( vins != 0 && jitem(vins,i) != 0 ) { + uint32_t sighash; iguana_vinobjset(&msg->vins[i],jitem(vins,i),spendscript,sizeof(spendscript)); - sigtxid = bitcoin_sigtxid(taddr,pubtype,p2shtype,isPoS,height,sigser,maxsize*2,msg,i,msg->vins[i].spendscript,msg->vins[i].spendlen,SIGHASH_ALL,vpnstr,suppress_pubkeys,zcash); + sighash = LP_sighash(symbol,zcash); + spendamount = LP_outpoint_amount(symbol,msg->vins[i].prev_hash,msg->vins[i].prev_vout); + sigtxid = bitcoin_sigtxid(symbol,taddr,pubtype,p2shtype,isPoS,height,sigser,maxsize*2,msg,i,msg->vins[i].spendscript,msg->vins[i].spendlen,spendamount,sighash,vpnstr,suppress_pubkeys,zcash); //printf("after vini.%d vinscript.%p spendscript.%p spendlen.%d (%s)\n",i,msg->vins[i].vinscript,msg->vins[i].spendscript,msg->vins[i].spendlen,jprint(jitem(vins,i),0)); if ( iguana_vinarray_check(vinarray,msg->vins[i].prev_hash,msg->vins[i].prev_vout) < 0 ) jaddi(vinarray,iguana_vinjson(&msg->vins[i],sigtxid)); @@ -3457,7 +3600,8 @@ int32_t iguana_rwmsgtx(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t is jadd(json,"vout",voutarray); jaddnum(json,"numvouts",msg->tx_out); } - *txidp = bits256_doublesha256(txidstr,txstart,len); + if ( segwitflag == 0 ) + *txidp = bits256_doublesha256(txidstr,txstart,len); if ( json != 0 ) { jaddnum(json,"locktime",msg->lock_time); @@ -3535,13 +3679,13 @@ bits256 iguana_parsetxobj(uint8_t isPoS,int32_t *txstartp,uint8_t *serialized,in return(txid); } -char *iguana_rawtxbytes(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,cJSON *json,struct iguana_msgtx *msgtx,int32_t suppress_pubkeys,int32_t zcash) +char *iguana_rawtxbytes(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,cJSON *json,struct iguana_msgtx *msgtx,int32_t suppress_pubkeys,int32_t zcash) { int32_t n; char *txbytes = 0,vpnstr[64]; uint8_t *serialized; serialized = malloc(IGUANA_MAXPACKETSIZE); vpnstr[0] = 0; //char str[65]; printf("%d of %d: %s\n",i,msg.txn_count,bits256_str(str,tx.txid)); - if ( (n= iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,1,json,serialized,IGUANA_MAXPACKETSIZE,msgtx,&msgtx->txid,vpnstr,0,0,0,suppress_pubkeys,zcash)) > 0 ) + if ( (n= iguana_rwmsgtx(symbol,taddr,pubtype,p2shtype,isPoS,height,1,json,serialized,IGUANA_MAXPACKETSIZE,msgtx,&msgtx->txid,vpnstr,0,0,0,suppress_pubkeys,zcash)) > 0 ) { txbytes = malloc(n*2+1); init_hexbytes_noT(txbytes,serialized,n); @@ -3569,7 +3713,7 @@ char *bitcoin_json2hex(uint8_t isPoS,bits256 *txidp,cJSON *txjson,struct vin_inf return(txbytes); } -cJSON *bitcoin_data2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash) +cJSON *bitcoin_data2json(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash) { int32_t n; char vpnstr[64]; struct iguana_msgtx M; cJSON *txobj; if ( serialized == 0 ) @@ -3580,7 +3724,7 @@ cJSON *bitcoin_data2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t memset(msgtx,0,sizeof(M)); vpnstr[0] = 0; memset(txidp,0,sizeof(*txidp)); - if ( (n= iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,0,txobj,serialized,len,msgtx,txidp,vpnstr,extraspace,extralen,vins,suppress_pubkeys,zcash)) <= 0 ) + if ( (n= iguana_rwmsgtx(symbol,taddr,pubtype,p2shtype,isPoS,height,0,txobj,serialized,len,msgtx,txidp,vpnstr,extraspace,extralen,vins,suppress_pubkeys,zcash)) <= 0 ) { printf("errortxobj.(%s)\n",jprint(txobj,0)); free_json(txobj); @@ -3591,14 +3735,14 @@ cJSON *bitcoin_data2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t if ( n != len ) { int32_t i; - for (i=0; isymbol,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->height,&checktxid,&msgtx,extraspace,4000000,serialized,len,0,0,coin->zcash); + //printf("TX.(%s) match.%d\n",jprint(txobj,0),bits256_cmp(txid,checktxid)); + free(extraspace); + if ( bits256_cmp(txid,checktxid) != 0 ) + { + printf("%s LP_transaction_fromdata mismatched txid %s vs %s\n",coin->symbol,bits256_str(str,txid),bits256_str(str2,checktxid)); + free_json(txobj); + txobj = 0; + } + return(txobj); +} + +struct LP_transaction *LP_create_transaction(struct iguana_info *coin,bits256 txid,uint8_t *serialized,int32_t len,int32_t height,long fpos) +{ + cJSON *txobj; bits256 spenttxid; int32_t i,spentvout,numvins,numvouts; cJSON *vout,*vin,*vins,*vouts; struct LP_transaction *tx; char str[65]; + if ( (tx= LP_transactionfind(coin,txid)) != 0 ) + return(tx); + if ( (txobj= LP_transaction_fromdata(coin,txid,serialized,len)) != 0 ) + { + vins = jarray(&numvins,txobj,"vin"); + vouts = jarray(&numvouts,txobj,"vout"); + tx = LP_transactionadd(coin,txid,height,numvouts,numvins); + tx->serialized = serialized, tx->len = len; + // free(serialized), tx->len = 0; + tx->fpos = fpos; + tx->SPV = tx->height = height; + //printf("tx.%s numvins.%d numvouts.%d\n",bits256_str(str,txid),numvins,numvouts); + for (i=0; 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,ht=0,SPV = 0; + if ( height <= 0 ) + return(0); + if ( (tx= LP_transactionfind(coin,txid)) == 0 && strcmp(coinaddr,coin->smartaddr) == 0 ) + { + if ( (retjson= electrum_transaction(&ht,coin->symbol,ep,&retjson,txid,0)) != 0 ) + free_json(retjson); + } + if ( tx != 0 ) + { + if ( tx->height == 0 ) + { + if ( height != 0 ) + tx->height = height; + else if ( ht != 0 ) + tx->height = ht; + height = tx->height; + } + if ( tx->SPV > 0 ) + return(tx->SPV); + } + if ( (merkobj= electrum_getmerkle(coin->symbol,ep,&merkobj,txid,height)) != 0 ) + { + char str[65],str2[65],str3[65]; + SPV = 0; + memset(roothash.bytes,0,sizeof(roothash)); + if ( (merkles= jarray(&m,merkobj,"merkle")) != 0 ) + { + roothash = validate_merkle(jint(merkobj,"pos"),txid,merkles,m); + merkleroot = LP_merkleroot(coin,ep,height); + if ( bits256_nonz(merkleroot) != 0 ) + { + if ( bits256_cmp(merkleroot,roothash) == 0 ) + { + SPV = height; + LP_SPV_store(coin,txid,height); + if ( tx != 0 ) + { + tx->SPV = height; + if ( strcmp(coinaddr,coin->smartaddr) != 0 && tx->serialized != 0 ) + { + free(tx->serialized); + tx->serialized = 0; + tx->len = 0; + } + } + //printf("validated MERK %s ht.%d -> %s root.(%s)\n",bits256_str(str,txid),height,jprint(merkobj,0),bits256_str(str2,roothash)); + } + else + { + SPV = -1; + printf("ERROR MERK %s ht.%d -> %s root.(%s) vs %s\n",bits256_str(str,txid),height,jprint(merkobj,0),bits256_str(str2,roothash),bits256_str(str3,merkleroot)); + } + } else SPV = 0; + } + if ( SPV < 0 ) + { + printf("MERKLE DIDNT VERIFY.%s %s ht.%d (%s)\n",coin->symbol,bits256_str(str,txid),height,jprint(merkobj,0)); + if ( jobj(merkobj,"error") != 0 ) + SPV = 0; // try again later + } + free_json(merkobj); + } + return(SPV); +} + +char *LP_unspents_filestr(char *symbol,char *addr) +{ + char fname[1024]; long fsize; + sprintf(fname,"%s/UNSPENTS/%s_%s",GLOBAL_DBDIR,symbol,addr), OS_portable_path(fname); + return(OS_filestr(&fsize,fname)); +} + +void LP_unspents_cache(char *symbol,char *addr,char *arraystr,int32_t updatedflag) +{ + char fname[1024]; FILE *fp=0; + sprintf(fname,"%s/UNSPENTS/%s_%s",GLOBAL_DBDIR,symbol,addr), OS_portable_path(fname); + //printf("unspents cache.(%s) for %s %s, updated.%d\n",fname,symbol,addr,updatedflag); + if ( updatedflag == 0 && (fp= fopen(fname,"rb")) == 0 ) + updatedflag = 1; + else if ( fp != 0 ) + fclose(fp); + if ( updatedflag != 0 && (fp= fopen(fname,"wb")) != 0 ) + { + fwrite(arraystr,1,strlen(arraystr),fp); + fclose(fp); + } +} + +uint64_t LP_unspents_load(char *symbol,char *addr) +{ + char *arraystr; uint64_t balance = 0; int32_t i,n; bits256 zero; cJSON *retjson,*item; struct iguana_info *coin; + if ( (coin= LP_coinfind(symbol)) != 0 ) + { + if ( (arraystr= LP_unspents_filestr(symbol,addr)) != 0 ) + { + if ( (retjson= cJSON_Parse(arraystr)) != 0 ) + { + //printf("PROCESS UNSPENTS %s\n",arraystr); + if ( (n= cJSON_GetArraySize(retjson)) > 0 ) + { + for (i=0; ielectrum,addr,retjson,1,zero,zero); + free_json(retjson); + } + free(arraystr); + } + } + return(balance); +} + + + diff --git a/iguana/exchanges/LP_coins.c b/iguana/exchanges/LP_coins.c index 945bd5915..ae66c3701 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 ) { @@ -197,8 +227,12 @@ cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif) jadd(item,"installed",coin->userpass[0] == 0 ? jfalse() : jtrue()); if ( coin->userpass[0] != 0 ) { - jaddnum(item,"height",LP_getheight(coin)); - balance = LP_smartbalance(coin); + jaddnum(item,"height",LP_getheight(¬arized,coin)); + if ( notarized > 0 ) + jaddnum(item,"notarized",notarized); + if ( coin->electrum != 0 ) + balance = LP_unspents_load(coin->symbol,coin->smartaddr); + else balance = LP_RTsmartbalance(coin); jaddnum(item,"balance",dstr(balance)); jaddnum(item,"KMDvalue",dstr(LP_KMDvalue(coin,balance))); } @@ -224,19 +258,33 @@ cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif) jaddnum(item,"pubtype",coin->pubtype); jaddnum(item,"p2shtype",coin->p2shtype); jaddnum(item,"wiftype",coin->wiftype); - jaddnum(item,"txfee",coin->txfee); + jaddnum(item,"txfee",strcmp(coin->symbol,"BTC") != 0 ? coin->txfee : LP_txfeecalc(coin,0,0)); + if ( strcmp(coin->symbol,"KMD") == 0 ) + { + memset(zero.bytes,0,sizeof(zero)); + if ( strcmp(coin->smartaddr,coin->instantdex_address) != 0 ) + { + LP_instantdex_depositadd(coin->smartaddr,zero); + strcpy(coin->instantdex_address,coin->smartaddr); + } + jaddnum(item,"zcredits",dstr(LP_myzcredits())); + jadd(item,"zdebits",LP_myzdebits()); + } return(item); } struct iguana_info *LP_conflicts_find(struct iguana_info *refcoin) { struct iguana_info *coin=0,*tmp; - HASH_ITER(hh,LP_coins,coin,tmp) + if ( refcoin != 0 ) { - if ( coin->inactive != 0 || coin->electrum != 0 || coin == refcoin ) - continue; - if ( strcmp(coin->serverport,refcoin->serverport) == 0 ) - break; + HASH_ITER(hh,LP_coins,coin,tmp) + { + if ( coin->inactive != 0 || coin->electrum != 0 || coin == refcoin ) + continue; + if ( strcmp(coin->serverport,refcoin->serverport) == 0 ) + break; + } } return(coin); } @@ -254,31 +302,37 @@ cJSON *LP_coinsjson(int32_t showwif) char *LP_getcoin(char *symbol) { int32_t numenabled,numdisabled; struct iguana_info *coin,*tmp; cJSON *item=0,*retjson; - numenabled = numdisabled = 0; retjson = cJSON_CreateObject(); - HASH_ITER(hh,LP_coins,coin,tmp) + if ( symbol != 0 && symbol[0] != 0 ) { - if ( strcmp(symbol,coin->symbol) == 0 ) - item = LP_coinjson(coin,0); - if ( coin->inactive == 0 ) - numenabled++; - else numdisabled++; + numenabled = numdisabled = 0; + HASH_ITER(hh,LP_coins,coin,tmp) + { + if ( strcmp(symbol,coin->symbol) == 0 ) + item = LP_coinjson(coin,0); + if ( coin->inactive == 0 ) + numenabled++; + else numdisabled++; + } + jaddstr(retjson,"result","success"); + jaddnum(retjson,"enabled",numenabled); + jaddnum(retjson,"disabled",numdisabled); + if ( item == 0 ) + item = cJSON_CreateObject(); + jadd(retjson,"coin",item); } - jaddstr(retjson,"result","success"); - jaddnum(retjson,"enabled",numenabled); - jaddnum(retjson,"disabled",numdisabled); - if ( item == 0 ) - item = cJSON_CreateObject(); - jadd(retjson,"coin",item); return(jprint(retjson,1)); } struct iguana_info *LP_coinsearch(char *symbol) { - struct iguana_info *coin; - portable_mutex_lock(&LP_coinmutex); - HASH_FIND(hh,LP_coins,symbol,strlen(symbol),coin); - portable_mutex_unlock(&LP_coinmutex); + struct iguana_info *coin = 0; + if ( symbol != 0 && symbol[0] != 0 ) + { + portable_mutex_lock(&LP_coinmutex); + HASH_FIND(hh,LP_coins,symbol,strlen(symbol),coin); + portable_mutex_unlock(&LP_coinmutex); + } return(coin); } @@ -339,6 +393,11 @@ uint16_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *asse coin->zcash = LP_IS_BITCOINCASH; //printf("set coin.%s <- LP_IS_BITCOINCASH %d\n",symbol,coin->zcash); } + else if ( strcmp(symbol,"BTG") == 0 ) + { + coin->zcash = LP_IS_BITCOINGOLD; + printf("set coin.%s <- LP_IS_BITCOINGOLD %d\n",symbol,coin->zcash); + } return(port); } @@ -389,9 +448,9 @@ struct iguana_info *LP_coinfind(char *symbol) if ( (coin= LP_coinadd(&cdata)) != 0 ) { coin->inactive = isinactive * (uint32_t)time(NULL); - if ( strcmp(symbol,"KMD") == 0 ) + /*if ( strcmp(symbol,"KMD") == 0 ) coin->inactive = 0; - else if ( strcmp(symbol,"BTC") == 0 ) + else*/ if ( strcmp(symbol,"BTC") == 0 ) { coin->inactive = (uint32_t)time(NULL) * !IAMLP; printf("BTC inactive.%u\n",coin->inactive); @@ -450,3 +509,12 @@ struct iguana_info *LP_coincreate(cJSON *item) return(0); } +void LP_otheraddress(char *destcoin,char *otheraddr,char *srccoin,char *coinaddr) +{ + uint8_t addrtype,rmd160[20]; struct iguana_info *src,*dest; + if ( (src= LP_coinfind(srccoin)) != 0 && (dest= LP_coinfind(destcoin)) != 0 ) + { + bitcoin_addr2rmd160(src->taddr,&addrtype,rmd160,coinaddr); + bitcoin_address(otheraddr,dest->taddr,dest->pubtype,rmd160,20); + } else printf("couldnt find %s or %s\n",srccoin,destcoin); +} diff --git a/iguana/exchanges/LP_commands.c b/iguana/exchanges/LP_commands.c index 63b8ce736..dd87341eb 100644 --- a/iguana/exchanges/LP_commands.c +++ b/iguana/exchanges/LP_commands.c @@ -34,10 +34,12 @@ char *LP_numutxos() char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port { - char *method,*ipaddr,*userpass,*base,*rel,*coin,*retstr = 0; uint16_t argport=0,pushport,subport; int32_t changed,otherpeers,flag = 0; struct LP_peerinfo *peer; cJSON *retjson,*reqjson = 0; struct iguana_info *ptr; - //printf("stats_JSON(%s)\n",jprint(argjson,0)); + char *method,*userpass,*base,*rel,*coin,*retstr = 0; int32_t changed,flag = 0; cJSON *retjson,*reqjson = 0; struct iguana_info *ptr; method = jstr(argjson,"method"); - if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 && (method == 0 || strcmp(method,"electrum") != 0) ) + if ( method != 0 && (strcmp(method,"addr_unspents") == 0 || strcmp(method,"uitem") == 0 || strcmp(method,"postutxos") == 0) ) + return(0); +//printf("stats_JSON.(%s)\n",jprint(argjson,0)); + /*if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 && (method == 0 || strcmp(method,"electrum") != 0) ) { if ( strcmp(ipaddr,"127.0.0.1") != 0 && argport >= 1000 ) { @@ -50,31 +52,34 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r { if ( 0 && (otherpeers= jint(argjson,"numpeers")) > peer->numpeers ) peer->numpeers = otherpeers; - /*if ( 0 && (othernumutxos= jint(argjson,"numutxos")) > peer->numutxos ) - { - printf("change.(%s) numutxos.%d -> %d mynumutxos.%d\n",peer->ipaddr,peer->numutxos,othernumutxos,LP_mypeer != 0 ? LP_mypeer->numutxos:0); - peer->numutxos = othernumutxos; - }*/ if ( peer->sessionid == 0 ) peer->sessionid = juint(argjson,"session"); //printf("peer.(%s) found (%d %d) (%d %d) (%s)\n",peer->ipaddr,peer->numpeers,peer->numutxos,otherpeers,othernumutxos,jprint(argjson,0)); } else LP_addpeer(LP_mypeer,LP_mypubsock,ipaddr,argport,pushport,subport,jint(argjson,"numpeers"),jint(argjson,"numutxos"),juint(argjson,"session")); } - } + }*/ if ( method == 0 ) { if ( is_cJSON_Array(argjson) != 0 ) printf("RAWARRAY command? %s\n",jprint(argjson,0)); if ( flag == 0 || jobj(argjson,"result") != 0 ) - printf("stats_JSON no method: (%s) (%s:%u)\n",jprint(argjson,0),ipaddr,argport); + printf("stats_JSON no method: (%s)\n",jprint(argjson,0)); return(0); } - /*if ( strcmp(method,"hello") == 0 ) - { - //printf("got hello from %s:%u\n",ipaddr!=0?ipaddr:"",argport); - return(0); - } - else*/ if ( strcmp(method,"sendmessage") == 0 && jobj(argjson,"userpass") == 0 ) + if ( strcmp(method,"hello") == 0 ) + { + //int32_t i; cJSON *array = cJSON_CreateArray(); + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jaddstr(retjson,"status","got hello"); + //for (i=0; i<10000; i++) + // jaddinum(array,i); + //jadd(retjson,"array",array); + return(jprint(retjson,1)); + //printf("got hello from %s:%u\n",ipaddr!=0?ipaddr:"",argport); + //return(clonestr("{\"result\":\"success\",\"status\":\"got hello\"}")); + } + /*else if ( strcmp(method,"sendmessage") == 0 && jobj(argjson,"userpass") == 0 ) { static char *laststr; char *newstr; bits256 pubkey = jbits256(argjson,"pubkey"); @@ -91,35 +96,35 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r retstr = clonestr(laststr); } } else retstr = clonestr("{\"error\":\"duplicate message\"}"); - } + }*/ //else if ( strcmp(method,"nn_tests") == 0 ) // return(clonestr("{\"result\":\"success\"}")); else if ( strcmp(method,"help") == 0 ) return(clonestr("{\"result\":\" \ available localhost RPC commands: \n \ -pricearray(base, rel, starttime=0, endtime=-1, timescale=60) -> [timestamp, avebid, aveask, highbid, lowask]\n\ -setprice(base, rel, price)\n\ -autoprice(base, rel, minprice, margin, refbase, refrel, factor, offset)*\n\ +setprice(base, rel, price, broadcast=1)\n\ +autoprice(base, rel, fixed, minprice, margin, refbase, refrel, factor, offset)*\n\ goal(coin=*, val=)\n\ myprice(base, rel)\n\ enable(coin)\n\ disable(coin)\n\ notarizations(coin)\n\ -parselog()\n\ -statsdisp(starttime=0, endtime=0, gui="", pubkey="")\n\ +statsdisp(starttime=0, endtime=0, gui="", pubkey="", base="", rel="")\n\ +tradesarray(base, rel, starttime=-timescale*1024, endtime=, timescale=60) -> [timestamp, high, low, open, close, relvolume, basevolume, aveprice, numtrades]\n\ +pricearray(base, rel, starttime=0, endtime=0, timescale=60) -> [timestamp, avebid, aveask, highbid, lowask]\n\ getrawtransaction(coin, txid)\n\ -inventory(coin)\n\ -bestfit(rel, relvolume)\n\ +inventory(coin, reset=0, [passphrase=])\n\ lastnonce()\n\ -buy(base, rel, price, relvolume, timeout=10, duration=3600, nonce, pubkey="")\n\ -sell(base, rel, price, basevolume, timeout=10, duration=3600, nonce, pubkey="")\n\ +buy(base, rel, price, relvolume, timeout=10, duration=3600, nonce)\n\ +sell(base, rel, price, basevolume, timeout=10, duration=3600, nonce)\n\ withdraw(coin, outputs[])\n\ sendrawtransaction(coin, signedtx)\n\ -swapstatus()\n\ +swapstatus(pending=0)\n\ swapstatus(coin, limit=10)\n\ swapstatus(base, rel, limit=10)\n\ swapstatus(requestid, quoteid)\n\ recentswaps(limit=3)\n\ +notarizations(coin)\n\ public API:\n \ getcoins()\n\ getcoin(coin)\n\ @@ -130,23 +135,39 @@ listunspent(coin, address)\n\ setconfirms(coin, numconfirms, maxconfirms=6)\n\ trust(pubkey, trust) # positive to trust, 0 for normal, negative to blacklist\n\ balance(coin, address)\n\ +balances(address)\n\ +fundvalue(address="", holdings=[], divisor=0)\n\ orderbook(base, rel, duration=3600)\n\ -getprices(base, rel)\n\ -sendmessage(base=coin, rel="", pubkey=zero, )\n\ -getmessages(firsti=0, num=100)\n\ -deletemessages(firsti=0, num=100)\n\ +getprices()\n\ +getprice(base, rel)\n\ +//sendmessage(base=coin, rel="", pubkey=zero, )\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\ +instantdex_deposit(weeks, amount, broadcast=1)\n\ +instantdex_claim()\n\ \"}")); //sell(base, rel, price, basevolume, timeout=10, duration=3600)\n\ - base = jstr(argjson,"base"); - rel = jstr(argjson,"rel"); - coin = jstr(argjson,"coin"); + if ( (base= jstr(argjson,"base")) == 0 ) + base = ""; + if ((rel= jstr(argjson,"rel")) == 0 ) + rel = ""; + if ( (coin= jstr(argjson,"coin")) == 0 ) + coin = ""; if ( G.USERPASS[0] != 0 && strcmp(remoteaddr,"127.0.0.1") == 0 && port != 0 ) // protected localhost { if ( G.USERPASS_COUNTER == 0 ) @@ -163,6 +184,7 @@ stop()\n\ jdelete(argjson,"userpass"); if ( strcmp(method,"passphrase") == 0 ) { + char coinaddr[64]; G.USERPASS_COUNTER = 1; if ( LP_passphrase_init(jstr(argjson,"passphrase"),jstr(argjson,"gui")) < 0 ) return(clonestr("{\"error\":\"couldnt change passphrase\"}")); @@ -171,25 +193,40 @@ stop()\n\ jaddstr(retjson,"result","success"); jaddstr(retjson,"userpass",G.USERPASS); jaddbits256(retjson,"mypubkey",G.LP_mypub25519); + bitcoin_address(coinaddr,0,60,G.LP_myrmd160,20); + jaddstr(retjson,"KMD",coinaddr); + bitcoin_address(coinaddr,0,0,G.LP_myrmd160,20); + jaddstr(retjson,"BTC",coinaddr); + jaddstr(retjson,"NXT",G.LP_NXTaddr); + jadd(retjson,"coins",LP_coinsjson(LP_showwif)); return(jprint(retjson,1)); } } - else if ( strcmp(method,"sendmessage") == 0 ) + else if ( strcmp(method,"instantdex_deposit") == 0 ) { - if ( jobj(argjson,"method2") == 0 ) + if ( (ptr= LP_coinsearch("KMD")) != 0 ) { - LP_broadcast_message(LP_mypubsock,base!=0?base:jstr(argjson,"coin"),rel,jbits256(argjson,"pubkey"),jprint(argjson,0)); + if ( jint(argjson,"weeks") <= 0 || jdouble(argjson,"amount") < 10. ) + return(clonestr("{\"error\":\"instantdex_deposit needs to have weeks and amount\"}")); + else return(LP_instantdex_deposit(ptr,juint(argjson,"weeks"),jdouble(argjson,"amount"),jobj(argjson,"broadcast") != 0 ? jint(argjson,"broadcast") : 1)); } - return(clonestr("{\"result\":\"success\"}")); + return(clonestr("{\"error\":\"cant find KMD\"}")); } - else if ( strcmp(method,"recentswaps") == 0 ) + else if ( strcmp(method,"instantdex_claim") == 0 ) { - return(LP_recent_swaps(jint(argjson,"limit"))); + if ( (ptr= LP_coinsearch("KMD")) != 0 ) + { + return(LP_instantdex_claim(ptr)); + } + return(clonestr("{\"error\":\"cant find KMD\"}")); } - else if ( strcmp(method,"stop") == 0 ) + /*else if ( strcmp(method,"sendmessage") == 0 ) { - printf("DEBUG stop\n"); - exit(0); + if ( jobj(argjson,"method2") == 0 ) + { + LP_broadcast_message(LP_mypubsock,base!=0?base:coin,rel,jbits256(argjson,"pubkey"),jprint(argjson,0)); + } + return(clonestr("{\"result\":\"success\"}")); } else if ( strcmp(method,"getmessages") == 0 ) { @@ -201,18 +238,36 @@ stop()\n\ { LP_deletemessages(jint(argjson,"firsti"),jint(argjson,"num")); return(clonestr("{\"result\":\"success\"}")); + }*/ + else if ( strcmp(method,"recentswaps") == 0 ) + { + return(LP_recent_swaps(jint(argjson,"limit"))); + } + else if ( strcmp(method,"stop") == 0 ) + { + printf("DEBUG stop\n"); + exit(0); + } + else if ( strcmp(method,"millis") == 0 ) + { + LP_millistats_update(0); + return(clonestr("{\"result\":\"success\"}")); } + else if ( strcmp(method,"getprices") == 0 ) + return(LP_prices()); + else if ( strcmp(method,"getpeers") == 0 ) + return(LP_peers()); + else if ( strcmp(method,"getcoins") == 0 ) + return(jprint(LP_coinsjson(0),1)); else if ( strcmp(method,"notarizations") == 0 ) { - int32_t height,bestheight; if ( (ptr= LP_coinsearch(coin)) != 0 ) { - height = LP_notarization_latest(&bestheight,ptr); retjson = cJSON_CreateObject(); jaddstr(retjson,"result","success"); jaddstr(retjson,"coin",coin); - jaddnum(retjson,"lastnotarization",height); - jaddnum(retjson,"bestheight",bestheight); + jaddnum(retjson,"lastnotarization",ptr->notarized); + jaddnum(retjson,"bestheight",ptr->height); return(jprint(retjson,1)); } else return(clonestr("{\"error\":\"cant find coin\"}")); } @@ -220,16 +275,9 @@ stop()\n\ { return(LP_portfolio()); } - else if ( strcmp(method,"parselog") == 0 ) - { - bits256 zero; int32_t n = LP_statslog_parse(); - memset(zero.bytes,0,sizeof(zero)); - return(LP_statslog_disp(n,2000000000,2000000000,"",zero)); - } else if ( strcmp(method,"statsdisp") == 0 ) { - int32_t n = LP_statslog_parse(); - return(LP_statslog_disp(n,juint(argjson,"starttime"),juint(argjson,"endtime"),jstr(argjson,"gui"),jbits256(argjson,"pubkey"))); + return(jprint(LP_statslog_disp(juint(argjson,"starttime"),juint(argjson,"endtime"),jstr(argjson,"gui"),jbits256(argjson,"pubkey"),jstr(argjson,"base"),jstr(argjson,"rel")),1)); } else if ( strcmp(method,"secretaddresses") == 0 ) { @@ -242,16 +290,55 @@ stop()\n\ { uint32_t requestid,quoteid; if ( (requestid= juint(argjson,"requestid")) != 0 && (quoteid= juint(argjson,"quoteid")) != 0 ) - return(basilisk_swapentry(requestid,quoteid)); - else if ( coin != 0 && coin[0] != 0 ) + return(basilisk_swapentry(requestid,quoteid,1)); + else if ( coin[0] != 0 ) return(basilisk_swapentries(coin,0,jint(argjson,"limit"))); - else if ( base != 0 && base[0] != 0 && rel != 0 && rel[0] != 0 ) + else if ( base[0] != 0 && rel[0] != 0 ) return(basilisk_swapentries(base,rel,jint(argjson,"limit"))); - else return(basilisk_swaplist(0,0)); + else return(basilisk_swaplist(0,0,0,jint(argjson,"pending"))); + } + else if ( strcmp(method,"dynamictrust") == 0 ) + { + struct LP_address *ap; char *coinaddr; + if ( (ptr= LP_coinsearch("KMD")) != 0 && (coinaddr= jstr(argjson,"address")) != 0 ) + { + //LP_zeroconf_deposits(ptr); + if ( (ap= LP_addressfind(ptr,coinaddr)) != 0 ) + { + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jaddstr(retjson,"address",coinaddr); + jaddnum(retjson,"zcredits",dstr(ap->instantdex_credits)); + return(jprint(retjson,1)); + } + } + return(clonestr("{\"error\":\"cant find address\"}")); } - if ( base != 0 && rel != 0 ) + else if ( (retstr= LP_istradebots_command(ctx,pubsock,method,argjson)) != 0 ) + return(retstr); + if ( base[0] != 0 && rel[0] != 0 ) { double price,bid,ask; + if ( strcmp(method,"autoprice") == 0 ) + { + if ( LP_autoprice(ctx,base,rel,argjson) < 0 ) + return(clonestr("{\"error\":\"couldnt set autoprice\"}")); + else return(clonestr("{\"result\":\"success\"}")); + } + else if ( strcmp(method,"pricearray") == 0 ) + { + uint32_t firsttime; + if ( base[0] != 0 && rel[0] != 0 ) + { + if ( (firsttime= juint(argjson,"starttime")) < time(NULL)-30*24*3600 ) + firsttime = (uint32_t)(time(NULL)-30*24*3600); + return(jprint(LP_pricearray(base,rel,firsttime,juint(argjson,"endtime"),jint(argjson,"timescale")),1)); + } else return(clonestr("{\"error\":\"pricearray needs base and rel\"}")); + } + else if ( strcmp(method,"tradesarray") == 0 ) + { + return(jprint(LP_tradesarray(base,rel,juint(argjson,"starttime"),juint(argjson,"endtime"),jint(argjson,"timescale")),1)); + } if ( IAMLP == 0 && LP_isdisabled(base,rel) != 0 ) return(clonestr("{\"error\":\"at least one of coins disabled\"}")); price = jdouble(argjson,"price"); @@ -261,18 +348,12 @@ stop()\n\ return(clonestr("{\"error\":\"couldnt set price\"}")); //else if ( LP_mypriceset(&changed,rel,base,1./price) < 0 ) // return(clonestr("{\"error\":\"couldnt set price\"}")); - else return(LP_pricepings(ctx,myipaddr,LP_mypubsock,base,rel,price * LP_profitratio)); - } - else if ( strcmp(method,"autoprice") == 0 ) - { - if ( LP_autoprice(base,rel,argjson) < 0 ) - return(clonestr("{\"error\":\"couldnt set autoprice\"}")); + else if ( price == 0. || jobj(argjson,"broadcast") == 0 || jint(argjson,"broadcast") != 0 ) + return(LP_pricepings(ctx,myipaddr,LP_mypubsock,base,rel,price * LP_profitratio)); else return(clonestr("{\"result\":\"success\"}")); } - else if ( strcmp(method,"pricearray") == 0 ) - { - return(jprint(LP_pricearray(base,rel,juint(argjson,"starttime"),juint(argjson,"endtime"),jint(argjson,"timescale")),1)); - } + else if ( strcmp(method,"orderbook") == 0 ) + return(LP_orderbook(base,rel,jint(argjson,"duration"))); else if ( strcmp(method,"myprice") == 0 ) { if ( LP_myprice(&bid,&ask,base,rel) > SMALLVAL ) @@ -290,7 +371,7 @@ stop()\n\ //* if ( price > SMALLVAL ) { - return(LP_autobuy(ctx,myipaddr,pubsock,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui"),juint(argjson,"nonce"),jbits256(argjson,"pubkey"))); + return(LP_autobuy(ctx,myipaddr,pubsock,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui"),juint(argjson,"nonce"),jbits256(argjson,"destpubkey"),0)); } else return(clonestr("{\"error\":\"no price set\"}")); } else if ( strcmp(method,"sell") == 0 ) @@ -298,18 +379,18 @@ stop()\n\ //* if ( price > SMALLVAL ) { - return(LP_autobuy(ctx,myipaddr,pubsock,rel,base,1./price,jdouble(argjson,"basevolume"),jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui"),juint(argjson,"nonce"),jbits256(argjson,"pubkey"))); + return(LP_autobuy(ctx,myipaddr,pubsock,rel,base,1./price,jdouble(argjson,"basevolume"),jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui"),juint(argjson,"nonce"),jbits256(argjson,"destpubkey"),0)); } else return(clonestr("{\"error\":\"no price set\"}")); } } - else if ( rel != 0 && strcmp(method,"bestfit") == 0 ) + /*else if ( rel[0] != 0 && strcmp(method,"bestfit") == 0 ) { double relvolume; if ( (relvolume= jdouble(argjson,"relvolume")) > SMALLVAL ) return(LP_bestfit(rel,relvolume)); else return(clonestr("{\"error\":\"no relvolume set\"}")); - } - else if ( (coin= jstr(argjson,"coin")) != 0 ) + }*/ + else if ( coin[0] != 0 ) { if ( strcmp(method,"enable") == 0 ) { @@ -319,14 +400,28 @@ stop()\n\ if ( ptr->userpass[0] == 0 ) { cJSON *retjson = cJSON_CreateObject(); - jaddstr(retjson,"error","couldnt find coin locally installed"); + jaddstr(retjson,"error",LP_DONTCHANGE_ERRMSG0); jaddstr(retjson,"coin",coin); return(jprint(retjson,1)); } if ( LP_conflicts_find(ptr) == 0 ) { ptr->inactive = 0; - cJSON *array = cJSON_CreateArray(); + cJSON *array; int32_t notarized; + if ( LP_getheight(¬arized,ptr) <= 0 ) + { + ptr->inactive = (uint32_t)time(NULL); + return(clonestr("{\"error\":\"coin cant be activated till synced\"}")); + } + else + { + if ( ptr->smartaddr[0] != 0 ) + LP_unspents_load(coin,ptr->smartaddr); + LP_unspents_load(coin,ptr->smartaddr); + if ( strcmp(ptr->symbol,"KMD") == 0 ) + LP_importaddress("KMD",BOTS_BONDADDRESS); + } + array = cJSON_CreateArray(); jaddi(array,LP_coinjson(ptr,0)); return(jprint(array,1)); } else return(clonestr("{\"error\":\"coin port conflicts with existing coin\"}")); @@ -343,6 +438,34 @@ stop()\n\ return(jprint(array,1)); } else return(clonestr("{\"error\":\"couldnt find coin\"}")); } + else if ( strcmp(method,"listunspent") == 0 ) + { + if ( (ptr= LP_coinsearch(coin)) != 0 ) + { + char *coinaddr; bits256 zero; + memset(zero.bytes,0,sizeof(zero)); + if ( (coinaddr= jstr(argjson,"address")) != 0 ) + { + if ( coinaddr[0] != 0 ) + { + LP_address(ptr,coinaddr); + if ( strcmp(coinaddr,ptr->smartaddr) == 0 && bits256_nonz(G.LP_privkey) != 0 ) + { + LP_listunspent_issue(coin,coinaddr,2,zero,zero); + //LP_privkey_init(-1,ptr,G.LP_privkey,G.LP_mypub25519); + } + return(jprint(LP_listunspent(coin,coinaddr,zero,zero),1)); + } + } + return(clonestr("{\"error\":\"no address specified\"}")); + } else return(clonestr("{\"error\":\"cant find coind\"}")); + } + else if ( strcmp(method,"balance") == 0 ) + { + if ( (ptr= LP_coinsearch(coin)) != 0 ) + return(jprint(LP_address_balance(ptr,jstr(argjson,"address"),1),1)); + else return(clonestr("{\"error\":\"cant find coind\"}")); + } else if ( strcmp(method,"electrum") == 0 ) { if ( (ptr= LP_coinsearch(coin)) != 0 ) @@ -357,7 +480,7 @@ stop()\n\ } else if ( strcmp(method,"getrawtransaction") == 0 ) { - return(jprint(LP_gettx(coin,jbits256(argjson,"txid")),0)); + return(jprint(LP_gettx(coin,jbits256(argjson,"txid"),0),1)); } else if ( strcmp(method,"withdraw") == 0 ) { @@ -404,14 +527,23 @@ stop()\n\ else return(clonestr("{\"error\":\"cant find coind\"}")); } if ( LP_isdisabled(coin,0) != 0 ) - return(clonestr("{\"error\":\"coin is disabled\"}")); + { + retjson = cJSON_CreateObject(); + jaddstr(retjson,"error",LP_DONTCHANGE_ERRMSG1); + return(jprint(retjson,1)); + } if ( strcmp(method,"inventory") == 0 ) { struct iguana_info *ptr; if ( (ptr= LP_coinfind(coin)) != 0 ) { - //privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,ptr,"",USERPASS_WIFSTR); - //LP_utxopurge(0); + LP_address(ptr,ptr->smartaddr); + if ( jint(argjson,"reset") != 0 ) + { + ptr->privkeydepth = 0; + LP_address_utxo_reset(ptr); + LP_passphrase_init(jstr(argjson,"passphrase"),G.gui); + } if ( bits256_nonz(G.LP_privkey) != 0 ) LP_privkey_init(-1,ptr,G.LP_privkey,G.LP_mypub25519); else printf("no LP_privkey\n"); @@ -419,9 +551,11 @@ stop()\n\ jaddstr(retjson,"result","success"); jaddstr(retjson,"coin",coin); jaddnum(retjson,"timestamp",time(NULL)); - jadd(retjson,"alice",LP_inventory(coin)); + jadd(retjson,"alice",cJSON_Parse("[]")); + //jadd(retjson,"alice",LP_inventory(coin)); //jadd(retjson,"bob",LP_inventory(coin,1)); - LP_smartutxos_push(ptr); + //LP_smartutxos_push(ptr); + LP_address_utxo_reset(ptr); return(jprint(retjson,1)); } } @@ -458,55 +592,85 @@ stop()\n\ } argjson = reqjson; } + if ( strcmp(method,"getdPoW") == 0 ) + retstr = clonestr("{\"result\":\"success\"}"); + } + else + { + if ( strcmp(method,"tradesarray") == 0 ) + { + return(jprint(LP_tradesarray(base,rel,juint(argjson,"starttime"),juint(argjson,"endtime"),jint(argjson,"timescale")),1)); + } + else if ( strcmp(method,"getdPoW") == 0 ) + { + if ( (ptr= LP_coinfind(jstr(argjson,"coin"))) != 0 ) + LP_dPoW_broadcast(ptr); + retstr = clonestr("{\"result\":\"success\"}"); + } } // received response - if ( strcmp(method,"postprice") == 0 ) + if ( strcmp(method,"swapstatus") == 0 ) + return(LP_swapstatus_recv(argjson)); + else if ( strcmp(method,"gettradestatus") == 0 ) + return(LP_gettradestatus(j64bits(argjson,"aliceid"),juint(argjson,"requestid"),juint(argjson,"quoteid"))); + else if ( strcmp(method,"postprice") == 0 ) return(LP_postprice_recv(argjson)); - else if ( strcmp(method,"postutxos") == 0 ) - return(LP_postutxos_recv(argjson)); else if ( strcmp(method,"uitem") == 0 ) return(LP_uitem_recv(argjson)); + else if ( strcmp(method,"dPoW") == 0 ) + return(LP_dPoW_recv(argjson)); else if ( strcmp(method,"notify") == 0 ) return(LP_notify_recv(argjson)); + else if ( strcmp(method,"getpeers") == 0 ) + retstr = clonestr("{\"error\":\"deprecated\"}"); + else if ( strcmp(method,"balances") == 0 ) + return(jprint(LP_balances(jstr(argjson,"address")),1)); + else if ( strcmp(method,"fundvalue") == 0 ) + return(jprint(LP_fundvalue(argjson),1)); + else if ( strcmp(method,"getprice") == 0 ) + { + double price,bid,ask; + ask = LP_price(base,rel); + if ( (bid= LP_price(rel,base)) > SMALLVAL ) + bid = 1./bid; + price = _pairaved(bid,ask); + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jaddstr(retjson,"base",base); + jaddstr(retjson,"rel",rel); + jaddnum(retjson,"timestamp",time(NULL)); + jaddnum(retjson,"bid",bid); + jaddnum(retjson,"ask",ask); + jaddnum(retjson,"price",price); + return(jprint(retjson,1)); + } + /*else if ( strcmp(method,"getpeers") == 0 ) + { + char *tmpstr; + if ( (tmpstr= jstr(argjson,"LPnode")) != 0 ) + LP_addpeer(LP_mypeer,LP_mypubsock,tmpstr,RPC_port,RPC_port+10,RPC_port+20,1,G.LP_sessionid); + if ( IAMLP != 0 ) + { + printf("send peers list %s\n",LP_peers()); + bits256 zero; memset(zero.bytes,0,sizeof(zero)); + LP_reserved_msg(0,"","",zero,LP_peers()); + } + retstr = clonestr("{\"result\":\"success\"}"); + }*/ // end received response - // public access, even from http else if ( strcmp(method,"tradestatus") == 0 ) { LP_tradecommand_log(argjson); - printf("GOT TRADESTATUS! %s\n",jprint(argjson,0)); + printf("%-4d tradestatus | aliceid.%llu RT.%d %d\n",(uint32_t)time(NULL) % 3600,(long long)j64bits(argjson,"aliceid"),LP_RTcount,LP_swapscount); retstr = clonestr("{\"result\":\"success\"}"); } - else if ( strcmp(method,"balance") == 0 ) - { - if ( (ptr= LP_coinsearch(jstr(argjson,"coin"))) != 0 ) - return(jprint(LP_address_balance(ptr,jstr(argjson,"address"),1),1)); - else return(clonestr("{\"error\":\"cant find coind\"}")); - } - else if ( strcmp(method,"pricearray") == 0 ) - { - uint32_t firsttime; - if ( base != 0 && rel != 0 ) - { - if ( (firsttime= juint(argjson,"firsttime")) < time(NULL)-30*24*3600 ) - firsttime = (uint32_t)(time(NULL)-30*24*3600); - return(jprint(LP_pricearray(base,rel,firsttime,juint(argjson,"lasttime"),jint(argjson,"timescale")),1)); - } else return(clonestr("{\"error\":\"pricearray needs base and rel\"}")); - } - else if ( strcmp(method,"getprices") == 0 ) - return(LP_prices()); - else if ( strcmp(method,"orderbook") == 0 ) - return(LP_orderbook(base,rel,jint(argjson,"duration"))); - else if ( strcmp(method,"getpeers") == 0 ) - return(LP_peers()); - else if ( strcmp(method,"getcoins") == 0 ) - return(jprint(LP_coinsjson(0),1)); else if ( strcmp(method,"wantnotify") == 0 ) { bits256 pub; static uint32_t lastnotify; pub = jbits256(argjson,"pub"); //char str[65]; printf("got wantnotify.(%s) vs %s\n",jprint(argjson,0),bits256_str(str,G.LP_mypub25519)); - if ( bits256_cmp(pub,G.LP_mypub25519) == 0 && time(NULL) > lastnotify+30 ) + if ( bits256_cmp(pub,G.LP_mypub25519) == 0 && time(NULL) > lastnotify+60 ) { lastnotify = (uint32_t)time(NULL); //printf("wantnotify for me!\n"); @@ -514,36 +678,10 @@ stop()\n\ } retstr = clonestr("{\"result\":\"success\"}"); } - else if ( strcmp(method,"listunspent") == 0 ) - { - if ( (ptr= LP_coinsearch(jstr(argjson,"coin"))) != 0 ) - { - char *coinaddr; - if ( (coinaddr= jstr(argjson,"address")) != 0 ) - { - if ( coinaddr[0] != 0 ) - { - LP_address(ptr,coinaddr); - LP_listunspent_issue(coin,coinaddr,1); - if ( strcmp(coinaddr,ptr->smartaddr) == 0 && bits256_nonz(G.LP_privkey) != 0 ) - { - printf("network invoked\n"); - LP_privkey_init(-1,ptr,G.LP_privkey,G.LP_mypub25519); - //LP_smartutxos_push(ptr); - } - else - { - - } - } - return(jprint(LP_address_utxos(ptr,coinaddr,1),1)); - } else return(clonestr("{\"error\":\"no address specified\"}")); - } else return(clonestr("{\"error\":\"cant find coind\"}")); - } else if ( strcmp(method,"addr_unspents") == 0 ) { //printf("GOT ADDR_UNSPENTS %s %s\n",jstr(argjson,"coin"),jstr(argjson,"address")); - if ( (ptr= LP_coinsearch(jstr(argjson,"coin"))) != 0 ) + if ( (ptr= LP_coinsearch(coin)) != 0 ) { char *coinaddr; if ( (coinaddr= jstr(argjson,"address")) != 0 ) @@ -554,6 +692,8 @@ stop()\n\ if ( strcmp(coinaddr,ptr->smartaddr) == 0 && bits256_nonz(G.LP_privkey) != 0 ) { //printf("ADDR_UNSPENTS %s %s is my address being asked for!\n",ptr->symbol,coinaddr); + if ( ptr->lastpushtime > 0 && ptr->addr_listunspent_requested > (uint32_t)time(NULL)-10 ) + ptr->lastpushtime -= LP_ORDERBOOK_DURATION*0.1; ptr->addr_listunspent_requested = (uint32_t)time(NULL); } } diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index f53c28993..5c009d2cd 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -21,10 +21,20 @@ #ifndef LP_INCLUDE_H #define LP_INCLUDE_H +#ifdef FROMGUI +#define printf(...) +#endif + +#define LP_MAJOR_VERSION "0" +#define LP_MINOR_VERSION "1" +#define LP_BUILD_NUMBER "17701" +#define LP_BARTERDEX_VERSION 1 +#define LP_MAGICBITS 1 + #ifdef FROM_JS #include -#define sleep(x) emscripten_sleep((x) * 1000) -void emscripten_usleep(int32_t x); +#define sleep(x) emscripten_usleep((x) * 1000000) +void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping #define usleep(x) emscripten_usleep(x) // ./autogen.sh // emconfigure ./configure CFLAGS="-s PTHREAD_POOL_SIZE=8 -s USE_PTHREADS=1 -O2" @@ -34,26 +44,36 @@ void emscripten_usleep(int32_t x); #endif //#define LP_STRICTPEERS -#define LP_BARTERDEX_VERSION 0 -#define LP_MAGICBITS 8 +#define LP_MAXVINS 64 #define LP_HTTP_TIMEOUT 3 // 1 is too small due to edge cases of time(NULL) -#define LP_AUTOTRADE_TIMEOUT 15 -#define ELECTRUM_TIMEOUT 10 -#define LP_ELECTRUM_MAXERRORS 3 +#define LP_AUTOTRADE_TIMEOUT 60 +#define LP_RESERVETIME 600 //(LP_AUTOTRADE_TIMEOUT * 2) +#define ELECTRUM_TIMEOUT 7 +#define LP_ELECTRUM_KEEPALIVE 60 +#define LP_ELECTRUM_MAXERRORS 777 #define LP_MEMPOOL_TIMEINCR 10 +#define LP_SCREENWIDTH 1024 + +#define LP_MIN_PEERS 8 +#define LP_MAX_PEERS 32 + +#define LP_MAXDESIRED_UTXOS (IAMLP != 0 ? 256 : 64) +#define LP_MINDESIRED_UTXOS (IAMLP != 0 ? 64 : 16) +#define LP_DUSTCOMBINE_THRESHOLD 1000000 // RTmetrics #define LP_RTMETRICS_TOPGROUP 1.01 -#define LP_MAXPENDING_SWAPS 13 +//#define LP_MAXPENDING_SWAPS 13 +#define LP_CLIENT_STATSPARSE (90 * 1024 * 1024) #define LP_COMMAND_SENDSOCK NN_PUSH #define LP_COMMAND_RECVSOCK NN_PULL #define DPOW_MIN_ASSETCHAIN_SIGS 11 -#define LP_ENCRYPTED_MAXSIZE (4096 + 2 + crypto_box_NONCEBYTES + crypto_box_ZEROBYTES) +#define LP_ENCRYPTED_MAXSIZE (16384 + 2 + crypto_box_NONCEBYTES + crypto_box_ZEROBYTES) -#define LP_MAXPUBKEY_ERRORS 3 +#define LP_MAXPUBKEY_ERRORS 10 #define PSOCK_KEEPALIVE 3600 #define MAINLOOP_PERSEC 100 #define MAX_PSOCK_PORT 60000 @@ -68,7 +88,7 @@ void emscripten_usleep(int32_t x); #define LP_SWAPSTEP_TIMEOUT 30 #define LP_MIN_TXFEE 10000 #define LP_MINVOL 20 -#define LP_MINCLIENTVOL 1000 +#define LP_MINCLIENTVOL 200 #define LP_MINSIZE_TXFEEMULT 10 #define LP_REQUIRED_TXFEE 0.8 @@ -83,14 +103,18 @@ void emscripten_usleep(int32_t x); #define JUMBLR_RMD160 "5177f8b427e5f47342a4b8ab5dac770815d4389e" #define TIERNOLAN_RMD160 "daedddd8dbe7a2439841ced40ba9c3d375f98146" #define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu" -#define INSTANTDEX_BTCD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf" +#define INSTANTDEX_KMD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf" +#define BOTS_BONDADDRESS "RNdqHx26GWy9bk8MtmH1UiXjQcXE4RKK2P" +#define BOTS_BONDPUBKEY33 "03e641d22e1ff5a7d45c8880537e0b0a114d7b9fee2c18a6b4a8a80b6285292990" +#define LP_WEEKMULTBAD (7 * 24 * 2600) +#define LP_WEEKMULT (7 * 24 * 3600) +#define LP_FIRSTWEEKTIME 1510790400 // must be 0 mod LP_WEEKMULT //#define BASILISK_DISABLEWAITTX //#define BASILISK_DISABLESENDTX #define LP_RPCPORT 7783 #define LP_PROPAGATION_SLACK 100 // txid ordering is not enforced, so getting extra recent txid -#define LP_RESERVETIME 60 #define LP_AVETXSIZE 256 #define LP_CACHEDURATION 60 #define BASILISK_DEFAULT_NUMCONFIRMS 1 @@ -100,15 +124,29 @@ void emscripten_usleep(int32_t x); #define LP_IS_ZCASHPROTOCOL 1 #define LP_IS_BITCOINCASH 2 +#define LP_IS_BITCOINGOLD 79 #define SIGHASH_FORKID 0x40 #define ZKSNARK_PROOF_SIZE 296 #define ZCASH_SOLUTION_ELEMENTS 1344 +#define LP_REQUEST 0 +#define LP_RESERVED 1 +#define LP_CONNECT 2 +#define LP_CONNECTED 3 + +#define LP_DONTCHANGE_ERRMSG0 "couldnt find coin locally installed" +#define LP_DONTCHANGE_ERRMSG1 "coin is disabled" + extern char GLOBAL_DBDIR[]; extern int32_t IAMLP; -struct iguana_msgvin { bits256 prev_hash; uint8_t *vinscript,*userdata,*spendscript,*redeemscript; uint32_t prev_vout,sequence; uint16_t scriptlen,p2shlen,userdatalen,spendlen; }; +struct iguana_msgvin +{ + bits256 prev_hash; + uint8_t *vinscript,*userdata,*spendscript,*redeemscript; + uint32_t prev_vout,sequence; uint16_t scriptlen,p2shlen,userdatalen,spendlen; +}; struct iguana_msgvout { uint64_t value; uint32_t pk_scriptlen; uint8_t *pk_script; }; @@ -137,25 +175,25 @@ struct vin_signer { bits256 privkey; char coinaddr[64]; uint8_t siglen,sig[80],r struct vin_info { struct iguana_msgvin vin; uint64_t amount; cJSON *extras; bits256 sigtxid; - int32_t M,N,validmask,spendlen,type,p2shlen,numpubkeys,numsigs,height,hashtype,userdatalen,suppress_pubkeys,ignore_cltverr; - uint32_t sequence,unspentind; struct vin_signer signers[16]; char coinaddr[65]; + int32_t M,N,validmask,spendlen,type,p2shlen,numpubkeys,numsigs,height,userdatalen,suppress_pubkeys,ignore_cltverr; + uint32_t sequence,unspentind,hashtype; struct vin_signer signers[16]; char coinaddr[65]; uint8_t rmd160[20],spendscript[10000],p2shscript[10000],userdata[10000]; }; -struct basilisk_swapmessage +/*struct basilisk_swapmessage { bits256 srchash,desthash; uint32_t crc32,msgbits,quoteid,datalen; uint8_t *data; -}; +};*/ struct basilisk_swap; struct basilisk_rawtxinfo { - char destaddr[64],coinstr[16]; + char destaddr[64]; bits256 txid,signedtxid,actualtxid; - uint64_t amount,change,inputsum; + int64_t amount,change,inputsum; int32_t redeemlen,datalen,completed,vintype,vouttype,numconfirms,spendlen,secretstart,suppress_pubkeys; uint32_t locktime,crcs[2]; uint8_t addrtype,pubkey33[33],rmd160[20]; @@ -164,20 +202,19 @@ struct basilisk_rawtxinfo struct basilisk_request { uint32_t requestid,timestamp,quoteid,quotetime; // 0 to 15 - uint64_t srcamount,unused; // 16 to 31 + int64_t srcamount,unused; // 16 to 31 bits256 srchash; // 32 to 63 bits256 desthash; - char src[8],dest[8]; + char src[68],dest[68]; uint64_t destamount; int32_t optionhours,DEXselector; }; struct basilisk_rawtx { - char name[32]; + char name[32],symbol[65]; struct iguana_msgtx msgtx; struct basilisk_rawtxinfo I; - struct iguana_info *coin; char vinstr[8192],p2shaddr[64]; cJSON *vins; bits256 utxotxid; int32_t utxovout; @@ -187,11 +224,11 @@ struct basilisk_rawtx struct basilisk_swapinfo { struct basilisk_request req; - char bobstr[64],alicestr[64]; + char bobstr[128],alicestr[128]; bits256 myhash,otherhash,orderhash; uint32_t statebits,otherstatebits,started,expiration,finished,dead,reftime,putduration,callduration; int32_t bobconfirms,aliceconfirms,iambob,reclaimed,bobspent,alicespent,pad,aliceistrusted,bobistrusted,otheristrusted,otherstrust,alicemaxconfirms,bobmaxconfirms; - uint64_t alicesatoshis,bobsatoshis,bobinsurance,aliceinsurance,Atxfee,Btxfee; + int64_t alicesatoshis,bobsatoshis,bobinsurance,aliceinsurance,Atxfee,Btxfee; bits256 myprivs[2],mypubs[2],otherpubs[2],pubA0,pubA1,pubB0,pubB1,privAm,pubAm,privBn,pubBn; uint32_t crcs_mypub[2],crcs_mychoosei[2],crcs_myprivs[2],crcs_mypriv[2]; @@ -206,12 +243,45 @@ struct basilisk_swapinfo uint8_t userdata_bobrefund[256],userdata_bobrefundlen; }; -struct LP_outpoint { bits256 spendtxid; uint64_t value,interest; int32_t spendvini,spendheight; char coinaddr[64]; }; +#define BASILISK_ALICESPEND 0 +#define BASILISK_BOBSPEND 1 +#define BASILISK_BOBPAYMENT 2 +#define BASILISK_ALICEPAYMENT 3 +#define BASILISK_BOBDEPOSIT 4 +#define BASILISK_OTHERFEE 5 +#define BASILISK_MYFEE 6 +#define BASILISK_BOBREFUND 7 +#define BASILISK_BOBRECLAIM 8 +#define BASILISK_ALICERECLAIM 9 +#define BASILISK_ALICECLAIM 10 +//0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0 +char *txnames[] = { "alicespend", "bobspend", "bobpayment", "alicepayment", "bobdeposit", "otherfee", "myfee", "bobrefund", "bobreclaim", "alicereclaim", "aliceclaim" }; + +struct LP_swap_remember +{ + bits256 pubA0,pubB0,pubB1,privAm,privBn,paymentspent,Apaymentspent,depositspent,myprivs[2],txids[sizeof(txnames)/sizeof(*txnames)]; + uint64_t Atxfee,Btxfee,srcamount,destamount,aliceid; + int64_t values[sizeof(txnames)/sizeof(*txnames)]; + uint32_t finishtime,tradeid,requestid,quoteid,plocktime,dlocktime,expiration,state,otherstate; + int32_t iambob,finishedflag,origfinishedflag,Predeemlen,Dredeemlen,sentflags[sizeof(txnames)/sizeof(*txnames)]; + uint8_t secretAm[20],secretAm256[32],secretBn[20],secretBn256[32],Predeemscript[1024],Dredeemscript[1024],pubkey33[33],other33[33]; + char Agui[65],Bgui[65],gui[65],src[65],dest[65],destaddr[64],Adestaddr[64],Sdestaddr[64],alicepaymentaddr[64],bobpaymentaddr[64],bobdepositaddr[64],alicecoin[65],bobcoin[65],*txbytes[sizeof(txnames)/sizeof(*txnames)]; +}; + +struct LP_outpoint +{ + bits256 spendtxid; + uint64_t value,interest; + int32_t spendvini,spendheight; + char coinaddr[64]; +}; struct LP_transaction { UT_hash_handle hh; - bits256 txid; int32_t height,numvouts,numvins,len; //uint32_t timestamp; + bits256 txid; + long fpos; + int32_t height,numvouts,numvins,len,SPV; uint8_t *serialized; struct LP_outpoint outpoints[]; }; @@ -221,16 +291,18 @@ struct iguana_info UT_hash_handle hh; portable_mutex_t txmutex,addrmutex; struct LP_transaction *transactions; struct LP_address *addresses; uint64_t txfee; - int32_t longestchain,firstrefht,firstscanht,lastscanht,bussock,height; uint16_t busport; - uint32_t lastutxosync,addr_listunspent_requested,lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,obooktime; + int32_t numutxos,notarized,longestchain,firstrefht,firstscanht,lastscanht,bussock,height; uint16_t busport; + uint32_t dPoWtime,loadedcache,electrumlist,lastunspent,importedprivkey,lastpushtime,lastutxosync,addr_listunspent_requested,lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,obooktime; uint8_t pubtype,p2shtype,isPoS,wiftype,wiftaddr,taddr,noimportprivkey_flag,userconfirms,isassetchain,maxconfirms; - char symbol[16],smartaddr[64],userpass[1024],serverport[128]; + char symbol[128],smartaddr[64],userpass[1024],serverport[128],instantdex_address[64]; // portfolio double price_kmd,force,perc,goal,goalperc,relvolume,rate; void *electrum; void *ctx; uint64_t maxamount,kmd_equiv,balanceA,balanceB,valuesumA,valuesumB; uint8_t pubkey33[33],zcash; - bits256 cachedtxid; uint8_t *cachedtxiddata; int32_t cachedtxidlen; + int32_t privkeydepth; + bits256 cachedtxid,notarizationtxid; uint8_t *cachedtxiddata; int32_t cachedtxidlen; + bits256 cachedmerkle,notarizedhash; int32_t cachedmerkleheight; }; struct _LP_utxoinfo { bits256 txid; uint64_t value; int32_t vout,height; }; @@ -241,7 +313,7 @@ struct LP_utxobob { struct _LP_utxoinfo utxo,deposit; }; struct LP_utxoalice { struct _LP_utxoinfo utxo,fee; }; -struct LP_utxoswap { bits256 otherpubkey; void *swap; uint64_t satoshis; }; +//struct LP_utxoswap { bits256 otherpubkey; uint64_t satoshis; }; struct LP_utxoinfo { @@ -249,11 +321,12 @@ struct LP_utxoinfo bits256 pubkey; struct _LP_utxoinfo payment,deposit,fee; struct LP_utxostats T; - struct LP_utxoswap S; + int64_t swap_satoshis; + //struct LP_utxoswap S; int32_t iambob,iamlp; uint8_t key[sizeof(bits256) + sizeof(int32_t)]; uint8_t key2[sizeof(bits256) + sizeof(int32_t)]; - char coin[16],coinaddr[64],gui[16];//spendscript[256]; + char coin[65],coinaddr[64],gui[16];//spendscript[256]; }; struct LP_address_utxo @@ -261,6 +334,7 @@ struct LP_address_utxo struct LP_address_utxo *next,*prev; struct _LP_utxoinfo U; int32_t SPV,spendheight; + //uint32_t timestamp; }; struct LP_address @@ -268,19 +342,19 @@ struct LP_address UT_hash_handle hh; struct LP_address_utxo *utxos; bits256 pubkey; - int64_t balance,total; + int64_t balance,total,instantdex_credits; uint32_t timestamp,n,unspenttime; int32_t unspentheight; char coinaddr[40]; - uint8_t pubsecp[33],pad; + uint8_t pubsecp[33],didinstantdex; }; struct LP_peerinfo { UT_hash_handle hh; uint64_t ip_port; - uint32_t ipbits,errortime,errors,numpeers,needping,lasttime,connected,lastutxos,lastpeers,diduquery,good,sessionid; - int32_t pushsock,subsock; + uint32_t recvtime,numrecv,ipbits,errortime,errors,numpeers,needping,lasttime,connected,lastutxos,lastpeers,diduquery,good,sessionid; + int32_t pushsock,subsock,isLP; uint16_t port; char ipaddr[64]; }; @@ -289,43 +363,96 @@ struct LP_quoteinfo { struct basilisk_request R; bits256 srchash,desthash,txid,txid2,desttxid,feetxid,privkey; + int64_t othercredits; uint64_t satoshis,txfee,destsatoshis,desttxfee,aliceid; - uint32_t timestamp,quotetime; int32_t vout,vout2,destvout,feevout,pair; - char srccoin[16],coinaddr[64],destcoin[16],destaddr[64],gui[64]; + uint32_t timestamp,quotetime,tradeid; + int32_t vout,vout2,destvout,feevout,pair; + char srccoin[65],coinaddr[64],destcoin[65],destaddr[64],gui[64]; }; struct LP_endpoint { int32_t pair; char ipaddr[64]; uint16_t port; }; struct basilisk_swap { - void *ctx; struct iguana_info bobcoin,alicecoin; struct LP_utxoinfo *utxo; + void *ctx; //struct LP_utxoinfo *utxo; struct LP_endpoint N; void (*balancingtrade)(struct basilisk_swap *swap,int32_t iambob); - int32_t subsock,pushsock,connected,aliceunconf,depositunconf,paymentunconf; uint32_t lasttime,aborted; + int32_t subsock,pushsock,connected,aliceunconf,depositunconf,paymentunconf; + uint32_t lasttime,aborted,tradeid; FILE *fp; bits256 persistent_privkey,persistent_pubkey; struct basilisk_swapinfo I; struct basilisk_rawtx bobdeposit,bobpayment,alicepayment,myfee,otherfee,aliceclaim,alicespend,bobreclaim,bobspend,bobrefund,alicereclaim; bits256 privkeys[INSTANTDEX_DECKSIZE]; - struct basilisk_swapmessage *messages; int32_t nummessages,sentflag; + //struct basilisk_swapmessage *messages; int32_t nummessages,sentflag; char Bdeposit[64],Bpayment[64]; uint64_t aliceid,otherdeck[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2]; uint8_t persistent_pubkey33[33],persistent_other33[33],changermd160[20],pad[15],verifybuf[100000]; - }; +struct LP_pubkey_quote +{ + struct LP_pubkey_quote *next,*prev; + float price; + uint32_t maxutxo,aveutxo; + uint8_t baseind,relind,numutxos,scale; +}; + +struct LP_swapstats +{ + UT_hash_handle hh; + struct LP_quoteinfo Q; + bits256 bobdeposit,alicepayment,bobpayment,paymentspent,Apaymentspent,depositspent; + int32_t bobdeposit_ht,alicepayment_ht,bobpayment_ht,paymentspent_ht,Apaymentspent_ht,depositspent_ht; + double qprice; + uint64_t aliceid; + int32_t bobneeds_dPoW,aliceneeds_dPoW; + uint32_t ind,methodind,finished,expired,lasttime,dPoWfinished; + char alicegui[32],bobgui[32]; +}; + +struct LP_pubswap { struct LP_pubswap *next,*prev; struct LP_swapstats *swap; }; + #define LP_MAXPRICEINFOS 256 -struct LP_pubkeyinfo +struct LP_pubkey_info { UT_hash_handle hh; bits256 pubkey; - float matrix[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS]; - uint32_t timestamps[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS],timestamp,numerrors; + struct LP_pubkey_quote *quotes; + struct LP_pubswap *bobswaps,*aliceswaps; + int64_t dynamictrust,unconfcredits; + uint32_t timestamp,numerrors,lasttime,slowresponse; int32_t istrusted; uint8_t rmd160[20],sig[65],pubsecp[33],siglen; }; -int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *pubp,cJSON *item); +struct electrum_info +{ + queue_t sendQ,pendingQ; + portable_mutex_t mutex,txmutex; + struct electrum_info *prev; + int32_t bufsize,sock,*heightp,numerrors; + struct iguana_info *coin; + uint32_t stratumid,lasttime,keepalive,pending,*heighttimep; + char ipaddr[64],symbol[66]; + uint16_t port; + uint8_t buf[]; +}; + +struct LP_trade +{ + struct LP_trade *next,*prev; + UT_hash_handle hh; + uint64_t aliceid; + int64_t besttrust,bestunconfcredits; + double bestprice; + uint32_t negotiationdone,bestresponse,connectsent,firsttime,lasttime,firstprocessed,lastprocessed,newtime; + char pairstr[64],funcid,iambob; + struct LP_quoteinfo Qs[4],Q; +}; + +uint32_t LP_sighash(char *symbol,int32_t zcash); +int32_t LP_pubkey_sigcheck(struct LP_pubkey_info *pubp,cJSON *item); int32_t LP_pubkey_sigadd(cJSON *item,uint32_t timestamp,bits256 priv,bits256 pub,uint8_t *rmd160,uint8_t *pubsecp); int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson); struct LP_address *LP_address(struct iguana_info *coin,char *coinaddr); @@ -333,33 +460,44 @@ void LP_swap_coinaddr(struct iguana_info *coin,char *coinaddr,uint64_t *valuep,u void basilisk_dontforget_update(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx); uint32_t basilisk_requestid(struct basilisk_request *rp); uint32_t basilisk_quoteid(struct basilisk_request *rp); -struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp); +struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp,int32_t dynamictrust); char *bitcoind_passthru(char *coinstr,char *serverport,char *userpass,char *method,char *params); uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx,uint32_t nextbits,int32_t suppress_swapsend); -//double LP_query(char *method,struct LP_quoteinfo *qp,char *base,char *rel,bits256 mypub); int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys); void LP_quotesinit(char *base,char *rel); int32_t LP_forward(void *ctx,char *myipaddr,int32_t pubsock,bits256 pubkey,char *jsonstr,int32_t freeflag); -int32_t LP_ismine(struct LP_utxoinfo *utxo); -int32_t LP_isavailable(struct LP_utxoinfo *utxo); struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port); uint64_t LP_value_extract(cJSON *obj,int32_t addinterest); int32_t LP_swap_getcoinaddr(char *symbol,char *coinaddr,bits256 txid,int32_t vout); char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen); +int64_t LP_kmdvalue(char *symbol,int64_t satoshis); int64_t LP_komodo_interest(bits256 txid,int64_t value); -void LP_availableset(struct LP_utxoinfo *utxo); +void LP_availableset(bits256 txid,int32_t vout); int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2); int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsock,int32_t pullsock); -uint16_t LP_psock_get(char *connectaddr,char *connectaddr2,char *publicaddr,int32_t ispaired); +int64_t LP_listunspent_parseitem(struct iguana_info *coin,bits256 *txidp,int32_t *voutp,int32_t *heightp,cJSON *item); +void LP_unspents_cache(char *symbol,char *addr,char *arraystr,int32_t updatedflag); +uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired); //void LP_utxo_clientpublish(struct LP_utxoinfo *utxo); int32_t LP_coinbus(uint16_t coin_busport); int32_t LP_nanomsg_recvs(void *ctx); -uint64_t LP_smartbalance(struct iguana_info *coin); -int32_t LP_getheight(struct iguana_info *coin); -int32_t LP_reserved_msg(char *base,char *rel,bits256 pubkey,char *msg); +int32_t LP_numconfirms(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t mempool); +void LP_aliceid(uint32_t tradeid,uint64_t aliceid,char *event,uint32_t requestid,uint32_t quoteid); +cJSON *LP_cache_transaction(struct iguana_info *coin,bits256 txid,uint8_t *serialized,int32_t len); +cJSON *LP_transaction_fromdata(struct iguana_info *coin,bits256 txid,uint8_t *serialized,int32_t len); +uint64_t LP_RTsmartbalance(struct iguana_info *coin); +int32_t LP_getheight(int32_t *notarizedp,struct iguana_info *coin); +int32_t LP_reserved_msg(int32_t priority,char *base,char *rel,bits256 pubkey,char *msg); struct iguana_info *LP_coinfind(char *symbol); int32_t LP_crc32find(int32_t *duplicatep,int32_t ind,uint32_t crc32); char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *rel,double price); +int32_t LP_merkleproof(struct iguana_info *coin,char *coinaddr,struct electrum_info *ep,bits256 txid,int32_t height); +cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr,bits256 reftxid); +cJSON *LP_myzdebits(); +int32_t _LP_utxos_remove(bits256 txid,int32_t vout); +int32_t LP_utxos_remove(bits256 txid,int32_t vout); +struct LP_transaction *LP_transactionadd(struct iguana_info *coin,bits256 txid,int32_t height,int32_t numvouts,int32_t numvins); +void LP_tradebot_finished(uint32_t tradeid,uint32_t requestid,uint32_t quoteid); uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee,int32_t txlen); struct LP_address *_LP_address(struct iguana_info *coin,char *coinaddr); struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr); @@ -367,30 +505,47 @@ struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr); int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,struct iguana_msgtx *msgtx,char **signedtxp,bits256 *signedtxidp,struct vin_info *V,int32_t numinputs,char *rawtx,cJSON *vins,cJSON *privkeysjson,int32_t zcash); //void LP_butxo_swapfields_set(struct LP_utxoinfo *butxo); struct LP_address_utxo *LP_address_utxofind(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout); +int64_t LP_myzcredits(); +void LP_instantdex_depositadd(char *coinaddr,bits256 txid); +int64_t LP_instantdex_creditcalc(struct iguana_info *coin,int32_t dispflag,bits256 txid,char *refaddr); int32_t LP_destaddr(char *destaddr,cJSON *item); int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t duration); -char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey); +cJSON *LP_statslog_disp(uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey,char *refbase,char *refrel); +uint32_t LP_heighttime(char *symbol,int32_t height); +uint64_t LP_unspents_load(char *symbol,char *addr); +int32_t LP_validSPV(char *symbol,char *coinaddr,bits256 txid,int32_t vout); struct LP_transaction *LP_transactionfind(struct iguana_info *coin,bits256 txid); cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJSON *txobj); int32_t LP_mempoolscan(char *symbol,bits256 searchtxid); int32_t LP_txheight(struct iguana_info *coin,bits256 txid); int32_t LP_numpeers(); -char *basilisk_swapentry(uint32_t requestid,uint32_t quoteid); -uint64_t LP_KMDvalue(struct iguana_info *coin,uint64_t balance); -int32_t LP_address_utxoadd(char *debug,struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight); +double LP_CMCbtcprice(double *price_usdp,char *symbol); +char *basilisk_swapentry(uint32_t requestid,uint32_t quoteid,int32_t forceflag); +int64_t LP_KMDvalue(struct iguana_info *coin,int64_t balance); +int32_t LP_address_utxoadd(uint32_t timestamp,char *debug,struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight); void LP_smartutxos_push(struct iguana_info *coin); +void LP_cacheptrs_init(struct iguana_info *coin); cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrumret); cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout); void LP_postutxos(char *symbol,char *coinaddr); int32_t LP_listunspent_both(char *symbol,char *coinaddr,int32_t fullflag); uint16_t LP_randpeer(char *destip); -cJSON *bitcoin_data2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash); +void LP_tradebot_pauseall(); +void LP_portfolio_reset(); +uint32_t LP_atomic_locktime(char *base,char *rel); +struct LP_pubkey_info *LP_pubkeyfind(bits256 pubkey); +char *issue_LP_psock(char *destip,uint16_t destport,int32_t ispaired); +char *LP_unspents_filestr(char *symbol,char *addr); +cJSON *bitcoin_data2json(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash); //int32_t LP_butxo_findeither(bits256 txid,int32_t vout); -cJSON *LP_listunspent(char *symbol,char *coinaddr); +cJSON *LP_listunspent(char *symbol,char *coinaddr,bits256 reftxid,bits256 reftxid2); int32_t LP_gettx_presence(char *symbol,bits256 expectedtxid); double LP_getestimatedrate(struct iguana_info *coin); struct LP_utxoinfo *_LP_utxofind(int32_t iambob,bits256 txid,int32_t vout); struct LP_utxoinfo *_LP_utxo2find(int32_t iambob,bits256 txid,int32_t vout); +int64_t LP_dynamictrust(int64_t credits,bits256 pubkey,int64_t kmdvalue); +struct LP_address *LP_addressfind(struct iguana_info *coin,char *coinaddr); +int64_t LP_outpoint_amount(char *symbol,bits256 txid,int32_t vout); void LP_listunspent_query(char *symbol,char *coinaddr); int32_t bitcoin_priv2wif(uint8_t wiftaddr,char *wifstr,bits256 privkey,uint8_t addrtype); diff --git a/iguana/exchanges/LP_instantdex.c b/iguana/exchanges/LP_instantdex.c new file mode 100644 index 000000000..4d8002491 --- /dev/null +++ b/iguana/exchanges/LP_instantdex.c @@ -0,0 +1,650 @@ + +/****************************************************************************** + * Copyright © 2014-2017 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +// +// LP_instantdex.c +// marketmaker +// + +void LP_instantdex_txidaddfname(char *fname,char *afname,char *coinaddr) +{ + if ( coinaddr == 0 || coinaddr[0] == 0 ) + { + sprintf(fname,"%s/instantdex.json",GLOBAL_DBDIR); + sprintf(afname,"%s/instantdex_append.json",GLOBAL_DBDIR); + } + else + { + sprintf(fname,"%s/instantdex_%s.json",GLOBAL_DBDIR,coinaddr); + sprintf(afname,"%s/instantdex_%s_append.json",GLOBAL_DBDIR,coinaddr); + } +} + +cJSON *LP_instantdex_txids(int32_t appendonly,char *coinaddr) +{ + char *filestr,fname[1024],afname[1024]; long fsize; cJSON *retjson=0; + LP_instantdex_txidaddfname(fname,afname,coinaddr); + if ( (filestr= OS_filestr(&fsize,appendonly != 0 ? afname : fname)) != 0 ) + { + retjson = cJSON_Parse(filestr); + free(filestr); + } else printf("couldnt open (%s) or (%s)\n",fname,afname); + return(retjson); +} + +void LP_instantdex_filewrite(int32_t appendfile,cJSON *array,char *coinaddr) +{ + FILE *fp; char *filestr,fname[1024],afname[1024]; + LP_instantdex_txidaddfname(fname,afname,coinaddr); + if ( (fp= fopen(appendfile == 0 ? fname : afname,"wb")) != 0 ) + { + filestr = jprint(array,0); + fwrite(filestr,1,strlen(filestr)+1,fp); + fclose(fp); + free(filestr); + } +} + +void LP_instantdex_deposituniq(FILE *fp,bits256 txid) +{ + int32_t i,n; bits256 prevtxid; char str[65]; + n = (int32_t)(ftell(fp) / sizeof(txid)); + for (i=0; i 0 ) + { + for (i=0; i 0 ) + { + LP_instantdex_deposituniq(fp,prevtxid); + fflush(fp); + } + } + } + free_json(array); + } + } + } + } else fseek(fp,0,SEEK_END); + if ( fp != 0 && bits256_nonz(txid) != 0 ) + { + LP_instantdex_deposituniq(fp,txid); + fclose(fp); + } + LP_instantdex_filescreate(coinaddr); +} + +int32_t LP_deposit_addr(char *p2shaddr,uint8_t *script,uint8_t taddr,uint8_t p2shtype,uint32_t timestamp,uint8_t *pubsecp33) +{ + uint8_t elsepub33[33],p2sh_rmd160[20]; int32_t n; + decode_hex(elsepub33,33,BOTS_BONDPUBKEY33); + n = bitcoin_performancebond(p2sh_rmd160,script,0,timestamp,pubsecp33,elsepub33); + bitcoin_address(p2shaddr,taddr,p2shtype,script,n); + return(n); +} + +char *LP_instantdex_deposit(struct iguana_info *coin,int32_t weeks,double amount,int32_t broadcast) +{ + char p2shaddr[64],*retstr,*hexstr; uint8_t script[512]; int32_t weeki,scriptlen; cJSON *argjson,*retjson,*array,*item,*obj; uint32_t timestamp; bits256 txid,sendtxid; uint64_t amount64; + if ( strcmp(coin->symbol,"KMD") != 0 ) + return(clonestr("{\"error\":\"instantdex deposit must be in KMD\"}")); + if ( amount < 10.0 ) + return(clonestr("{\"error\":\"minimum instantdex deposit is 10 KMD\"}")); + if ( weeks <= 0 || weeks > 52 ) + return(clonestr("{\"error\":\"weeks must be between 1 and 52\"}")); + if ( weeks > 0 ) + { + timestamp = (uint32_t)time(NULL); + timestamp /= LP_WEEKMULT; + timestamp += weeks+2; + timestamp *= LP_WEEKMULT; + weeki = (timestamp - LP_FIRSTWEEKTIME) / LP_WEEKMULT; + if ( weeks >= 10000 ) + return(clonestr("{\"error\":\"numweeks must be less than 10000\"}")); + } else timestamp = (uint32_t)time(NULL) + 300, weeki = 0; + scriptlen = LP_deposit_addr(p2shaddr,script,coin->taddr,coin->p2shtype,timestamp,G.LP_pubsecp); + argjson = cJSON_CreateObject(); + array = cJSON_CreateArray(); + item = cJSON_CreateObject(); + jaddnum(item,p2shaddr,amount); + jaddi(array,item); + item = cJSON_CreateObject(); + amount64 = (amount * SATOSHIDEN) / 1000; + amount64 = (amount64 / 10000) * 10000 + weeki; + jaddnum(item,BOTS_BONDADDRESS,dstr(amount64)); + jaddi(array,item); + item = cJSON_CreateObject(); + jaddnum(item,coin->smartaddr,0.0001); + jaddi(array,item); + jadd(argjson,"outputs",array); + //printf("deposit.(%s)\n",jprint(argjson,0)); + if ( (retstr= LP_withdraw(coin,argjson)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( jobj(retjson,"result") != 0 ) + jdelete(retjson,"result"); + jaddstr(retjson,"address",p2shaddr); + jaddnum(retjson,"expiration",timestamp); + jaddnum(retjson,"deposit",amount); + if ( (obj= jobj(retjson,"complete")) != 0 && is_cJSON_True(obj) != 0 && (hexstr= jstr(retjson,"hex")) != 0 ) + { + txid = jbits256(retjson,"txid"); + if ( broadcast != 0 ) + { + if (bits256_nonz(txid) != 0 ) + { + sendtxid = LP_broadcast("deposit","KMD",hexstr,txid); + if ( bits256_cmp(sendtxid,txid) != 0 ) + { + jaddstr(retjson,"error","broadcast txid mismatch"); + jaddbits256(retjson,"broadcast",sendtxid); + free(retstr); + return(jprint(retjson,1)); + } + else + { + jaddstr(retjson,"result","success"); + jaddbits256(retjson,"broadcast",sendtxid); + LP_instantdex_depositadd(coin->smartaddr,txid); + free(retstr); + return(jprint(retjson,1)); + } + } + else + { + jaddstr(retjson,"error","couldnt broadcast since no txid created"); + free(retstr); + return(jprint(retjson,1)); + } + } + else + { + jaddstr(retjson,"result","success"); + free(retstr); + return(jprint(retjson,1)); + } + } + else + { + jaddstr(retjson,"error","couldnt create deposit txid"); + free(retstr); + return(jprint(retjson,1)); + } + free_json(retjson); + } + free(retstr); + } + return(clonestr("{\"error\":\"error with LP_withdraw for instantdex deposit\"}")); +} + +int64_t LP_claimtx(void *ctx,struct iguana_info *coin,bits256 *claimtxidp,bits256 utxotxid,int32_t utxovout,uint64_t satoshis,char *vinaddr,uint32_t claimtime,uint8_t *redeemscript,int32_t redeemlen) +{ + uint8_t userdata[2]; char *signedtx; bits256 signedtxid,sendtxid; int32_t isbots,userdatalen; int64_t destamount,sum = 0; + if ( strcmp(coin->smartaddr,BOTS_BONDADDRESS) == 0 ) + isbots = 1; + else isbots = 0; + userdata[0] = (isbots == 0) ? 0x51 : 0; + userdatalen = 1; + utxovout = 0; + memset(claimtxidp,0,sizeof(*claimtxidp)); + char str[65]; printf("LP_claimtx satoshis %.8f %s/v%d\n",dstr(satoshis),bits256_str(str,utxotxid),utxovout); + if ( (signedtx= basilisk_swap_bobtxspend(&signedtxid,10000,"instantdexclaim",coin->symbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,ctx,G.LP_privkey,0,redeemscript,redeemlen,userdata,userdatalen,utxotxid,utxovout,coin->smartaddr,G.LP_pubsecp,0,claimtime,&destamount,0,0,vinaddr,1,coin->zcash)) != 0 ) + { + printf("signedtx.(%s)\n",signedtx); + sendtxid = LP_broadcast("claim","KMD",signedtx,signedtxid); + if ( bits256_cmp(sendtxid,signedtxid) == 0 ) + { + *claimtxidp = sendtxid; + sum += (satoshis - coin->txfee); + } + else printf("error sending %s\n",bits256_str(str,signedtxid)); + free(signedtx); + } else printf("error claiming instantdex deposit %s/v%d %.8f\n",bits256_str(str,utxotxid),utxovout,dstr(satoshis)); + return(sum); +} + +int32_t LP_claim_submit(void *ctx,cJSON *txids,int64_t *sump,struct iguana_info *coin,bits256 utxotxid) +{ + uint8_t redeemscript[512]; bits256 claimtxid; cJSON *txjson,*vout0,*vout1,*vout2,*vouts,*item; int32_t numvouts; char str[65],vinaddr[64],destaddr[64],checkaddr[64]; int32_t j,utxovout,flagi = 0,redeemlen,weeki,iter; int64_t weeksatoshis,satoshis; uint32_t expiration,claimtime; + if ( (txjson= LP_gettx(coin->symbol,utxotxid,1)) != 0 ) + { + if ( (vouts= jarray(&numvouts,txjson,"vout")) != 0 && numvouts >= 3 ) + { + vout0 = jitem(vouts,0); + LP_destaddr(vinaddr,vout0); + satoshis = LP_value_extract(vout0,1); + vout2 = jitem(vouts,2); + LP_destaddr(destaddr,vout2); + if ( strcmp(destaddr,coin->smartaddr) == 0 ) + { + vout1 = jitem(vouts,1); + weeksatoshis = LP_value_extract(vout1,0); + weeki = (int32_t)(weeksatoshis % 10000); + for (iter=0; iter<2; iter++) + for (j=-168; j<=168; j++) + { + if ( iter == 1 ) + expiration = ((weeki * LP_WEEKMULTBAD + j*3600) + LP_FIRSTWEEKTIME); + else expiration = ((weeki * LP_WEEKMULT + j*3600) + LP_FIRSTWEEKTIME); + redeemlen = LP_deposit_addr(checkaddr,redeemscript,coin->taddr,coin->p2shtype,expiration,G.LP_pubsecp); + if ( strcmp(checkaddr,vinaddr) == 0 ) + { + flagi = 1; + claimtime = (uint32_t)time(NULL)-777; + item = cJSON_CreateObject(); + jaddbits256(item,"txid",utxotxid); + jaddnum(item,"deposit",dstr(LP_value_extract(vout0,0))); + if ( coin->electrum == 0 ) + jaddnum(item,"interest",dstr(satoshis)-dstr(LP_value_extract(vout0,0))); + else jaddnum(item,"interest",dstr(LP_komodo_interest(utxotxid,satoshis))); + if ( claimtime <= expiration ) + { + printf("iter.%d j.%d claimtime.%u vs %u, wait %d seconds to %s claim %.8f\n",iter,j,claimtime,expiration,(int32_t)expiration-claimtime,bits256_str(str,utxotxid),dstr(satoshis)); + jaddnum(item,"waittime",(int32_t)expiration-claimtime); + jaddi(txids,item); + break; + } + else + { + utxovout = 0; + *sump += LP_claimtx(ctx,coin,&claimtxid,utxotxid,utxovout,satoshis,vinaddr,claimtime,redeemscript,redeemlen); + if ( bits256_nonz(claimtxid) != 0 ) + { + jaddbits256(item,"claimtxid",claimtxid); + jaddi(txids,item); + } + } + } //else printf("expiration.%u j.%d checkaddr.(%s) != vinaddr.%s\n",expiration,j,checkaddr,vinaddr); + if ( flagi != 0 ) + break; + } + } else printf("vout2 dest.(%s) != %s\n",destaddr,coin->smartaddr); + } else printf("numvouts %d != 3\n",numvouts); + free_json(txjson); + } else printf("cant get transaction flagi.%d\n",flagi); + return(flagi); +} + +char *LP_instantdex_claim(struct iguana_info *coin) +{ + static void *ctx; static int32_t firsttime = 1; + int32_t i,n; cJSON *array,*txids,*newarray,*retjson; int64_t sum; bits256 utxotxid; + if ( ctx == 0 ) + ctx = bitcoin_ctx(); + if ( strcmp(coin->symbol,"KMD") != 0 ) + return(clonestr("{\"error\":\"instantdex deposit must be in KMD\"}")); + sum = 0; + txids = cJSON_CreateArray(); + newarray = cJSON_CreateArray(); + if ( (array= LP_instantdex_txids(firsttime,coin->smartaddr)) != 0 ) + { + printf("claiming from.(%s)\n",jprint(array,0)); + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; i 0 ) + LP_instantdex_filewrite(0,newarray,coin->smartaddr); + free_json(newarray); + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jaddnum(retjson,"claimed",dstr(sum)); + jadd(retjson,"txids",txids); + return(jprint(retjson,1)); +} + +int64_t LP_instantdex_credit(int32_t dispflag,char *coinaddr,int64_t satoshis,int32_t weeki,char *p2shaddr,bits256 txid) +{ + uint32_t timestamp; struct LP_address *ap; struct iguana_info *coin = LP_coinfind("KMD"); + if ( coin != 0 ) + { + timestamp = LP_FIRSTWEEKTIME + weeki*LP_WEEKMULT; + if ( (ap= LP_address(coin,coinaddr)) != 0 && time(NULL) < timestamp-60*3600 ) + { + ap->instantdex_credits += satoshis; + ap->didinstantdex = 1; + if ( 0 && dispflag != 0 ) + printf("InstantDEX credit.(%s) %.8f weeki.%d (%s) -> sum %.8f\n",coinaddr,dstr(satoshis),weeki,p2shaddr,dstr(ap->instantdex_credits)); + return(satoshis); + } else printf("null ap.%p or expired %ld\n",ap,time(NULL) - (timestamp-60*3600)); + } + return(0); +} + +int64_t LP_instantdex_creditcalc(struct iguana_info *coin,int32_t dispflag,bits256 txid,char *refaddr) +{ + cJSON *txjson,*vouts,*txobj,*item; int64_t satoshis=0,amount64; int32_t weeki,numvouts; char destaddr[64],p2shaddr[64]; + if ( (txjson= LP_gettx(coin->symbol,txid,0)) != 0 ) + { + // vout0 deposit, vout1 botsfee, vout2 smartaddress + if ( (vouts= jarray(&numvouts,txjson,"vout")) > 0 && numvouts >= 3 && LP_destaddr(destaddr,jitem(vouts,2)) == 0 ) + { + if ( refaddr != 0 && strcmp(refaddr,destaddr) != 0 ) + { + printf("LP_instantdex_creditcalc for (%s) but deposit sent for (%s)\n",refaddr,destaddr); + } + else + { + amount64 = LP_value_extract(jitem(vouts,1),0); + weeki = (amount64 % 10000); + item = jitem(vouts,0); + satoshis = LP_value_extract(item,0); + //char str[65]; printf("%s %s funded %.8f weeki.%d (%s)\n",bits256_str(str,txid),destaddr,dstr(satoshis),weeki,jprint(item,0)); + if ( LP_destaddr(p2shaddr,item) == 0 ) + { + if ( (txobj= LP_gettxout(coin->symbol,p2shaddr,txid,0)) != 0 ) + { + free_json(txobj); + LP_instantdex_credit(dispflag,destaddr,satoshis,weeki,p2shaddr,txid); + } else printf("already spent\n"); + } else printf("error getting p2shaddr.(%s)\n",p2shaddr); + } + } + free_json(txjson); + } + return(satoshis); +} + +#ifdef bruteforce +void LP_instantdex_deposits(struct iguana_info *coin) +{ + static int dispflag = 1; + cJSON *array,*item; int32_t i,n,height,vout; bits256 txid; struct LP_address *ap,*tmp; + if ( coin->electrum != 0 )//&& coin->electruminstantdex != 0 ) + return; + HASH_ITER(hh,coin->addresses,ap,tmp) + { + ap->instantdex_credits = 0; + } + if ( (array= LP_listreceivedbyaddress("KMD",BOTS_BONDADDRESS)) != 0 ) + { + //printf("instantdex.(%s)\n",jprint(array,0)); + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; ielectrum != 0 ) + { + item = jitem(array,i); + LP_listunspent_parseitem(coin,&txid,&vout,&height,item); + } else txid = jbits256i(array,i); + LP_instantdex_creditcalc(coin,dispflag,txid,0); + } + } + free_json(array); + } + dispflag = 0; +} +#endif + +int64_t LP_dynamictrust(int64_t credits,bits256 pubkey,int64_t kmdvalue) +{ + struct LP_pubswap *ptr,*tmp; struct LP_swapstats *sp; struct LP_pubkey_info *pubp; struct LP_address *ap; char coinaddr[64]; struct iguana_info *coin; int64_t swaps_kmdvalue = 0; + if ( (coin= LP_coinfind("KMD")) != 0 && (pubp= LP_pubkeyfind(pubkey)) != 0 ) + { + bitcoin_address(coinaddr,coin->taddr,coin->pubtype,pubp->pubsecp,33); + DL_FOREACH_SAFE(pubp->bobswaps,ptr,tmp) + { + if ( (sp= ptr->swap) != 0 && LP_swap_finished(sp,1) == 0 ) + swaps_kmdvalue += LP_kmdvalue(sp->Q.srccoin,sp->Q.satoshis); + } + DL_FOREACH_SAFE(pubp->aliceswaps,ptr,tmp) + { + if ( (sp= ptr->swap) != 0 && LP_swap_finished(sp,1) == 0 ) + swaps_kmdvalue += LP_kmdvalue(sp->Q.destcoin,sp->Q.destsatoshis); + } + if ( credits == 0 && (ap= LP_address(coin,coinaddr)) != 0 ) + credits = ap->instantdex_credits; + if ( credits != 0 && (swaps_kmdvalue+kmdvalue) > credits ) + { + if ( 0 ) + { + DL_FOREACH_SAFE(pubp->bobswaps,ptr,tmp) + { + if ( (sp= ptr->swap) != 0 && LP_swap_finished(sp,1) == 0 ) + printf("unfinished bob %llu r%u-r%u src.%s %.8f dest.%s %.8f -> price %.8f value %.8f\n",(long long)sp->aliceid,sp->Q.R.requestid,sp->Q.R.quoteid,sp->Q.srccoin,dstr(sp->Q.satoshis),sp->Q.destcoin,dstr(sp->Q.destsatoshis),(double)sp->Q.destsatoshis/(sp->Q.satoshis+1),dstr(LP_kmdvalue(sp->Q.destcoin,sp->Q.destsatoshis))); + } + DL_FOREACH_SAFE(pubp->aliceswaps,ptr,tmp) + { + if ( (sp= ptr->swap) != 0 && LP_swap_finished(sp,1) == 0 ) + printf("unfinished alice %llu r%u-r%u src.%s %.8f dest.%s %.8f -> price %.8f value %.8f\n",(long long)sp->aliceid,sp->Q.R.requestid,sp->Q.R.quoteid,sp->Q.srccoin,dstr(sp->Q.satoshis),sp->Q.destcoin,dstr(sp->Q.destsatoshis),(double)sp->Q.destsatoshis/(sp->Q.satoshis+1),dstr(LP_kmdvalue(sp->Q.destcoin,sp->Q.destsatoshis))); + } + } + printf("REJECT: %s instantdex_credits %.8f vs (%.8f + current %.8f)\n",coinaddr,dstr(credits),dstr(swaps_kmdvalue),dstr(kmdvalue)); + } + if ( 0 && credits != 0 ) + printf("%s %s othercredits %.8f debits %.8f + %.8f -> %.8f\n",coin->symbol,coinaddr,dstr(credits),dstr(swaps_kmdvalue),dstr(kmdvalue),dstr(credits - (swaps_kmdvalue+kmdvalue))); + return(credits - (swaps_kmdvalue+kmdvalue)); + } + return(0); +} + +int64_t LP_instantdex_proofcheck(char *coinaddr,cJSON *proof,int32_t num) +{ + uint8_t rmd160[20],addrtype; int64_t credits=0; int32_t i,j; bits256 prevtxid,txid; char othersmartaddr[64]; struct iguana_info *coin; struct LP_address *ap = 0; + if ( (coin= LP_coinfind("KMD")) != 0 ) + { + bitcoin_addr2rmd160(0,&addrtype,rmd160,coinaddr); + bitcoin_address(othersmartaddr,0,60,rmd160,20); + printf("proofcheck addrtype.%d (%s) -> %s\n",addrtype,coinaddr,othersmartaddr); + if ((ap= LP_address(coin,othersmartaddr)) != 0 ) + { + ap->instantdex_credits = 0; + for (i=0; iinstantdex_credits; + ap->didinstantdex = 1; + if ( ap->instantdex_credits > 0 ) + printf("validated instantdex %s.[%d] proof.(%s) credits %.8f\n",othersmartaddr,num,jprint(proof,0),dstr(ap->instantdex_credits)); + } //else printf("cant find ap.%p or already did %d %.8f\n",ap,ap!=0?ap->didinstantdex:-1,ap!=0?dstr(ap->instantdex_credits):-1); + } + return(credits); +} + +int64_t LP_myzcredits() +{ + cJSON *proof; struct iguana_info *coin; int64_t zcredits; + if ( (coin= LP_coinfind("KMD")) != 0 ) + { + if ( (proof= LP_instantdex_txids(0,coin->smartaddr)) != 0 ) + { + zcredits = LP_instantdex_proofcheck(coin->smartaddr,proof,cJSON_GetArraySize(proof)); + free_json(proof); + return(zcredits); + } + } + return(0); +} + +cJSON *LP_swapstats_item(struct LP_swapstats *sp,int32_t iambob) +{ + struct iguana_info *bob,*alice; int32_t flag = 0; char *retstr,*swapstr; bits256 zero; cJSON *item,*reqjson,*swapjson; + item = cJSON_CreateObject(); + jaddnum(item,"iambob",iambob); + jaddnum(item,"aliceid",sp->aliceid); + jaddnum(item,"requestid",sp->Q.R.requestid); + jaddnum(item,"quoteid",sp->Q.R.quoteid); + jaddstr(item,"base",sp->Q.srccoin); + jaddnum(item,"satoshis",sp->Q.satoshis); + jaddstr(item,"rel",sp->Q.destcoin); + jaddnum(item,"destsatoshis",sp->Q.destsatoshis); + jaddnum(item,"price",sp->Q.destsatoshis/((double)sp->Q.satoshis+1)); + if ( LP_swap_finished(sp,1) == 0 ) + { + jaddnum(item,"finished",sp->finished); + if ( sp->bobneeds_dPoW != 0 && (bob= LP_coinfind(sp->Q.srccoin)) != 0 ) + { + jaddnum(item,"bobneeds_dPoW",sp->bobneeds_dPoW); + jaddnum(item,"bob_dPoWheight",bob->notarized); + if ( sp->bobneeds_dPoW == 1 ) + flag = 1; + if ( bob->notarized == 0 ) + LP_dPoW_request(bob); + } + if ( sp->aliceneeds_dPoW != 0 && (alice= LP_coinfind(sp->Q.destcoin)) != 0 ) + { + jaddnum(item,"aliceneeds_dPoW",sp->aliceneeds_dPoW); + jaddnum(item,"alice_dPoWheight",alice->notarized); + if ( sp->aliceneeds_dPoW == 1 ) + flag = 1; + if ( alice->notarized == 0 ) + LP_dPoW_request(alice); + } + if ( flag != 0 ) + { + reqjson = cJSON_CreateObject(); + jaddstr(reqjson,"method","gettradestatus"); + jadd64bits(reqjson,"aliceid",sp->aliceid); + memset(zero.bytes,0,sizeof(zero)); + LP_reserved_msg(0,"","",zero,jprint(reqjson,1)); + if ( (swapstr= basilisk_swapentry(sp->Q.R.requestid,sp->Q.R.quoteid,0)) != 0 ) + { + if ( (swapjson= cJSON_Parse(swapstr)) != 0 ) + { + if ( (retstr= LP_swapstatus_recv(swapjson)) != 0 ) + free(retstr); + free_json(swapjson); + } + free(swapstr); + } + } + } + return(item); +} + +cJSON *LP_myzdebits() +{ + struct LP_pubswap *ptr,*tmp; struct LP_pubkey_info *pubp; struct LP_swapstats *sp; int64_t kmdvalue,swaps_kmdvalue = 0; struct iguana_info *coin; cJSON *retjson,*array,*item; + array = cJSON_CreateArray(); + if ( (coin= LP_coinfind("KMD")) != 0 ) + { + if ( (pubp= LP_pubkeyfind(G.LP_mypub25519)) != 0 ) + { + DL_FOREACH_SAFE(pubp->bobswaps,ptr,tmp) + { + if ( (sp= ptr->swap) != 0 && LP_swap_finished(sp,1) == 0 ) + { + kmdvalue = LP_kmdvalue(sp->Q.srccoin,sp->Q.satoshis); + item = LP_swapstats_item(sp,1); + jaddnum(item,"kmdvalue",dstr(kmdvalue)); + jaddi(array,item); + swaps_kmdvalue += kmdvalue; + } + } + DL_FOREACH_SAFE(pubp->aliceswaps,ptr,tmp) + { + if ( (sp= ptr->swap) != 0 && LP_swap_finished(sp,1) == 0 ) + { + kmdvalue = LP_kmdvalue(sp->Q.destcoin,sp->Q.destsatoshis); + item = LP_swapstats_item(sp,0); + jaddnum(item,"kmdvalue",dstr(kmdvalue)); + jaddi(array,item); + swaps_kmdvalue += kmdvalue; + } + } + } + } + retjson = cJSON_CreateObject(); + jadd(retjson,"swaps",array); + jaddnum(retjson,"pendingswaps",dstr(swaps_kmdvalue)); + return(retjson); +} diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index 395866af8..4fc1bacd4 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -13,57 +13,138 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - // // LP_nativeDEX.c // marketmaker // -// verify portfolio, interest to KMD withdraw, pricebroadcast loop +// ordermatch pricing error +// https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki for signing BCH/BTG +// compress packets +// portfolio to set prices from historical +// portfolio value based on ask? +// else claim path +// +// WONTFIX: // dPoW security -> 4: KMD notarized, 5: BTC notarized, after next notary elections // bigendian architectures need to use little endian for sighash calcs +// improve critical section detection when parallel trades +// use electrum in case of addr change in swap +// locktime claiming on sporadic assetchains +// there is an issue about waiting for notarization for a swap that never starts (expiration ok) #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_swapsloop_stats,LP_gcloop_stats,LP_tradesloop_stats; +extern int32_t IAMLP; +char LP_methodstr[64]; + +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_tradesloop_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 %s\n",mp->name,elapsed,mp->threshold,mp->millisum/mp->count,mp->count,LP_methodstr); + } + 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,LP_electrummutex,LP_butxomutex,LP_reservedmutex,LP_nanorecvsmutex; +portable_mutex_t LP_peermutex,LP_UTXOmutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex,LP_forwardmutex,LP_pubkeymutex,LP_networkmutex,LP_psockmutex,LP_coinmutex,LP_messagemutex,LP_portfoliomutex,LP_electrummutex,LP_butxomutex,LP_reservedmutex,LP_nanorecvsmutex,LP_tradebotsmutex,LP_gcmutex,LP_inusemutex,LP_cJSONmutex,LP_logmutex,LP_statslogmutex,LP_tradesmutex; int32_t LP_canbind; -char *Broadcaststr,*Reserved_msgs[1000]; -int32_t num_Reserved_msgs,max_Reserved_msgs; +char *Broadcaststr,*Reserved_msgs[2][1000]; +int32_t num_Reserved_msgs[2],max_Reserved_msgs[2]; struct LP_peerinfo *LP_peerinfos,*LP_mypeer; struct LP_forwardinfo *LP_forwardinfos; struct iguana_info *LP_coins; -struct LP_pubkeyinfo *LP_pubkeyinfos; -#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", };//"5.9.253.204" }; // +struct LP_pubkey_info *LP_pubkeyinfos; +struct rpcrequest_info *LP_garbage_collector; +struct LP_address_utxo *LP_garbage_collector2; +struct LP_trade *LP_trades,*LP_tradesQ; //uint32_t LP_deadman_switch; uint16_t LP_fixed_pairport,LP_publicport; -uint32_t LP_lastnonce,LP_counter; +uint32_t LP_lastnonce,LP_swap_endcritical,LP_swap_critical,LP_RTcount,LP_swapscount; int32_t LP_mybussock = -1; int32_t LP_mypubsock = -1; int32_t LP_mypullsock = -1; -int32_t LP_showwif,IAMLP = 0; +int32_t LP_numfinished,LP_showwif,IAMLP = 0; double LP_profitratio = 1.; struct LP_privkey { bits256 privkey; uint8_t rmd160[20]; }; struct LP_globals { - struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2]; + //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_pendingswaps,USERPASS_COUNTER,LP_numprivkeys,initializing,waiting,LP_numskips; - char USERPASS[65],USERPASS_WIFSTR[64],LP_myrmd160str[41],gui[16]; + 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],LP_NXTaddr[64]; 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 void tradebot_swap_balancingtrade(struct basilisk_swap *swap,int32_t iambob) @@ -91,6 +172,8 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_ #include "LP_bitcoin.c" #include "LP_coins.c" #include "LP_rpc.c" +#include "LP_NXT.c" +#include "LP_cache.c" #include "LP_RTmetrics.c" #include "LP_utxo.c" #include "LP_prices.c" @@ -98,22 +181,23 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_ #include "LP_transaction.c" #include "LP_stats.c" #include "LP_remember.c" +#include "LP_instantdex.c" #include "LP_swap.c" #include "LP_peers.c" -#include "LP_utxos.c" +#include "LP_privkey.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" char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen) { - char *retstr=0; + char *retstr=0; cJSON *retjson; bits256 zero; if ( jobj(argjson,"result") != 0 || jobj(argjson,"error") != 0 ) return(0); - //double millis = OS_milliseconds(); if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,data,datalen) <= 0 ) { if ( (retstr= stats_JSON(ctx,myipaddr,pubsock,argjson,"127.0.0.1",0)) != 0 ) @@ -122,9 +206,13 @@ char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson //if ( pubsock >= 0 ) //strncmp("{\"error\":",retstr,strlen("{\"error\":")) != 0 && //LP_send(pubsock,retstr,(int32_t)strlen(retstr)+1,0); } - } //else printf("finished tradecommand (%s)\n",jprint(argjson,0)); - //if ( OS_milliseconds()-millis > 100 ) - // printf("%.3f %s\n",OS_milliseconds()-millis,jprint(argjson,0)); + } + else if ( LP_statslog_parse() > 0 ) + { + memset(zero.bytes,0,sizeof(zero)); + if ( (retjson= LP_statslog_disp(2000000000,2000000000,"",zero,0,0))) // pending swaps + free_json(retjson); + } return(retstr); } @@ -144,7 +232,7 @@ char *LP_decrypt(uint8_t *ptr,int32_t *recvlenp) { 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; @@ -163,7 +251,8 @@ char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock, if ( duplicate != 0 ) dup++; else uniq++; - if ( (rand() % 10000) == 0 ) + 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 ) { @@ -233,9 +322,9 @@ char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock, else { memset(zero.bytes,0,sizeof(zero)); - if ( (method= jstr(reqjson,"method")) != 0 && (strcmp(method,"request") == 0 || strcmp(method,"requested") == 0 || strcmp(method,"connect") == 0 || strcmp(method,"connected") == 0) ) + if ( 0 && (method= jstr(reqjson,"method")) != 0 && (strcmp(method,"tradestatus") == 0) ) printf("broadcast.(%s)\n",Broadcaststr); - LP_reserved_msg("","",zero,jprint(reqjson,0)); + LP_reserved_msg(0,"","",zero,jprint(reqjson,0)); } retstr = clonestr("{\"result\":\"success\"}"); free_json(reqjson); @@ -243,21 +332,18 @@ char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock, } else { - portable_mutex_lock(&LP_commandmutex); if ( (retstr= LP_command_process(ctx,myipaddr,pubsock,argjson,&((uint8_t *)ptr)[len],recvlen - len)) != 0 ) { } - portable_mutex_unlock(&LP_commandmutex); - //printf("%.3f %s LP_command_process\n",OS_milliseconds()-millis,jstr(argjson,"method")); } - 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); } @@ -269,21 +355,21 @@ int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int while ( nonz < maxdepth && recvlen > 0 ) { nonz++; -#ifndef FROM_JS memset(&pfd,0,sizeof(pfd)); pfd.fd = sock; pfd.events = NN_POLLIN; if ( nn_poll(&pfd,1,1) != 1 ) break; -#endif + ptr = 0; + //buf = malloc(1000000); + //if ( (recvlen= nn_recv(sock,buf,1000000,0)) > 0 ) if ( (recvlen= nn_recv(sock,&ptr,NN_MSG,0)) > 0 ) { + //ptr = buf; methodstr[0] = 0; + //printf("%s.(%s)\n",typestr,(char *)ptr); if ( 1 ) { -#ifdef FROM_JS - printf("%s RECV.(%s)\n",typestr,(char *)ptr); -#endif cJSON *recvjson; char *mstr;//,*cstr; if ( (recvjson= cJSON_Parse((char *)ptr)) != 0 ) { @@ -291,46 +377,47 @@ int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int { //printf("%s RECV.(%s)\n",typestr,(char *)ptr); } - safecopy(methodstr,jstr(recvjson,"method"),sizeof(methodstr)); + safecopy(LP_methodstr,jstr(recvjson,"method"),sizeof(LP_methodstr)); free_json(recvjson); } } -#ifdef FROM_JS - else printf("%s got recv.%d\n",typestr,recvlen); -#endif - double millis = OS_milliseconds(); + 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 ( (retstr= LP_process_message(ctx,typestr,myipaddr,pubsock,ptr,recvlen,sock)) != 0 ) - free(retstr); - if ( Broadcaststr != 0 ) + if ( validreq != 0 ) { - //printf("self broadcast.(%s)\n",Broadcaststr); - str = Broadcaststr; - Broadcaststr = 0; - if ( (argjson= cJSON_Parse(str)) != 0 ) + if ( (retstr= LP_process_message(ctx,typestr,myipaddr,pubsock,ptr,recvlen,sock)) != 0 ) + free(retstr); + if ( Broadcaststr != 0 ) { - if ( jobj(argjson,"method") != 0 && strcmp("connect",jstr(argjson,"method")) == 0 ) - printf("self.(%s)\n",str); - if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,0,0) <= 0 ) + //printf("self broadcast.(%s)\n",Broadcaststr); + str = Broadcaststr; + Broadcaststr = 0; + if ( (argjson= cJSON_Parse(str)) != 0 ) { portable_mutex_lock(&LP_commandmutex); - if ( (retstr= stats_JSON(ctx,myipaddr,pubsock,argjson,remoteaddr,0)) != 0 ) - free(retstr); + 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_json(argjson); + free(str); } - free(str); } - if ( OS_milliseconds()-millis > 1000 ) - printf("%.3f LP_process_message (%s)\n",OS_milliseconds()-millis,methodstr); + } + if ( ptr != 0 ) + { + nn_freemsg(ptr), ptr = 0; + //free(buf); } } } @@ -347,7 +434,7 @@ int32_t LP_nanomsg_recvs(void *ctx) { if ( peer->errors >= LP_MAXPEER_ERRORS ) { - if ( (rand() % 10000) == 0 ) + if ( (LP_rand() % 10000) == 0 ) peer->errors--; else { @@ -373,123 +460,53 @@ int32_t LP_nanomsg_recvs(void *ctx) return(nonz); } -void command_rpcloop(void *myipaddr) +void command_rpcloop(void *ctx) { - int32_t nonz = 0; void *ctx; - ctx = bitcoin_ctx(); + int32_t nonz = 0; + 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 ) { if ( IAMLP != 0 ) - usleep(1000); - else usleep(10000); + usleep(10000); + else usleep(50000); } else if ( IAMLP == 0 ) - usleep(100); + usleep(1000); } } -void utxosQ_loop(void *myipaddr) +void LP_coinsloop(void *_coins) { - while ( 1 ) + 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 notarized,oldht,j,nonz; char *coins = _coins; + if ( strcmp("BTC",coins) == 0 ) { - if ( LP_utxosQ_process() == 0 ) - usleep(10000); + strcpy(LP_coinsloopBTC_stats.name,"BTC coin loop"); + LP_coinsloopBTC_stats.threshold = 20000.; } -} - -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) + else if ( strcmp("KMD",coins) == 0 ) { - 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)); - if ( (retstr2= issue_LP_uitem(peer->ipaddr,peer->port,coin->symbol,coin->smartaddr,txid,v,jint(item,"height"),j64bits(item,"value"))) != 0 ) - free(retstr2); - posted++; - } - } - 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"))) != 0 ) - free(retstr2); - } - } - free_json(array); - } + 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.; } - return(posted); -} - -void LP_coinsloop(void *_coins) -{ - struct LP_address *ap=0,*atmp; 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; 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 { @@ -506,14 +523,32 @@ void LP_coinsloop(void *_coins) continue; } } + if ( coin->smartaddr[0] == 0 ) + printf("%s has no smartaddress??\n",coin->symbol); memset(&zero,0,sizeof(zero)); if ( coin->inactive != 0 ) continue; + if ( coin->longestchain == 1 ) // special init value + coin->longestchain = LP_getheight(¬arized,coin); if ( (ep= coin->electrum) != 0 ) { + /*if ( strcmp("KMD",coin->symbol) == 0 && coin->electrumzeroconf == 0 ) + { + LP_zeroconf_deposits(coin); + coin->electrumzeroconf = (uint32_t)time(NULL); + }*/ if ( (backupep= ep->prev) == 0 ) backupep = ep; + if ( (retjson= electrum_address_listunspent(coin->symbol,ep,&retjson,coin->smartaddr,1,zero,zero)) != 0 ) + free_json(retjson); HASH_ITER(hh,coin->addresses,ap,atmp) + { + break; + //printf("call unspent %s\n",ap->coinaddr); + if ( strcmp(coin->smartaddr,ap->coinaddr) != 0 && (retjson= electrum_address_listunspent(coin->symbol,ep,&retjson,ap->coinaddr,1,zero,zero)) != 0 ) + free_json(retjson); + } + if ( (ap= LP_addressfind(coin,coin->smartaddr)) != 0 ) { DL_FOREACH_SAFE(ap->utxos,up,tmp) { @@ -522,18 +557,24 @@ void LP_coinsloop(void *_coins) if ( up->SPV == 0 ) { nonz++; - up->SPV = LP_merkleproof(coin,backupep,up->U.txid,up->U.height); - if ( 0 && up->SPV > 0 ) - printf("%s %s: SPV.%d\n",coin->symbol,bits256_str(str,up->U.txid),up->SPV); + 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); + LP_txheight_check(coin,ap->coinaddr,up->U.txid); if ( oldht != up->U.height ) - up->SPV = LP_merkleproof(coin,backupep,up->U.txid,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); @@ -541,6 +582,17 @@ void LP_coinsloop(void *_coins) } } } + 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_banner(coin->symbol,ep,&retjson)) != 0 ) + free_json(retjson); + ep->keepalive = (uint32_t)time(NULL); + } + ep = ep->prev; + } continue; } if ( coin->firstrefht == 0 ) @@ -567,97 +619,76 @@ void LP_coinsloop(void *_coins) coin->lastscanht = coin->firstscanht; continue; } - nonz++; - //if ( (coin->lastscanht % 1000) == 0 ) - 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 ( strcmp(coin->symbol,"BTC") != 0 && strcmp(coin->symbol,"KMD") != 0 ) // SPV as backup { - if ( LP_blockinit(coin,coin->lastscanht) < 0 ) + nonz++; + if ( strcmp("BTC",coins) == 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++) { - printf("blockinit.%s %d error\n",coin->symbol,coin->lastscanht); - break; + 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 || strcmp("BTC",coins) == 0 ) + break; } - coin->lastscanht++; - if ( coin->lastscanht == coin->longestchain+1 ) - break; + if ( strcmp("BTC",coins) == 0 ) + printf("done [%s]: %s ref.%d scan.%d to %d, longest.%d\n",coins,coin->symbol,coin->firstrefht,coin->firstscanht,coin->lastscanht,coin->longestchain); } } if ( coins == 0 ) return; if ( nonz == 0 ) - usleep(1000); + 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,numpeers; - struct iguana_info *coin,*ctmp; char *retstr,*origipaddr; struct LP_peerinfo *peer,*tmp; uint32_t now; int32_t needpings,height,nonz = 0; - now = (uint32_t)time(NULL); + static uint32_t counter;//,didinstantdex; + struct iguana_info *coin,*ctmp; char *origipaddr; uint32_t now; int32_t notarized,height,nonz = 0; if ( (origipaddr= myipaddr) == 0 ) origipaddr = "127.0.0.1"; if ( mypeer == 0 ) myipaddr = "127.0.0.1"; - numpeers = LP_numpeers(); - needpings = 0; - HASH_ITER(hh,LP_peerinfos,peer,tmp) + HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht { - if ( peer->errors >= LP_MAXPEER_ERRORS ) + now = (uint32_t)time(NULL); +#ifdef bruteforce + if ( IAMLP != 0 && coin->inactive == 0 && coin->electrum == 0 && didinstantdex == 0 && strcmp("KMD",coin->symbol) == 0 ) { - if ( (rand() % 10000) == 0 ) - { - peer->errors--; - if ( peer->errors < LP_MAXPEER_ERRORS ) - peer->diduquery = 0; - } - if ( IAMLP == 0 ) - continue; + LP_instantdex_deposits(coin); + didinstantdex = now; } - if ( now > peer->lastpeers+60 || (rand() % 10000) == 0 ) - { - if ( strcmp(peer->ipaddr,myipaddr) != 0 ) - { - nonz++; -#ifndef FROM_JS - LP_peersquery(mypeer,pubsock,peer->ipaddr,peer->port,myipaddr,myport); #endif - peer->diduquery = 0; - LP_peer_pricesquery(peer); - LP_utxos_sync(peer); - needpings++; - } - peer->lastpeers = now; - } - if ( peer->needping != 0 ) - { - peer->diduquery = now; - nonz++; -#ifndef FROM_JS - 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); -#endif - peer->needping = 0; - needpings++; - } - } - HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht - { - if ( coin->addr_listunspent_requested != 0 ) + /*if ( (coin->addr_listunspent_requested != 0 && now > coin->lastpushtime+LP_ORDERBOOK_DURATION*.5) || now > coin->lastpushtime+LP_ORDERBOOK_DURATION*5 ) { //printf("PUSH addr_listunspent_requested %u\n",coin->addr_listunspent_requested); + coin->lastpushtime = (uint32_t)now; LP_smartutxos_push(coin); coin->addr_listunspent_requested = 0; - } - if ( coin->inactive == 0 && time(NULL) > coin->lastgetinfo+LP_GETINFO_INCR ) + }*/ + if ( coin->electrum == 0 && coin->inactive == 0 && now > coin->lastgetinfo+LP_GETINFO_INCR ) { nonz++; - if ( (height= LP_getheight(coin)) > coin->longestchain ) + if ( (height= LP_getheight(¬arized,coin)) > coin->longestchain ) { coin->longestchain = height; - if ( coin->firstrefht != 0 ) + if ( notarized != 0 && notarized > coin->notarized ) + { + coin->notarized = notarized; + if ( IAMLP != 0 ) + LP_dPoW_broadcast(coin); + } + 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)time(NULL); + coin->lastgetinfo = (uint32_t)now; } } counter++; @@ -666,32 +697,62 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins) { - int32_t i,n; cJSON *item; + int32_t i,n,notarized; 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 ( strcmp(coin->symbol,"KMD") == 0 ) + { + LP_importaddress("KMD",BOTS_BONDADDRESS); + LP_dPoW_request(coin); + } + } + 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; + } + } } } 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,G.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); @@ -701,11 +762,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 { @@ -716,62 +775,181 @@ 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; j 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) +void LP_swapsloop(void *ctx) { - sleep(20); + char *retstr; + strcpy(LP_swapsloop_stats.name,"LP_swapsloop"); + LP_swapsloop_stats.threshold = 605000.; + sleep(50); while ( 1 ) { - LP_counter += 1000; - //printf("LP_privkeysloop %u\n",LP_counter); - LP_privkey_updates(ctx,LP_mypubsock,0); - sleep(LP_ORDERBOOK_DURATION * .777); + LP_millistats_update(&LP_swapsloop_stats); + if ( (retstr= basilisk_swapentry(0,0,0)) != 0 ) + free(retstr); + sleep(600); } } -void LP_swapsloop(void *ignore) +void gc_loop(void *ctx) { - char *retstr; - sleep(50); + 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 ) { - LP_counter += 10000; - //printf("LP_swapsloop %u\n",LP_counter); - if ( (retstr= basilisk_swapentry(0,0)) != 0 ) - free(retstr); - sleep(600); + 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 *ctx) +{ + struct LP_queue *ptr,*tmp; int32_t sentbytes,nonz,flag,duplicate,n=0; + strcpy(queue_loop_stats.name,"queue_loop"); + queue_loop_stats.threshold = 1000.; + while ( 1 ) + { + LP_millistats_update(&queue_loop_stats); + //printf("LP_Q.%p next.%p prev.%p\n",LP_Q,LP_Q!=0?LP_Q->next:0,LP_Q!=0?LP_Q->prev:0); + n = nonz = flag = 0; + DL_FOREACH_SAFE(LP_Q,ptr,tmp) + { + n++; + flag = 0; + if ( ptr->sock >= 0 ) + { + if ( ptr->notready == 0 || (LP_rand() % ptr->notready) == 0 ) + { + if ( LP_sockcheck(ptr->sock) > 0 ) + { + bits256 magic; + magic = LP_calc_magic(ptr->msg,(int32_t)(ptr->msglen - sizeof(bits256))); + memcpy(&ptr->msg[ptr->msglen - sizeof(bits256)],&magic,sizeof(magic)); + if ( (sentbytes= nn_send(ptr->sock,ptr->msg,ptr->msglen,0)) != ptr->msglen ) + printf("%d LP_send sent %d instead of %d\n",n,sentbytes,ptr->msglen); + else flag++; + ptr->sock = -1; + if ( ptr->peerind > 0 ) + ptr->starttime = (uint32_t)time(NULL); + } + else + { + if ( ptr->notready++ > 1000 ) + flag = 1; + } + } + } + else if ( 0 && time(NULL) > ptr->starttime+13 ) + { + LP_crc32find(&duplicate,-1,ptr->crc32); + if ( duplicate > 0 ) + { + LP_Qfound++; + if ( (LP_Qfound % 100) == 0 ) + printf("found.%u Q.%d err.%d match.%d\n",ptr->crc32,LP_Qenqueued,LP_Qerrors,LP_Qfound); + flag++; + } + else if ( 0 ) // too much beyond duplicate filter when network is busy + { + printf("couldnt find.%u peerind.%d Q.%d err.%d match.%d\n",ptr->crc32,ptr->peerind,LP_Qenqueued,LP_Qerrors,LP_Qfound); + ptr->peerind++; + if ( (ptr->sock= LP_peerindsock(&ptr->peerind)) < 0 ) + { + printf("%d no more peers to try at peerind.%d %p Q_LP.%p\n",n,ptr->peerind,ptr,LP_Q); + flag++; + LP_Qerrors++; + } + } + } + if ( flag != 0 ) + { + nonz++; + portable_mutex_lock(&LP_networkmutex); + DL_DELETE(LP_Q,ptr); + portable_mutex_unlock(&LP_networkmutex); + free(ptr); + ptr = 0; + break; + } + } + if ( nonz == 0 ) + { + if ( IAMLP == 0 ) + usleep(50000); + else usleep(10000); + } } } void LP_reserved_msgs(void *ignore) { - bits256 zero; int32_t flag; struct nn_pollfd pfd; + 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 ) { - if ( num_Reserved_msgs > 0 ) + 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 ) { @@ -784,39 +962,60 @@ void LP_reserved_msgs(void *ignore) if ( flag == 1 ) { portable_mutex_lock(&LP_reservedmutex); - num_Reserved_msgs--; - LP_broadcast_message(LP_mypubsock,"","",zero,Reserved_msgs[num_Reserved_msgs]); - Reserved_msgs[num_Reserved_msgs] = 0; + 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); } } if ( ignore == 0 ) break; - usleep(3000); + if ( nonz != 0 ) + usleep(1000); + else usleep(5000); } } -int32_t LP_reserved_msg(char *base,char *rel,bits256 pubkey,char *msg) +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 < sizeof(Reserved_msgs)/sizeof(*Reserved_msgs) ) + if ( num_Reserved_msgs[priority] < sizeof(Reserved_msgs[priority])/sizeof(*Reserved_msgs[priority]) ) { - Reserved_msgs[num_Reserved_msgs++] = msg; - n = num_Reserved_msgs; - } else LP_broadcast_message(LP_mypubsock,base,rel,pubkey,msg); - portable_mutex_unlock(&LP_reservedmutex); - if ( num_Reserved_msgs > max_Reserved_msgs ) + 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 = num_Reserved_msgs; - printf("New max_Reserved_msgs.%d\n",max_Reserved_msgs); + 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 valid,timeout,pubsock=-1; struct LP_peerinfo *mypeer=0; char pushaddr[128],bindaddr2[128],subaddr[128],bindaddr[128],*coins_str=0; cJSON *coinsjson=0; 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 ) { @@ -832,6 +1031,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 ) @@ -866,7 +1066,9 @@ 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); @@ -876,6 +1078,11 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu 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); + portable_mutex_init(&LP_logmutex); + portable_mutex_init(&LP_statslogmutex); + portable_mutex_init(&LP_tradesmutex); myipaddr = clonestr("127.0.0.1"); #ifndef _WIN32 #ifndef FROM_JS @@ -900,15 +1107,15 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu pubsock = -1; nanomsg_transportname(0,subaddr,myipaddr,mypubport); nanomsg_transportname(1,bindaddr,myipaddr,mypubport); - nanomsg_transportname2(1,bindaddr2,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 ( nn_bind(pubsock,bindaddr2) >= 0 ) + // valid++; if ( valid > 0 ) { timeout = 1; @@ -921,11 +1128,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) (%s) pullsock.%d valid.%d\n",bindaddr,bindaddr2,subaddr,pubsock,valid); + 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); @@ -952,6 +1160,10 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu LP_initcoins(ctx,pubsock,coinsjson); G.waiting = 1; LP_passphrase_init(passphrase,jstr(argjson,"gui")); + //char coinaddr[64]; bits256 zero; + //bitcoin_address(coinaddr,0,60,G.LP_myrmd160,20); + //memset(zero.bytes,0,sizeof(zero)); + //LP_instantdex_depositadd(coinaddr,zero); #ifndef FROM_JS if ( IAMLP != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_psockloop,(void *)myipaddr) != 0 ) { @@ -963,62 +1175,69 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu 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 ) + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)stats_rpcloop,(void *)&myport) != 0 ) { - printf("error launching utxosQ_loop for (%s)\n",myipaddr); + printf("error launching stats rpcloop for port.%u\n",myport); exit(-1); } - if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)stats_rpcloop,(void *)&myport) != 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 *)command_rpcloop,(void *)myipaddr) != 0 ) + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)command_rpcloop,ctx) != 0 ) + { + printf("error launching command_rpcloop for ctx.%p\n",ctx); + exit(-1); + } + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)queue_loop,ctx) != 0 ) { - printf("error launching command_rpcloop for port.%u\n",myport); + printf("error launching queue_loop for ctx.%p\n",ctx); 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 *)gc_loop,ctx) != 0 ) { - printf("error launching queue_loop for port.%u\n",myport); + printf("error launching gc_loop for port.%p\n",ctx); 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 *)prices_loop,ctx) != 0 ) { - printf("error launching prices_loop for port.%u\n",myport); + printf("error launching prices_loop for ctx.%p\n",ctx); 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); + printf("error launching LP_coinsloop for (%s)\n",""); 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); + printf("error launching LP_coinsloop for (%s)\n","BTC"); 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); + printf("error launching LP_coinsloop for (%s)\n","KMD"); exit(-1); } - if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_pubkeysloop,(void *)myipaddr) != 0 ) + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_pubkeysloop,ctx) != 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 ) + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_tradesloop,ctx) != 0 ) { - printf("error launching LP_privkeysloop for ctx.%p\n",ctx); + printf("error launching LP_tradessloop for ctx.%p\n",ctx); exit(-1); } - if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_swapsloop,(void *)myipaddr) != 0 ) + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_swapsloop,ctx) != 0 ) { - printf("error launching LP_swapsloop for port.%u\n",myport); + printf("error launching LP_swapsloop for ctx.%p\n",ctx); exit(-1); } int32_t nonz; + LP_statslog_parse(); while ( 1 ) { nonz = 0; @@ -1051,7 +1270,7 @@ char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char * 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/req.%u",counter); + sprintf(fname,"bitcoind_RPC/request.%d",counter % 10); counter++; //printf("issue.(%s)\n",url); emscripten_wget(url,fname); @@ -1060,6 +1279,21 @@ char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char * 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; @@ -1070,30 +1304,116 @@ void LP_fromjs_iter() } 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); + //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); + //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 + if ( 0 ) // 10 seconds { LP_coinsloop(0); - if ( (LP_counter % 100) == 0 ) // 100 seconds + if ( 0 ) // 100 seconds { LP_notify_pubkeys(ctx,LP_mypubsock); LP_privkey_updates(ctx,LP_mypubsock,0); - prices_loop(0); - if ( (retstr= basilisk_swapentry(0,0)) != 0 ) + if ( (retstr= basilisk_swapentry(0,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 1b6713614..673db2940 100644 --- a/iguana/exchanges/LP_network.c +++ b/iguana/exchanges/LP_network.c @@ -29,7 +29,7 @@ struct psock uint16_t Numpsocks,Psockport = MIN_PSOCK_PORT; #ifdef FROM_JS -/* + int32_t nn_socket(int domain, int protocol) { return(0); @@ -69,6 +69,7 @@ int32_t nn_shutdown(int s, int how) int32_t nn_send(int s, const void *buf, size_t len, int flags) { + printf("JS cant nn_send (%s)\n",(char *)buf); return(0); } @@ -90,24 +91,24 @@ const char *nn_strerror(int errnum) int32_t nn_poll(struct nn_pollfd *fds, int nfds, int timeout) { return(0); -}*/ +} #endif char *nanomsg_transportname(int32_t bindflag,char *str,char *ipaddr,uint16_t port) { - sprintf(str,"ws://%s:%u",bindflag == 0 ? ipaddr : "*",port); + sprintf(str,"tcp://%s:%u",bindflag == 0 ? ipaddr : "*",port); return(str); } -char *nanomsg_transportname2(int32_t bindflag,char *str,char *ipaddr,uint16_t port) +/*char *nanomsg_transportname2(int32_t bindflag,char *str,char *ipaddr,uint16_t port) { - sprintf(str,"tcp://%s:%u",bindflag == 0 ? ipaddr : "*",port+10); + sprintf(str,"ws://%s:%u",bindflag == 0 ? ipaddr : "*",port+10); return(str); } -/*int32_t _LP_send(int32_t sock,void *msg,int32_t sendlen,int32_t freeflag) +int32_t _LP_send(int32_t sock,void *msg,int32_t sendlen,int32_t freeflag) { int32_t sentbytes; if ( sock < 0 ) @@ -139,7 +140,7 @@ struct LP_queue { struct LP_queue *next,*prev; int32_t sock,peerind,msglen; - uint32_t starttime,crc32; + uint32_t starttime,crc32,notready; uint8_t msg[]; } *LP_Q; int32_t LP_Qenqueued,LP_Qerrors,LP_Qfound; @@ -182,11 +183,11 @@ bits256 LP_calc_magic(uint8_t *msg,int32_t len) sum += (OS_milliseconds() - millis); nsum += n; counter++; - if ( n > maxn || (rand() % 100) == 0 ) + if ( n > maxn || (LP_rand() % 10000) == 0 ) { if ( n > maxn ) { - printf("LP_calc_magic maxn.%d <- %d\n",maxn,n); + printf("LP_calc_magic maxn.%d <- %d | ",maxn,n); maxn = n; } printf("millis %.3f ave %.3f, aveiters %.1f\n",OS_milliseconds() - millis,sum/counter,(double)nsum/counter); @@ -236,7 +237,7 @@ int32_t LP_crc32find(int32_t *duplicatep,int32_t ind,uint32_t crc32) break; } if ( i >= sizeof(crcs)/sizeof(*crcs) ) - i = (rand() % (sizeof(crcs)/sizeof(*crcs))); + i = (LP_rand() % (sizeof(crcs)/sizeof(*crcs))); return(i); } else @@ -264,87 +265,17 @@ int32_t LP_peerindsock(int32_t *peerindp) return(-1); } -void queue_loop(void *arg) -{ - struct LP_queue *ptr,*tmp; int32_t sentbytes,nonz,flag,duplicate,n=0; - while ( 1 ) - { - nonz = 0; - //printf("LP_Q.%p next.%p prev.%p\n",LP_Q,LP_Q!=0?LP_Q->next:0,LP_Q!=0?LP_Q->prev:0); - n = 0; - DL_FOREACH_SAFE(LP_Q,ptr,tmp) - { - n++; - flag = 0; - if ( ptr->sock >= 0 ) - { - if ( LP_sockcheck(ptr->sock) > 0 ) - { - bits256 magic; - magic = LP_calc_magic(ptr->msg,(int32_t)(ptr->msglen - sizeof(bits256))); - memcpy(&ptr->msg[ptr->msglen - sizeof(bits256)],&magic,sizeof(magic)); - if ( (sentbytes= nn_send(ptr->sock,ptr->msg,ptr->msglen,0)) != ptr->msglen ) - printf("%d LP_send sent %d instead of %d\n",n,sentbytes,ptr->msglen); - ptr->sock = -1; - if ( ptr->peerind > 0 ) - ptr->starttime = (uint32_t)time(NULL); - else flag = 1; - } //else printf("sock not ready to send.%d\n",ptr->msglen); - } - else if ( 0 && time(NULL) > ptr->starttime+13 ) - { - LP_crc32find(&duplicate,-1,ptr->crc32); - if ( duplicate > 0 ) - { - LP_Qfound++; - if ( (LP_Qfound % 100) == 0 ) - printf("found.%u Q.%d err.%d match.%d\n",ptr->crc32,LP_Qenqueued,LP_Qerrors,LP_Qfound); - flag = 1; - } - else if ( 0 ) // too much beyond duplicate filter when network is busy - { - printf("couldnt find.%u peerind.%d Q.%d err.%d match.%d\n",ptr->crc32,ptr->peerind,LP_Qenqueued,LP_Qerrors,LP_Qfound); - ptr->peerind++; - if ( (ptr->sock= LP_peerindsock(&ptr->peerind)) < 0 ) - { - printf("%d no more peers to try at peerind.%d %p Q_LP.%p\n",n,ptr->peerind,ptr,LP_Q); - flag = 1; - LP_Qerrors++; - } - } - } - if ( flag != 0 ) - { - nonz++; - portable_mutex_lock(&LP_networkmutex); - DL_DELETE(LP_Q,ptr); - portable_mutex_unlock(&LP_networkmutex); - free(ptr); - ptr = 0; - } - } - if ( arg == 0 ) - break; - //if ( n != 0 ) - // printf("LP_Q.[%d]\n",n); - if ( nonz == 0 ) - usleep(5000); - else if ( IAMLP == 0 ) - usleep(1000); - } -} - void _LP_queuesend(uint32_t crc32,int32_t sock0,int32_t sock1,uint8_t *msg,int32_t msglen,int32_t needack) { int32_t maxind,peerind = 0; //sentbytes, if ( sock0 < 0 && sock1 < 0 ) { if ( (maxind= LP_numpeers()) > 0 ) - peerind = (rand() % maxind) + 1; + peerind = (LP_rand() % maxind) + 1; else peerind = 1; sock0 = LP_peerindsock(&peerind); if ( (maxind= LP_numpeers()) > 0 ) - peerind = (rand() % maxind) + 1; + peerind = (LP_rand() % maxind) + 1; else peerind = 1; sock1 = LP_peerindsock(&peerind); } @@ -373,9 +304,14 @@ void LP_broadcast_finish(int32_t pubsock,char *base,char *rel,uint8_t *msg,cJSON msglen = (int32_t)strlen((char *)msg) + 1; if ( crc32 == 0 ) crc32 = calc_crc32(0,&msg[2],msglen - 2); +#ifdef FROM_MARKETMAKER + if ( G.LP_IAMLP == 0 ) +#else if ( IAMLP == 0 ) +#endif { free(msg); +//printf("broadcast %s\n",jstr(argjson,"method")); jdelete(argjson,"method"); jaddstr(argjson,"method","broadcast"); if ( jobj(argjson,"timestamp") == 0 ) @@ -473,8 +409,11 @@ void LP_psockloop(void *_ptr) // printouts seem to be needed for forwarding to w { static struct nn_pollfd *pfds; int32_t i,n,nonz,iter,retval,sentbytes,size=0,sendsock = -1; uint32_t now; struct psock *ptr=0; void *buf=0; char keepalive[512]; + strcpy(LP_psockloop_stats.name,"LP_psockloop"); + LP_psockloop_stats.threshold = 200.; while ( 1 ) { + LP_millistats_update(&LP_psockloop_stats); now = (uint32_t)time(NULL); if ( buf != 0 && ptr != 0 && sendsock >= 0 ) { @@ -518,13 +457,20 @@ void LP_psockloop(void *_ptr) // printouts seem to be needed for forwarding to w } else if ( (pfds[n].revents & POLLIN) != 0 ) { - printf("publicsock.%d %s has pollin\n",ptr->publicsock,ptr->publicaddr); + //printf("publicsock.%d %s has pollin\n",ptr->publicsock,ptr->publicaddr); + buf = 0; if ( (size= nn_recv(ptr->publicsock,&buf,NN_MSG,0)) > 0 ) { ptr->lasttime = now; sendsock = ptr->sendsock; break; } + else if ( buf != 0 ) + { + nn_freemsg(buf); + buf = 0; + size = 0; + } } } n++; @@ -551,12 +497,12 @@ void LP_psockloop(void *_ptr) // printouts seem to be needed for forwarding to w sendsock = ptr->publicsock; break; } - else - { - nn_freemsg(buf); - buf = 0; - size = 0; - } + } + if ( buf != 0 ) + { + nn_freemsg(buf); + buf = 0; + size = 0; } } } @@ -724,17 +670,18 @@ char *LP_psock(char *myipaddr,int32_t ispaired) both are combined in LP_psock_get */ + char *issue_LP_psock(char *destip,uint16_t destport,int32_t ispaired) { char url[512],*retstr; - sprintf(url,"http://%s:%u/api/stats/psock?ispaired=%d",destip,destport,ispaired); + sprintf(url,"http://%s:%u/api/stats/psock?ispaired=%d",destip,destport-1,ispaired); //return(LP_issue_curl("psock",destip,destport,url)); retstr = issue_curlt(url,LP_HTTP_TIMEOUT*3); printf("issue_LP_psock got (%s) from %s\n",retstr,destip); return(retstr); } -uint16_t LP_psock_get(char *connectaddr,char *connectaddr2,char *publicaddr,int32_t ispaired) +uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired) { uint16_t publicport = 0; char *retstr,*addr; cJSON *retjson; struct LP_peerinfo *peer,*tmp; HASH_ITER(hh,LP_peerinfos,peer,tmp) @@ -749,8 +696,8 @@ uint16_t LP_psock_get(char *connectaddr,char *connectaddr2,char *publicaddr,int3 safecopy(publicaddr,addr,128); if ( (addr= jstr(retjson,"connectaddr")) != 0 ) safecopy(connectaddr,addr,128); - if ( (addr= jstr(retjson,"connectaddr2")) != 0 ) - safecopy(connectaddr2,addr,128); + //if ( (addr= jstr(retjson,"connectaddr2")) != 0 ) + // safecopy(connectaddr2,addr,128); if ( publicaddr[0] != 0 && connectaddr[0] != 0 ) publicport = juint(retjson,"publicport"); free_json(retjson); @@ -766,9 +713,9 @@ uint16_t LP_psock_get(char *connectaddr,char *connectaddr2,char *publicaddr,int3 int32_t LP_initpublicaddr(void *ctx,uint16_t *mypullportp,char *publicaddr,char *myipaddr,uint16_t mypullport,int32_t ispaired) { - int32_t nntype,pullsock,timeout; char bindaddr[128],bindaddr2[128],connectaddr[128],connectaddr2[128]; + int32_t nntype,pullsock,timeout; char bindaddr[128],connectaddr[128]; *mypullportp = mypullport; - connectaddr2[0] = 0; + //connectaddr2[0] = 0; if ( ispaired == 0 ) { if ( LP_canbind != 0 ) @@ -779,7 +726,7 @@ int32_t LP_initpublicaddr(void *ctx,uint16_t *mypullportp,char *publicaddr,char { nanomsg_transportname(0,publicaddr,myipaddr,mypullport); nanomsg_transportname(1,bindaddr,myipaddr,mypullport); - nanomsg_transportname2(1,bindaddr2,myipaddr,mypullport); + //nanomsg_transportname2(1,bindaddr2,myipaddr,mypullport); } else { @@ -791,7 +738,7 @@ int32_t LP_initpublicaddr(void *ctx,uint16_t *mypullportp,char *publicaddr,char } while ( *mypullportp == 0 ) { - if ( (*mypullportp= LP_psock_get(connectaddr,connectaddr2,publicaddr,ispaired)) != 0 ) + if ( (*mypullportp= LP_psock_get(connectaddr,publicaddr,ispaired)) != 0 ) break; sleep(10); printf("try to get publicaddr again\n"); @@ -810,8 +757,8 @@ int32_t LP_initpublicaddr(void *ctx,uint16_t *mypullportp,char *publicaddr,char } else { - if ( connectaddr2[0] != 0 && nn_connect(pullsock,connectaddr2) > 0 ) - printf("%s ",connectaddr2); + //if ( connectaddr2[0] != 0 && nn_connect(pullsock,connectaddr2) > 0 ) + // printf("%s ",connectaddr2); printf("nntype.%d NN_PAIR.%d connect to %s connectsock.%d\n",nntype,NN_PAIR,connectaddr,pullsock); } } @@ -822,8 +769,8 @@ int32_t LP_initpublicaddr(void *ctx,uint16_t *mypullportp,char *publicaddr,char printf("bind to %s error for %s: %s\n",bindaddr,publicaddr,nn_strerror(nn_errno())); exit(-1); } - if ( nn_bind(pullsock,bindaddr2) >= 0 ) - printf("bound to %s\n",bindaddr2); + //if ( nn_bind(pullsock,bindaddr2) >= 0 ) + // printf("bound to %s\n",bindaddr2); } timeout = 1; nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); diff --git a/iguana/exchanges/LP_ordermatch.c b/iguana/exchanges/LP_ordermatch.c index aba389945..86cb812e4 100644 --- a/iguana/exchanges/LP_ordermatch.c +++ b/iguana/exchanges/LP_ordermatch.c @@ -18,6 +18,49 @@ // LP_ordermatch.c // marketmaker // +struct LP_quoteinfo LP_Alicequery,LP_Alicereserved; +double LP_Alicemaxprice; +bits256 LP_Alicedestpubkey,LP_bobs_reserved; +uint32_t Alice_expiration,Bob_expiration; +struct { uint64_t aliceid; double bestprice; uint32_t starttime,counter; } Bob_competition[512]; + +double LP_bob_competition(int32_t *counterp,uint64_t aliceid,double price,int32_t counter) +{ + 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; + } + 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); +} uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee,int32_t txlen) { @@ -42,23 +85,6 @@ uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee,int32_t txlen) 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) -{ - uint64_t destsatoshis,satoshis; - a_value -= (desttxfee + 1); - destsatoshis = ((b_satoshis - txfee) * price); - if ( destsatoshis > a_value ) - destsatoshis = a_value; - if ( maxdestsatoshis != 0 && destsatoshis > maxdestsatoshis-desttxfee-1 ) - destsatoshis = maxdestsatoshis-desttxfee-1; - satoshis = (destsatoshis / price + 0.49) - txfee; - *destsatoshisp = destsatoshis; - *satoshisp = satoshis; - if ( satoshis > 0 ) - return((double)destsatoshis / satoshis); - else return(0.); -} - int32_t LP_quote_checkmempool(struct LP_quoteinfo *qp,struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo) { int32_t selector,spendvini; bits256 spendtxid; @@ -78,12 +104,12 @@ int32_t LP_quote_checkmempool(struct LP_quoteinfo *qp,struct LP_utxoinfo *autxo, double LP_quote_validate(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,struct LP_quoteinfo *qp,int32_t iambob) { double qprice=0.; 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)); + //printf(">>>>>>> quote satoshis.(%.8f %.8f) %s %.8f -> %s %.8f\n",dstr(qp->satoshis),dstr(qp->destsatoshis),qp->srccoin,dstr(qp->satoshis),qp->destcoin,dstr(qp->destsatoshis)); if ( butxo != 0 ) { if ( LP_iseligible(&srcvalue,&srcvalue2,1,qp->srccoin,qp->txid,qp->vout,qp->satoshis,qp->txid2,qp->vout2) == 0 ) { - printf("bob not eligible %s\n",jprint(LP_quotejson(qp),1)); + //printf("bob not eligible %s (%.8f %.8f)\n",jprint(LP_quotejson(qp),1),dstr(srcvalue),dstr(srcvalue2)); return(-2); } if ( (txout= LP_gettxout(qp->srccoin,qp->coinaddr,qp->txid,qp->vout)) != 0 ) @@ -115,7 +141,8 @@ double LP_quote_validate(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,str { if ( LP_iseligible(&destvalue,&destvalue2,0,qp->destcoin,qp->desttxid,qp->destvout,qp->destsatoshis,qp->feetxid,qp->feevout) == 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); + //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 ) @@ -133,25 +160,22 @@ double LP_quote_validate(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,str return(-24); } } + //printf("checked autxo and butxo\n"); if ( LP_quote_checkmempool(qp,autxo,butxo) < 0 ) return(-4); - //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(autxo->coinaddr,qp->destaddr) != 0 ) return(-10); } - if ( autxo != 0 && destvalue < 2*qp->desttxfee+qp->destsatoshis ) + if ( autxo != 0 && destvalue < qp->desttxfee+qp->destsatoshis ) { printf("destvalue %.8f destsatoshis %.8f is too small txfee %.8f?\n",dstr(destvalue),dstr(qp->destsatoshis),dstr(qp->desttxfee)); return(-11); } - if ( butxo != 0 && srcvalue < 2*qp->txfee+qp->satoshis ) + if ( butxo != 0 && srcvalue < qp->txfee+qp->satoshis ) { printf("srcvalue %.8f [%.8f] satoshis %.8f is too small txfee %.8f?\n",dstr(srcvalue),dstr(srcvalue) - dstr(qp->txfee+qp->satoshis),dstr(qp->satoshis),dstr(qp->txfee)); return(-33); @@ -163,7 +187,7 @@ double LP_quote_validate(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,str 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)); + //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 ) @@ -208,7 +232,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); @@ -231,13 +255,13 @@ int32_t LP_nanobind(void *ctx,char *pairstr) int32_t LP_nearest_utxovalue(struct iguana_info *coin,char *coinaddr,struct LP_address_utxo **utxos,int32_t n,uint64_t targetval) { - int32_t i,mini = -1; struct LP_address_utxo *up; struct electrum_info *backupep=0,*ep; int64_t dist; uint64_t mindist = (1LL << 60); + 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)); + //printf("LP_nearest_utxovalue %s %s utxos[%d] target %.8f\n",coin->symbol,coinaddr,n,dstr(targetval)); for (i=0; iU.value),dstr(dist),dstr(mindist),mini,up->spendheight); if ( up->spendheight <= 0 ) { - if ( (coin->electrum == 0 || up->SPV > 0) && dist >= 0 && dist < mindist ) + if ( dist >= 0 && dist < mindist ) { //printf("(%.8f %.8f %.8f).%d ",dstr(up->U.value),dstr(dist),dstr(mindist),mini); mini = i; @@ -255,61 +279,57 @@ int32_t LP_nearest_utxovalue(struct iguana_info *coin,char *coinaddr,struct LP_a } } } + 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(((double)bestheight - up->U.height)/1000) ) + { + 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); } -uint64_t LP_basesatoshis(double relvolume,double price,uint64_t txfee,uint64_t desttxfee) +void LP_butxo_set(struct LP_utxoinfo *butxo,int32_t iambob,struct iguana_info *coin,struct LP_address_utxo *up,struct LP_address_utxo *up2,int64_t satoshis) { - //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_utxopair(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; struct LP_utxoinfo *utxo = 0; - if ( coin != 0 && (ap= LP_addressfind(coin,coinaddr)) != 0 ) + 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; + if ( (butxo->iambob= iambob) != 0 ) { - if ( (m= LP_address_utxo_ptrs(coin,iambob,utxos,max,ap,coinaddr)) > 1 ) - { - targetval = LP_basesatoshis(relvolume,price,txfee,desttxfee); - if ( 0 ) - { - int32_t i; - for (i=0; iU.value)); - printf("targetval %.8f vol %.8f price %.8f txfee %.8f %s\n",dstr(targetval),relvolume,price,dstr(txfee),coinaddr); - } - mini = -1; - if ( targetval != 0 && (mini= LP_nearest_utxovalue(coin,coinaddr,utxos,m,targetval)) >= 0 ) - { - up = utxos[mini]; - utxos[mini] = 0; - targetval2 = (targetval / 8) * 9 + 2*txfee; - //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 * 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)) != 0 ) - { - utxo->S.satoshis = targetval; - char str[65],str2[65]; printf("butxo.%p targetval %.8f, found val %.8f %s | targetval2 %.8f val2 %.8f %s\n",utxo,dstr(targetval),dstr(up->U.value),bits256_str(str,utxo->payment.txid),dstr(targetval2),dstr(up2->U.value),bits256_str(str2,utxo->deposit.txid)); - return(utxo); - } - } - } //else printf("cant find targetval2 %.8f\n",dstr(targetval2)); - } else printf("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("couldnt find %s %s\n",coin->symbol,coinaddr); - return(0); + butxo->deposit.txid = up2->U.txid; + butxo->deposit.vout = up2->U.vout; + butxo->deposit.value = up2->U.value; + } + else + { + butxo->fee.txid = up2->U.txid; + butxo->fee.vout = up2->U.vout; + butxo->fee.value = up2->U.value; + } + butxo->swap_satoshis = satoshis; } void LP_abutxo_set(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,struct LP_quoteinfo *qp) @@ -327,7 +347,7 @@ void LP_abutxo_set(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,struct LP butxo->deposit.txid = qp->txid2; butxo->deposit.vout = qp->vout2; //butxo->deposit.value = up2->U.value; - butxo->S.satoshis = qp->satoshis; + butxo->swap_satoshis = qp->satoshis; } if ( autxo != 0 ) { @@ -342,524 +362,900 @@ void LP_abutxo_set(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,struct LP autxo->fee.txid = qp->feetxid; autxo->fee.vout = qp->feevout; //autxo->deposit.value = up2->U.value; - autxo->S.satoshis = qp->destsatoshis; + autxo->swap_satoshis = qp->destsatoshis; } } -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) +uint64_t LP_basesatoshis(double relvolume,double price,uint64_t txfee,uint64_t desttxfee) { - 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); + //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 fee,targetval,targetval2; int32_t m,mini; struct LP_address_utxo *up,*up2; double ratio; + memset(butxo,0,sizeof(*butxo)); + if ( iambob != 0 ) + { + targetval = LP_basesatoshis(relvolume,price,txfee,desttxfee) + 3*txfee; + targetval2 = (targetval / 8) * 9 + 3*txfee; + fee = txfee; + ratio = LP_MINVOL; + } + else + { + targetval = relvolume*SATOSHIDEN + 3*desttxfee; + targetval2 = (targetval / 777) + 3*desttxfee; + fee = desttxfee; + ratio = LP_MINCLIENTVOL; + } + 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(fee),coin->symbol,coinaddr); + } + while ( 1 ) + { + mini = -1; + if ( targetval != 0 && (mini= LP_nearest_utxovalue(coin,coinaddr,utxos,m,targetval+fee)) >= 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 < ratio-1 ) + + { + if ( 0 ) + { + int32_t i; + for (i=0; iU.value >= targetval2 ) + printf("%.8f ",dstr(utxos[i]->U.value)); + printf("targetval2 %.8f vol %.8f price %.8f txfee %.8f %s %s\n",dstr(targetval2),relvolume,price,dstr(fee),coin->symbol,coinaddr); + } + if ( (mini= LP_nearest_utxovalue(coin,coinaddr,utxos,m,(targetval2+2*fee) * 1.01)) >= 0 ) + { + if ( up != 0 && (up2= utxos[mini]) != 0 ) + { + LP_butxo_set(butxo,iambob,coin,up,up2,targetval); + return(butxo); + } else printf("cant find utxos[mini %d]\n",mini); + } 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); + if ( targetval == 0 || mini < 0 ) + break; + } + } 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,char *base,char *rel,double price,struct LP_quoteinfo *qp) +{ + char pairstr[512],otheraddr[64]; cJSON *reqjson; bits256 privkey; int32_t pair=-1,retval = -1,DEXselector = 0; struct basilisk_swap *swap; struct iguana_info *coin,*kmdcoin; 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 && bits256_cmp(G.LP_mypub25519,qp->srchash) == 0 ) //qp->quotetime >= qp->timestamp-3 && qp->quotetime <= utxo->T.swappending && + 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,LP_dynamictrust(qp->othercredits,qp->desthash,LP_kmdvalue(qp->destcoin,qp->destsatoshis)) > 0)) == 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-2*qp->txfee,rel,qp->destsatoshis-2*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); - // LP_addsig - char str[65]; printf("BOB pubsock.%d binds to %d (%s)\n",pubsock,pair,bits256_str(str,utxo->S.otherpubkey)); - LP_reserved_msg(base,rel,utxo->S.otherpubkey,jprint(retjson,0)); - LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,qp->desthash,jprint(retjson,0)); - free_json(retjson); + reqjson = LP_quotejson(qp); + jaddstr(reqjson,"method","connected"); + jaddstr(reqjson,"pair",pairstr); + if ( (kmdcoin= LP_coinfind("KMD")) != 0 ) + jadd(reqjson,"proof",LP_instantdex_txids(0,kmdcoin->smartaddr)); + char str[65]; printf("BOB pubsock.%d binds to %d (%s)\n",pubsock,pair,bits256_str(str,qp->desthash)); + bits256 zero; + memset(zero.bytes,0,sizeof(zero)); + LP_reserved_msg(1,base,rel,zero,jprint(reqjson,0)); + if ( IAMLP == 0 ) + { + sleep(1); + LP_reserved_msg(1,qp->srccoin,qp->destcoin,qp->desthash,jprint(reqjson,0)); + } + LP_reserved_msg(0,base,rel,zero,jprint(reqjson,0)); + free_json(reqjson); + LP_importaddress(qp->destcoin,qp->destaddr); + LP_otheraddress(qp->srccoin,otheraddr,qp->destcoin,qp->destaddr); + LP_importaddress(qp->srccoin,otheraddr); 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(G.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_butxo_swapfields(utxo); + LP_availableset(qp->txid,qp->vout); + LP_availableset(qp->txid2,qp->vout2); + } return(retval); } -struct LP_quoteinfo LP_Alicequery; -double LP_Alicemaxprice; -uint32_t Alice_expiration; -char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp,double maxprice,int32_t timeout,int32_t duration) +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; //cJSON *bestitem=0; int32_t DEXselector=0; uint32_t expiration; double price; struct LP_pubkeyinfo *pubp; struct basilisk_swap *swap; - if ( (aliceutxo= LP_utxopairfind(0,qp->desttxid,qp->destvout,qp->feetxid,qp->feevout)) == 0 ) - { - char str[65],str2[65]; printf("dest.(%s)/v%d fee.(%s)/v%d\n",bits256_str(str,qp->desttxid),qp->destvout,bits256_str(str2,qp->feetxid),qp->feevout); - return(clonestr("{\"error\":\"cant find alice utxopair\"}")); - } + double price; 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; - return(clonestr("{\"result\":\"success\"}")); + 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(struct LP_quoteinfo *qp,struct LP_quoteinfo *qp2) +int32_t LP_quotecmp(int32_t strictflag,struct LP_quoteinfo *qp,struct LP_quoteinfo *qp2) { - if ( bits256_cmp(qp->srchash,qp2->srchash) == 0 && bits256_cmp(qp->desthash,qp2->desthash) == 0 && strcmp(qp->srccoin,qp2->srccoin) == 0 && strcmp(qp->destcoin,qp2->destcoin) == 0 && bits256_cmp(qp->desttxid,qp2->desttxid) == 0 && qp->destvout == qp2->destvout && bits256_cmp(qp->feetxid,qp2->feetxid) == 0 && qp->feevout == qp2->feevout && qp->destsatoshis == qp2->destsatoshis && qp->txfee >= qp2->txfee && qp->desttxfee == qp2->desttxfee ) - return(0); - else return(-1); + 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); } -int32_t LP_alice_eligible() +void LP_alicequery_clear() { - if ( Alice_expiration != 0 && time(NULL) > Alice_expiration ) + 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"); - memset(&LP_Alicequery,0,sizeof(LP_Alicequery)); - LP_Alicemaxprice = 0.; - Alice_expiration = 0; + 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) +char *LP_connectedalice(struct LP_quoteinfo *qp,char *pairstr) // alice { - double price=0.,maxprice = LP_Alicemaxprice; - if ( LP_alice_eligible() > 0 && LP_quotecmp(qp,&LP_Alicequery) == 0 ) + cJSON *retjson; char otheraddr[64]; double bid,ask,price,qprice; int32_t pairsock = -1; int32_t DEXselector = 0; struct LP_utxoinfo *autxo,A,B,*butxo; struct basilisk_swap *swap; struct iguana_info *coin; + /*if ( LP_quoteparse(&Q,argjson) < 0 ) { - price = LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout); - if ( LP_pricevalid(price) > 0 && maxprice > SMALLVAL && price <= maxprice ) - { - memset(&LP_Alicequery,0,sizeof(LP_Alicequery)); - LP_Alicemaxprice = 0.; - Alice_expiration = 0; - LP_query(ctx,myipaddr,mypubsock,"connect",qp); - } - } else printf("reject reserved due to not eligible.%d or mismatched quote price %.8f vs maxprice %.8f\n",LP_alice_eligible(),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,B,*butxo; struct LP_quoteinfo Q; struct basilisk_swap *swap; struct iguana_info *coin; //uint64_t value,value2; - 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,G.LP_mypub25519) != 0 ) - return(clonestr("{\"result\",\"update stats\"}")); - printf("CONNECTED.(%s) numpending.%d\n",jprint(argjson,0),G.LP_pendingswaps); - /*if ( LP_alice_eligible() == 0 || LP_quotecmp(&Q,&LP_Alicequery) != 0 ) + }*/ + if ( bits256_cmp(qp->desthash,G.LP_mypub25519) != 0 ) { - printf("reject mismatched alice query\n"); - return(clonestr("{\"error\",\"mismatched alice query\"}")); + LP_aliceid(qp->tradeid,qp->aliceid,"error1",0,0); + return(clonestr("{\"result\",\"update stats\"}")); } - memset(&LP_Alicequery,0,sizeof(LP_Alicequery)); - LP_Alicemaxprice = 0.; - Alice_expiration = 0;*/ - if ( (autxo= LP_utxopairfind(0,Q.desttxid,Q.destvout,Q.feetxid,Q.feevout)) == 0 ) + printf("CONNECTED numpending.%d tradeid.%u requestid.%u quoteid.%u pairstr.%s\n",G.LP_pendingswaps,qp->tradeid,qp->R.requestid,qp->R.quoteid,pairstr!=0?pairstr:""); + LP_requestinit(&qp->R,qp->srchash,qp->desthash,qp->srccoin,qp->satoshis-qp->txfee,qp->destcoin,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector); + //printf("calculated requestid.%u quoteid.%u\n",qp->R.requestid,qp->R.quoteid); + if ( LP_pendingswap(qp->R.requestid,qp->R.quoteid) > 0 ) { - printf("cant find autxo\n"); - return(clonestr("{\"error\":\"cant find autxo\"}")); + printf("requestid.%u quoteid.%u is already in progres\n",qp->R.requestid,qp->R.quoteid); + retjson = cJSON_CreateObject(); + jaddstr(retjson,"error","swap already in progress"); + return(jprint(retjson,1)); } - if ( autxo->S.swap != 0 ) - return(clonestr("{\"error\":\"ignore duplicate swap\"}")); + /*if ( LP_quotecmp(1,qp,&LP_Alicereserved) == 0 ) + { + printf("mismatched between reserved and connected\n"); + }*/ + memset(&LP_Alicereserved,0,sizeof(LP_Alicereserved)); + LP_aliceid(qp->tradeid,qp->aliceid,"connected",qp->R.requestid,qp->R.quoteid); + autxo = &A; butxo = &B; + memset(autxo,0,sizeof(*autxo)); memset(butxo,0,sizeof(*butxo)); - LP_abutxo_set(0,butxo,&Q); - if ( (qprice= LP_quote_validate(autxo,butxo,&Q,0)) <= SMALLVAL ) + LP_abutxo_set(autxo,butxo,qp); + if ( (qprice= LP_quote_validate(autxo,butxo,qp,0)) <= SMALLVAL ) { - LP_availableset(autxo); + LP_availableset(qp->desttxid,qp->vout); + LP_availableset(qp->feetxid,qp->feevout); + LP_aliceid(qp->tradeid,qp->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 ) + if ( LP_myprice(&bid,&ask,qp->srccoin,qp->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); + printf("this node has no price for %s/%s (%.8f %.8f)\n",qp->destcoin,qp->srccoin,bid,ask); + LP_availableset(qp->desttxid,qp->vout); + LP_availableset(qp->feetxid,qp->feevout); + LP_aliceid(qp->tradeid,qp->aliceid,"error5",0,0); return(clonestr("{\"error\":\"no price set\"}")); } - 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)); + //LP_RTmetrics_update(qp->srccoin,qp->destcoin); + printf("%s/%s bid %.8f ask %.8f values %.8f %.8f\n",qp->srccoin,qp->destcoin,bid,ask,dstr(butxo->payment.value),dstr(butxo->deposit.value)); price = bid; - if ( (coin= LP_coinfind(Q.destcoin)) == 0 ) + if ( (coin= LP_coinfind(qp->destcoin)) == 0 ) + { + LP_aliceid(qp->tradeid,qp->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 ) + } + qp->privkey = LP_privkey(qp->destaddr,coin->taddr); + if ( bits256_nonz(qp->privkey) != 0 )//&& qp->quotetime >= qp->timestamp-3 ) { retjson = cJSON_CreateObject(); - if ( (pairstr= jstr(argjson,"pair")) == 0 || (pairsock= nn_socket(AF_SP,NN_PAIR)) < 0 ) + if ( (swap= LP_swapinit(0,0,qp->privkey,&qp->R,qp,LP_dynamictrust(qp->othercredits,qp->srchash,LP_kmdvalue(qp->srccoin,qp->satoshis)) > 0)) == 0 ) + { + jaddstr(retjson,"error","couldnt swapinit"); + LP_availableset(qp->desttxid,qp->vout); + LP_availableset(qp->feetxid,qp->feevout); + LP_aliceid(qp->tradeid,qp->aliceid,"error7",qp->R.requestid,qp->R.quoteid); + return(jprint(retjson,1)); + } + if ( pairstr == 0 || pairstr[0] == 0 || (pairsock= nn_socket(AF_SP,NN_PAIR)) < 0 ) + { + LP_aliceid(qp->tradeid,qp->aliceid,"error8",qp->R.requestid,qp->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-2*Q.txfee,Q.destcoin,Q.destsatoshis-2*Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector); - swap = LP_swapinit(0,0,Q.privkey,&Q.R,&Q); + swap->tradeid = qp->tradeid; swap->N.pair = pairsock; - autxo->S.swap = swap; - swap->utxo = autxo; - printf("alice pairstr.(%s) pairsock.%d\n",pairstr,pairsock); + //autxo->S.swap = swap; + //swap->utxo = autxo; + LP_importaddress(qp->srccoin,qp->coinaddr); + LP_otheraddress(qp->destcoin,otheraddr,qp->srccoin,qp->coinaddr); + LP_importaddress(qp->srccoin,otheraddr); + LP_aliceid(qp->tradeid,qp->aliceid,"started",qp->R.requestid,qp->R.quoteid); + printf("alice pairstr.(%s) pairsock.%d pthread_t %ld\n",pairstr,pairsock,sizeof(pthread_t)); if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_aliceloop,(void *)swap) == 0 ) { - retjson = LP_quotejson(&Q); + retjson = LP_quotejson(qp); jaddstr(retjson,"result","success"); - //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",qp->R.requestid); + //jaddnum(retjson,"quoteid",qp->R.quoteid); + } + else + { + LP_aliceid(qp->tradeid,qp->aliceid,"error9",qp->R.requestid,qp->R.quoteid); + jaddstr(retjson,"error","couldnt aliceloop"); + } + } + else + { + LP_aliceid(qp->tradeid,qp->aliceid,"error10",qp->R.requestid,qp->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); + { + LP_availableset(qp->desttxid,qp->vout); + LP_availableset(qp->feetxid,qp->feevout); + } return(jprint(retjson,1)); } else { - LP_availableset(autxo); - printf("no privkey found coin.%s %s taddr.%u\n",Q.destcoin,Q.destaddr,coin->taddr); + LP_availableset(qp->desttxid,qp->vout); + LP_availableset(qp->feetxid,qp->feevout); + LP_aliceid(qp->tradeid,qp->aliceid,"error11",0,0); + printf("no privkey found coin.%s %s taddr.%u\n",qp->destcoin,qp->destaddr,coin->taddr); return(clonestr("{\"error\",\"no privkey\"}")); } } -int32_t LP_listunspent_both(char *symbol,char *coinaddr,int32_t fullflag) +int32_t LP_aliceonly(char *symbol) { - int32_t i,v,numconfs,height,n=0; uint64_t value; bits256 txid; char buf[512]; cJSON *array,*item; struct iguana_info *coin = LP_coinfind(symbol); - if ( coin != 0 )//&& (IAMLP != 0 || coin->inactive == 0) ) + 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; int32_t height; struct LP_transaction *tx; + coin = LP_coinfind(symbol); + if ( coin != 0 && (ep= coin->electrum) != 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 ( (up= LP_address_utxofind(coin,coinaddr,txid,vout)) == 0 ) { - 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 ( (txobj= electrum_transaction(&height,symbol,ep,&txobj,txid,coinaddr)) != 0 ) + free_json(txobj); + if ( (tx= LP_transactionfind(coin,txid)) != 0 ) { - if ( (n= cJSON_GetArraySize(array)) > 0 ) + if ( vout < tx->numvouts && tx->height > 0 ) { - for (i=0; ioutpoints[vout].value,tx->height,-1); } } } - } //else printf("%s coin.%p inactive.%d\n",symbol,coin,coin!=0?coin->inactive:-1); - return(n); + if ( (up= LP_address_utxofind(coin,coinaddr,txid,vout)) != 0 ) + { + if ( up->SPV > 0 ) + return(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); } -char *LP_bestfit(char *rel,double relvolume) +double LP_trades_alicevalidate(void *ctx,struct LP_quoteinfo *qp) { - 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)); + double qprice; struct LP_utxoinfo A,B,*autxo,*butxo; char str[65]; + autxo = &A; + butxo = &B; + memset(autxo,0,sizeof(*autxo)); + memset(butxo,0,sizeof(*butxo)); + LP_abutxo_set(autxo,butxo,qp); + if ( (qprice= LP_quote_validate(autxo,butxo,qp,0)) <= SMALLVAL ) + { + printf("reserved quote validate error %.0f\n",qprice); + return((int32_t)qprice); + } + if ( LP_validSPV(qp->srccoin,qp->coinaddr,qp->txid,qp->vout) < 0 ) + { + sleep(1); + if ( LP_validSPV(qp->srccoin,qp->coinaddr,qp->txid,qp->vout) < 0 ) + { + printf("LP_trades_alicevalidate %s src %s failed SPV check\n",qp->srccoin,bits256_str(str,qp->txid)); + return(-44); + } + } + else if ( LP_validSPV(qp->srccoin,qp->coinaddr,qp->txid2,qp->vout2) < 0 ) + { + sleep(1); + if ( LP_validSPV(qp->srccoin,qp->coinaddr,qp->txid2,qp->vout2) < 0 ) + { + printf("LP_trades_alicevalidate %s src2 %s failed SPV check\n",qp->srccoin,bits256_str(str,qp->txid2)); + return(-55); + } + } + return(qprice); } -int32_t LP_aliceonly(char *symbol) +void LP_reserved(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp) { - if ( strcmp(symbol,"GAME") == 0 ) - return(1); - else return(0); + 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 %llu price %.8f vs maxprice %.8f\n",(long long)qp->aliceid,price,maxprice); + } //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); } -int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen) +double LP_trades_bobprice(double *bidp,double *askp,struct LP_quoteinfo *qp) { - char *method,*msg,*retstr,str[65]; int32_t DEXselector = 0; uint64_t value,value2; cJSON *retjson; double qprice,price,bid,ask; struct LP_utxoinfo A,B,*autxo,*butxo; struct iguana_info *coin; struct LP_address_utxo *utxos[1000]; struct LP_quoteinfo Q; int32_t retval = -1,max=(int32_t)(sizeof(utxos)/sizeof(*utxos)); - if ( (method= jstr(argjson,"method")) != 0 && (strcmp(method,"reserved") == 0 ||strcmp(method,"connected") == 0 || strcmp(method,"request") == 0 || strcmp(method,"connect") == 0) ) + double price; struct iguana_info *coin; char str[65]; + price = LP_myprice(bidp,askp,qp->srccoin,qp->destcoin); + if ( (coin= LP_coinfind(qp->srccoin)) == 0 || price <= SMALLVAL || *askp <= SMALLVAL ) { - // LP_checksig - LP_quoteparse(&Q,argjson); - LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-2*Q.txfee,Q.destcoin,Q.destsatoshis-2*Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector); - LP_tradecommand_log(argjson); - printf("LP_tradecommand: check received method %s aliceid.%llx\n",method,(long long)Q.aliceid); - retval = 1; - if ( strcmp(method,"reserved") == 0 ) + //printf("this node has no price for %s/%s\n",qp->srccoin,qp->destcoin); + return(0.); + } + price = *askp; + //printf("MYPRICE %s/%s %.8f vs qprice %.8f\n",qp->srccoin,qp->destcoin,price,(double)qp->destsatoshis/qp->satoshis); + if ( LP_validSPV(qp->destcoin,qp->destaddr,qp->desttxid,qp->destvout) < 0 ) + { + printf("LP_trades_bobprice %s dest %s failed SPV check\n",qp->destcoin,bits256_str(str,qp->desttxid)); + return(0.); + } + else if (LP_validSPV(qp->destcoin,qp->destaddr,qp->feetxid,qp->feevout) < 0 ) + { + printf("LP_trades_bobprice %s dexfee %s failed SPV check\n",qp->destcoin,bits256_str(str,qp->feetxid)); + return(0.); + } + return(*askp); +} + +double LP_trades_pricevalidate(struct LP_quoteinfo *qp,struct iguana_info *coin,double price) +{ + double qprice; struct LP_utxoinfo A,B,*autxo,*butxo; + autxo = &A; + butxo = &B; + memset(autxo,0,sizeof(*autxo)); + memset(butxo,0,sizeof(*butxo)); + LP_abutxo_set(autxo,butxo,qp); + if ( strcmp(qp->coinaddr,coin->smartaddr) != 0 ) + { + printf("bob is patching qp->coinaddr %s mismatch != %s\n",qp->coinaddr,coin->smartaddr); + strcpy(qp->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,qp->txid),qp->vout,bits256_str(str2,qp->txid2),qp->vout2,dstr(qp->satoshis),dstr(qp->destsatoshis)); + return(-66); + } + if ( (qprice= LP_quote_validate(autxo,butxo,qp,1)) <= SMALLVAL ) + { + printf("quote validate error %.0f\n",qprice); + return(-3); + } + if ( qprice < (price - 0.00000001) * 0.998 ) + { + printf(" quote price %.8f too low vs %.8f for %s/%s %.8f < %.8f\n",qprice,price,qp->srccoin,qp->destcoin,qprice,(price - 0.00000001) * 0.998); + return(-77); + } + return(qprice); +} + +struct LP_quoteinfo *LP_trades_gotrequest(void *ctx,struct LP_quoteinfo *qp,struct LP_quoteinfo *newqp,char *pairstr) +{ + double price,qprice,myprice,bestprice,range,bid,ask; struct iguana_info *coin; struct LP_utxoinfo A,B,*autxo,*butxo; cJSON *reqjson; char str[65]; struct LP_address_utxo *utxos[1000]; int32_t r,counter,max = (int32_t)(sizeof(utxos)/sizeof(*utxos)); + *newqp = *qp; + qp = newqp; + if ( (coin= LP_coinfind(qp->srccoin)) == 0 ) + return(0); + //printf("LP_trades_gotrequest %s/%s %.8f\n",qp->srccoin,qp->destcoin,LP_trades_bobprice(&bid,&ask,qp)); + if ( (myprice= LP_trades_bobprice(&bid,&ask,qp)) == 0. ) + return(0); + autxo = &A; + butxo = &B; + memset(autxo,0,sizeof(*autxo)); + memset(butxo,0,sizeof(*butxo)); + LP_abutxo_set(autxo,butxo,qp); + if ( bits256_nonz(qp->srchash) == 0 || bits256_cmp(qp->srchash,G.LP_mypub25519) == 0 ) + { + qprice = (double)qp->destsatoshis / (qp->satoshis - qp->txfee); + strcpy(qp->gui,G.gui); + strcpy(qp->coinaddr,coin->smartaddr); + strcpy(butxo->coinaddr,coin->smartaddr); + qp->srchash = G.LP_mypub25519; + memset(&qp->txid,0,sizeof(qp->txid)); + memset(&qp->txid2,0,sizeof(qp->txid2)); + qp->vout = qp->vout2 = -1; + } else return(0); + printf("LP_trades_gotrequest qprice %.8f vs myprice %.8f\n",qprice,myprice); + if ( qprice > myprice ) + { + r = (LP_rand() % 100); + range = (qprice - myprice); + price = myprice + (r * range) / 100.; + bestprice = LP_bob_competition(&counter,qp->aliceid,price,0); + printf("%llu >>>>>>> qprice %.8f r.%d range %.8f -> %.8f, bestprice %.8f counter.%d\n",(long long)qp->aliceid,qprice,r,range,price,bestprice,counter); + if ( counter > 3 && price >= bestprice+SMALLVAL ) // skip if late or bad price + return(0); + } else return(0); + //LP_RTmetrics_update(qp->srccoin,qp->destcoin); + if ( LP_RTmetrics_blacklisted(qp->desthash) >= 0 ) + { + printf("request from blacklisted %s, ignore\n",bits256_str(str,qp->desthash)); + return(0); + } + LP_address_utxo_reset(coin); + if ( (butxo= LP_address_myutxopair(butxo,1,utxos,max,LP_coinfind(qp->srccoin),qp->coinaddr,qp->txfee,dstr(qp->destsatoshis),price,qp->desttxfee)) != 0 ) + { + strcpy(qp->gui,G.gui); + strcpy(qp->coinaddr,coin->smartaddr); + qp->srchash = G.LP_mypub25519; + qp->txid = butxo->payment.txid; + qp->vout = butxo->payment.vout; + qp->txid2 = butxo->deposit.txid; + qp->vout2 = butxo->deposit.vout; + qp->satoshis = butxo->swap_satoshis;// + qp->txfee; + qp->quotetime = (uint32_t)time(NULL); + } + else + { + printf("cant find utxopair aliceid.%llu %s/%s %.8f -> relvol %.8f\n",(long long)qp->aliceid,qp->srccoin,qp->destcoin,dstr(LP_basesatoshis(dstr(qp->destsatoshis),price,qp->txfee,qp->desttxfee)),dstr(qp->destsatoshis)); + return(0); + } + if ( (qprice= LP_trades_pricevalidate(qp,coin,myprice)) < 0. ) + return(0); + if ( LP_allocated(qp->txid,qp->vout) == 0 && LP_allocated(qp->txid2,qp->vout2) == 0 ) + { + reqjson = LP_quotejson(qp); + LP_unavailableset(qp->txid,qp->vout,qp->timestamp + LP_RESERVETIME,qp->desthash); + LP_unavailableset(qp->txid2,qp->vout2,qp->timestamp + LP_RESERVETIME,qp->desthash); + if ( qp->quotetime == 0 ) + qp->quotetime = (uint32_t)time(NULL); + jaddnum(reqjson,"quotetime",qp->quotetime); + jaddnum(reqjson,"pending",qp->timestamp + LP_RESERVETIME); + jaddstr(reqjson,"method","reserved"); + bits256 zero; + memset(zero.bytes,0,sizeof(zero)); + LP_reserved_msg(1,qp->srccoin,qp->destcoin,zero,jprint(reqjson,0)); + if ( IAMLP == 0 ) { - if ( bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 && LP_alice_eligible() > 0 ) - { - printf("alice %s received RESERVED.(%s)\n",bits256_str(str,G.LP_mypub25519),jprint(argjson,0)); - if ( (retstr= LP_quotereceived(argjson)) != 0 ) - free(retstr); - LP_reserved(ctx,myipaddr,pubsock,&Q); - } - return(retval); + sleep(1); + LP_reserved_msg(1,qp->srccoin,qp->destcoin,qp->desthash,jprint(reqjson,0)); } - else if ( strcmp(method,"connected") == 0 ) + LP_reserved_msg(0,qp->srccoin,qp->destcoin,zero,jprint(reqjson,0)); + free_json(reqjson); + return(qp); + } else printf("request processing selected ineligible utxos?\n"); + return(0); +} + +struct LP_quoteinfo *LP_trades_gotreserved(void *ctx,struct LP_quoteinfo *qp,struct LP_quoteinfo *newqp) +{ + char *retstr; + char str[65]; printf("alice %s received RESERVED.(%llu) %.8f\n",bits256_str(str,G.LP_mypub25519),(long long)qp->aliceid,(double)qp->destsatoshis/(qp->satoshis+1)); + *newqp = *qp; + qp = newqp; + if ( LP_trades_alicevalidate(ctx,qp) > 0. ) + { + LP_aliceid(qp->tradeid,qp->aliceid,"reserved",0,0); + if ( (retstr= LP_quotereceived(qp)) != 0 ) + free(retstr); + return(qp); + } + return(0); +} + +struct LP_quoteinfo *LP_trades_gotconnect(void *ctx,struct LP_quoteinfo *qp,struct LP_quoteinfo *newqp,char *pairstr) +{ + double myprice,qprice,bid,ask; struct iguana_info *coin; + *newqp = *qp; + qp = newqp; + if ( (coin= LP_coinfind(qp->srccoin)) == 0 ) + return(0); + if ( (myprice= LP_trades_bobprice(&bid,&ask,qp)) == 0. ) + return(0); + if ( (qprice= LP_trades_pricevalidate(qp,coin,myprice)) < 0. ) + return(0); + if ( LP_reservation_check(qp->txid,qp->vout,qp->desthash) == 0 && LP_reservation_check(qp->txid2,qp->vout2,qp->desthash) == 0 ) + { + LP_connectstartbob(ctx,LP_mypubsock,qp->srccoin,qp->destcoin,qprice,qp); + return(qp); + } else printf("connect message from non-reserved (%llu)\n",(long long)qp->aliceid); + return(0); +} + +struct LP_quoteinfo *LP_trades_gotconnected(void *ctx,struct LP_quoteinfo *qp,struct LP_quoteinfo *newqp,char *pairstr) +{ + char *retstr; + char str[65]; printf("alice %s received CONNECTED.(%llu)\n",bits256_str(str,G.LP_mypub25519),(long long)qp->aliceid); + *newqp = *qp; + qp = newqp; + if ( LP_trades_alicevalidate(ctx,qp) > 0. ) + { + //printf("LP_trades_alicevalidate fine\n"); + LP_aliceid(qp->tradeid,qp->aliceid,"connected",0,0); + if ( (retstr= LP_connectedalice(qp,pairstr)) != 0 ) + free(retstr); + return(qp); + } + //printf("LP_trades_alicevalidate error\n"); + return(0); +} + +int32_t LP_trades_bestpricecheck(void *ctx,struct LP_trade *tp) +{ + double qprice; int32_t flag = 0; struct LP_quoteinfo Q; int64_t dynamictrust; char *retstr; struct LP_pubkey_info *pubp; + Q = tp->Q; + //printf("check bestprice %.8f vs new price %.8f\n",tp->bestprice,(double)Q.destsatoshis/Q.satoshis); + if ( Q.satoshis != 0 && (pubp= LP_pubkeyadd(Q.srchash)) != 0 )//(qprice= LP_trades_alicevalidate(ctx,&Q)) > 0. ) + { + qprice = (double)Q.destsatoshis / (Q.satoshis - Q.txfee); + LP_aliceid(Q.tradeid,tp->aliceid,"reserved",0,0); + if ( (retstr= LP_quotereceived(&Q)) != 0 ) + free(retstr); + //LP_trades_gotreserved(ctx,&Q,&tp->Qs[LP_RESERVED]); + dynamictrust = LP_dynamictrust(Q.othercredits,Q.srchash,LP_kmdvalue(Q.srccoin,Q.satoshis)); + if ( tp->bestprice == 0. ) + flag = 1; + else if ( qprice < tp->bestprice && pubp->slowresponse <= tp->bestresponse*1.05 ) + flag = 1; + else if ( qprice < tp->bestprice*1.01 && dynamictrust > tp->besttrust && pubp->slowresponse <= tp->bestresponse*1.1 ) + flag = 1; + else if ( qprice <= tp->bestprice && pubp->unconfcredits > tp->bestunconfcredits && pubp->slowresponse <= tp->bestresponse ) + flag = 1; + if ( flag != 0 ) { - if ( bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 ) - { - printf("alice %s received CONNECTED.(%s)\n",bits256_str(str,G.LP_mypub25519),jprint(argjson,0)); - if ( (retstr= LP_connectedalice(argjson)) != 0 ) - free(retstr); - } - return(retval); - } - if ( bits256_cmp(G.LP_mypub25519,Q.srchash) == 0 && bits256_cmp(G.LP_mypub25519,Q.desthash) != 0 ) + tp->Qs[LP_CONNECT] = tp->Q; + tp->bestprice = qprice; + tp->besttrust = dynamictrust; + tp->bestunconfcredits = pubp->unconfcredits; + tp->bestresponse = pubp->slowresponse; + printf("aliceid.%llu got new bestprice %.8f dynamictrust %.8f (unconf %.8f) slowresponse.%d\n",(long long)tp->aliceid,tp->bestprice,dstr(dynamictrust),dstr(tp->bestunconfcredits),tp->bestresponse); + return(qprice); + } //else printf("qprice %.8f dynamictrust %.8f not good enough\n",qprice,dstr(dynamictrust)); + } else printf("alice didnt validate\n"); + return(0); +} + +void LP_tradesloop(void *ctx) +{ + struct LP_trade *qtp,*tp,*tmp; struct LP_quoteinfo *qp,Q; uint32_t now; int32_t timeout,funcid,flag,nonz; struct iguana_info *coin; struct LP_pubkey_info *pubp; + strcpy(LP_tradesloop_stats.name,"LP_tradesloop"); + LP_tradesloop_stats.threshold = 10000; + sleep(5); + while ( 1 ) + { + LP_millistats_update(&LP_tradesloop_stats); + nonz = 0; + DL_FOREACH_SAFE(LP_tradesQ,qtp,tmp) { - if ( (coin= LP_coinfind(Q.srccoin)) == 0 || (price= LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin)) <= SMALLVAL || ask <= SMALLVAL ) - { - printf("this node has no price for %s/%s\n",Q.srccoin,Q.destcoin); - return(retval); - } - if ( coin->electrum != 0 ) - { - printf("electrum can only be for alice\n"); - return(retval); - } - if ( LP_aliceonly(Q.srccoin) > 0 ) + now = (uint32_t)time(NULL); + Q = qtp->Q; + funcid = qtp->funcid; +//printf("dequeue %p funcid.%d aliceid.%llu iambob.%d\n",qtp,funcid,(long long)qtp->aliceid,qtp->iambob); + portable_mutex_lock(&LP_tradesmutex); + DL_DELETE(LP_tradesQ,qtp); + HASH_FIND(hh,LP_trades,&qtp->aliceid,sizeof(qtp->aliceid),tp); + if ( tp == 0 ) { - printf("{\"error\":\"GAME can only be alice coin\"}\n"); - 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); + tp = qtp; + HASH_ADD(hh,LP_trades,aliceid,sizeof(tp->aliceid),tp); + portable_mutex_unlock(&LP_tradesmutex); + if ( tp->iambob != 0 && funcid == LP_REQUEST ) // bob maybe sends LP_RESERVED + { + if ( (qp= LP_trades_gotrequest(ctx,&Q,&tp->Qs[LP_REQUEST],tp->pairstr)) != 0 ) + tp->Qs[LP_RESERVED] = Q; + } + else if ( tp->iambob == 0 && funcid == LP_RESERVED ) // alice maybe sends LP_CONNECT + { + LP_trades_bestpricecheck(ctx,tp); + } + nonz++; + tp->firstprocessed = tp->lastprocessed = (uint32_t)time(NULL); +//printf("iambob.%d funcid.%d vs %d\n",tp->iambob,funcid,LP_REQUEST); + continue; } - price = ask; - autxo = &A; - butxo = &B; - memset(autxo,0,sizeof(*autxo)); - memset(butxo,0,sizeof(*butxo)); - LP_abutxo_set(autxo,butxo,&Q); - printf("utxopairfind\n"); - if ( (butxo= LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2)) == 0 ) - butxo = &B; - //LP_butxo_swapfields(butxo); - if ( strcmp(method,"request") == 0 ) + portable_mutex_unlock(&LP_tradesmutex); + tp->Q = qtp->Q; + if ( qtp->iambob == tp->iambob && qtp->pairstr[0] != 0 ) + safecopy(tp->pairstr,qtp->pairstr,sizeof(tp->pairstr)); +//printf("finished dequeue %p funcid.%d aliceid.%llu iambob.%d\n",qtp,funcid,(long long)qtp->aliceid,qtp->iambob); + free(qtp); + if ( tp->negotiationdone != 0 ) + continue; + flag = 0; + if ( qtp->iambob == tp->iambob ) { - char str[65],str2[65]; - printf("request.(%s)\n",jprint(argjson,0)); - if ( 1 )//LP_allocated(butxo->payment.txid,butxo->payment.vout) != 0 || LP_allocated(butxo->deposit.txid,butxo->deposit.vout) != 0 || (qprice= LP_quote_validate(autxo,butxo,&Q,1)) <= SMALLVAL ) + if ( tp->iambob == 0 ) { - LP_RTmetrics_update(Q.srccoin,Q.destcoin); - if ( LP_RTmetrics_blacklisted(Q.desthash) >= 0 ) + if ( funcid == LP_RESERVED ) { - printf("request from blacklisted %s, ignore\n",bits256_str(str,Q.desthash)); - return(retval); + if ( tp->connectsent == 0 ) + flag = LP_trades_bestpricecheck(ctx,tp); } - printf("butxo.%p replace path %p %s, %p %s, %.8f\n",butxo,LP_allocated(butxo->payment.txid,butxo->payment.vout),bits256_str(str,butxo->payment.txid),LP_allocated(butxo->deposit.txid,butxo->deposit.vout),bits256_str(str2,butxo->deposit.txid),LP_quote_validate(autxo,butxo,&Q,1)); - LP_listunspent_both(Q.srccoin,Q.coinaddr,0); - if ( (butxo= LP_address_utxopair(1,utxos,max,LP_coinfind(Q.srccoin),Q.coinaddr,Q.txfee,dstr(Q.destsatoshis),price,Q.desttxfee)) != 0 ) + else if ( funcid == LP_CONNECTED && tp->connectsent != 0 && tp->negotiationdone == 0 ) // alice all done { - Q.txid = butxo->payment.txid; - Q.vout = butxo->payment.vout; - Q.txid2 = butxo->deposit.txid; - Q.vout2 = butxo->deposit.vout; - printf("set butxo.%p %s/v%d %s/v%d %.8f %.8f -> bsat %.8f asat %.8f\n",butxo,bits256_str(str,butxo->payment.txid),butxo->payment.vout,bits256_str(str2,butxo->deposit.txid),butxo->deposit.vout,dstr(butxo->payment.value),dstr(butxo->deposit.value),dstr(butxo->S.satoshis),dstr(autxo->S.satoshis)); - } else printf("cant find utxopair\n"); - //LP_abutxo_set(0,butxo,&Q); - //LP_butxo_swapfields(butxo); + flag = 1; + tp->negotiationdone = now; + LP_trades_gotconnected(ctx,&tp->Q,&tp->Qs[LP_CONNECTED],tp->pairstr); + } } else { - printf("other path %p %p %.8f\n",LP_allocated(butxo->payment.txid,butxo->payment.vout),LP_allocated(butxo->deposit.txid,butxo->deposit.vout), LP_quote_validate(autxo,butxo,&Q,1)); - value = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid,Q.vout); - value2 = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid2,Q.vout2); - if ( (butxo= LP_utxoadd(1,coin->symbol,Q.txid,Q.vout,value,Q.txid2,Q.vout2,value2,Q.coinaddr,G.LP_mypub25519,G.gui,0)) == 0 ) - printf("couldnt create bob's utxopair\n"); - else printf("created butxo.(%s %s)\n",bits256_str(str,butxo->payment.txid),bits256_str(str2,butxo->deposit.txid)); + if ( funcid == LP_CONNECT && tp->negotiationdone == 0 ) // bob all cone + { + flag = 1; + tp->negotiationdone = now; + LP_trades_gotconnect(ctx,&tp->Q,&tp->Qs[LP_CONNECT],tp->pairstr); + } } - } - if ( butxo == 0 || butxo == &B ) - butxo = LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2); - if ( butxo == 0 || bits256_cmp(Q.txid,butxo->payment.txid) != 0 || bits256_cmp(Q.txid2,butxo->deposit.txid) != 0 ) - { - printf("%s %s null butxo.%p case\n",Q.srccoin,Q.coinaddr,butxo); - value = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid,Q.vout); - value2 = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid2,Q.vout2); - butxo = LP_utxoadd(1,Q.srccoin,Q.txid,Q.vout,value,Q.txid2,Q.vout2,value2,Q.coinaddr,Q.srchash,LP_gui,0); - } - char str[65],str2[65]; printf("butxo.%p (%s %s) TRADECOMMAND.(%s)\n",butxo,butxo!=0?bits256_str(str,butxo->payment.txid):"",butxo!=0?bits256_str(str2,butxo->deposit.txid):"",jprint(argjson,0)); - if ( butxo == 0 || bits256_nonz(butxo->payment.txid) == 0 || bits256_nonz(butxo->deposit.txid) == 0 || butxo->payment.vout < 0 || butxo->deposit.vout < 0 ) - { - 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 < (price - 0.00000001) * 0.9999 ) - { - printf("(%.8f %.8f) quote price %.8f too low vs %.8f for %s/%s\n",bid,ask,qprice,price,Q.srccoin,Q.destcoin); - return(-4); - } - 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 - { - if ( LP_isavailable(butxo) > 0 ) + if ( flag != 0 ) { - autxo->T.swappending = butxo->T.swappending = Q.timestamp + LP_RESERVETIME; - retjson = LP_quotejson(&Q); - butxo->S.otherpubkey = jbits256(argjson,"desthash"); - LP_unavailableset(butxo,butxo->S.otherpubkey); - 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,0); - butxo->T.lasttime = (uint32_t)time(NULL); - printf("return after queued RESERVED: set swappending.%u accept qprice %.8f, min %.8f\n(%s)\n",butxo->T.swappending,qprice,price,msg); - // LP_addsig - //msg2 = clonestr(msg); - LP_reserved_msg(Q.srccoin,Q.destcoin,butxo->S.otherpubkey,msg); - LP_broadcast_message(LP_mypubsock,Q.srccoin,Q.destcoin,Q.desthash,jprint(retjson,0)); - free_json(retjson); - return(retval); - } else printf("warning swappending.%u swap.%p\n",butxo->T.swappending,butxo->S.swap); + tp->lastprocessed = (uint32_t)time(NULL); + nonz++; + } } - else if ( strcmp(method,"connect") == 0 ) // bob + } + HASH_ITER(hh,LP_trades,tp,tmp) + { + if ( tp->negotiationdone != 0 ) + continue; + timeout = LP_AUTOTRADE_TIMEOUT; + if ( (coin= LP_coinfind(tp->Q.srccoin)) != 0 && coin->electrum != 0 ) + timeout += LP_AUTOTRADE_TIMEOUT * .5; + if ( (coin= LP_coinfind(tp->Q.destcoin)) != 0 && coin->electrum != 0 ) + timeout += LP_AUTOTRADE_TIMEOUT * .5; + now = (uint32_t)time(NULL); + if ( now > tp->lastprocessed ) { - retval = 4; - if ( butxo->S.swap == 0 && butxo->T.swappending != 0 ) + if ( tp->iambob == 0 ) { - // validate SPV alice - LP_connectstartbob(ctx,pubsock,butxo,argjson,Q.srccoin,Q.destcoin,qprice,&Q); - //LP_butxo_swapfields_set(butxo); - return(retval); + if ( tp->bestprice > 0. ) + { + if ( tp->connectsent == 0 ) + { + LP_Alicemaxprice = tp->bestprice; + LP_reserved(ctx,LP_myipaddr,LP_mypubsock,&tp->Qs[LP_CONNECT]); // send LP_CONNECT + tp->connectsent = now; + //printf("send LP_connect aliceid.%llu %.8f\n",(long long)tp->aliceid,tp->bestprice); + } + else if ( now < tp->firstprocessed+timeout && ((tp->firstprocessed - now) % 10) == 9 ) + { + LP_Alicemaxprice = tp->bestprice; + LP_reserved(ctx,LP_myipaddr,LP_mypubsock,&tp->Qs[LP_CONNECT]); // send LP_CONNECT + printf("repeat LP_connect aliceid.%llu %.8f\n",(long long)tp->aliceid,tp->bestprice); + if ( (pubp= LP_pubkeyfind(tp->Qs[LP_CONNECT].srchash)) != 0 ) + pubp->slowresponse++; + } + } + } + else if ( now > tp->firstprocessed+timeout*10 ) + { + //printf("purge swap aliceid.%llu\n",(long long)tp->aliceid); + portable_mutex_lock(&LP_tradesmutex); + HASH_DELETE(hh,LP_trades,tp); + portable_mutex_unlock(&LP_tradesmutex); + free(tp); } - else printf("pend.%u swap %p when connect came in (%s)\n",butxo->T.swappending,butxo->S.swap,jprint(argjson,0)); } - //LP_butxo_swapfields_set(butxo); } + if ( nonz == 0 ) + sleep(1); } - return(retval); } -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) +void LP_tradecommandQ(struct LP_quoteinfo *qp,char *pairstr,int32_t funcid) { - uint64_t basesatoshis; struct LP_utxoinfo *bestutxo; - basesatoshis = LP_basesatoshis(dstr(asatoshis),price,txfee,desttxfee); - if ( basesatoshis != 0 && (bestutxo= LP_address_utxopair(0,utxos,max,basecoin,coinaddr,txfee,dstr(basesatoshis)*price,price,desttxfee)) != 0 ) - { - bestutxo->pubkey = pubkey; - safecopy(bestutxo->gui,gui,sizeof(bestutxo->gui)); - *bestsatoshisp = basesatoshis; - *ordermatchpricep = price; - *bestdestsatoshisp = asatoshis; - return(bestutxo); - } - return(0); + struct LP_trade *qtp; uint64_t aliceid; int32_t iambob; + if ( funcid < 0 || funcid >= sizeof(qtp->Qs)/sizeof(*qtp->Qs) ) + return; + if ( funcid == LP_REQUEST || funcid == LP_CONNECT ) + iambob = 1; + else iambob = 0; + aliceid = qp->aliceid; + portable_mutex_lock(&LP_tradesmutex); + qtp = calloc(1,sizeof(*qtp)); + qtp->funcid = funcid; + qtp->iambob = iambob; + qtp->aliceid = aliceid; + qtp->newtime = (uint32_t)time(NULL); + qtp->Q = *qp; + if ( pairstr != 0 ) + safecopy(qtp->pairstr,pairstr,sizeof(qtp->pairstr)); + DL_APPEND(LP_tradesQ,qtp); + portable_mutex_unlock(&LP_tradesmutex); + //printf("queue.%d %p\n",funcid,qtp); } -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) +int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen) { - 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 || basecoin == 0 ) - return(0); - if ( basecoin->electrum == 0 ) - max = 1000; - else max = 20; - 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 ) + int32_t Qtrades = 1; + char *method,str[65]; int32_t num,DEXselector = 0; uint64_t aliceid; double qprice,bestprice,price,bid,ask; cJSON *proof; struct iguana_info *coin; struct LP_quoteinfo Q,Q2; int32_t counter,retval=-1; + if ( (method= jstr(argjson,"method")) != 0 && (strcmp(method,"reserved") == 0 ||strcmp(method,"connected") == 0 || strcmp(method,"request") == 0 || strcmp(method,"connect") == 0) ) { - if ( (orderbook= cJSON_Parse(obookstr)) != 0 ) + 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("%-4d (%-10u %10u) %12s id.%22llu %5s/%-5s %12.8f -> %11.8f price %11.8f | RT.%d %d\n",(uint32_t)time(NULL) % 3600,Q.R.requestid,Q.R.quoteid,method,(long long)Q.aliceid,Q.srccoin,Q.destcoin,dstr(Q.satoshis),dstr(Q.destsatoshis),(double)Q.destsatoshis/Q.satoshis,LP_RTcount,LP_swapscount); + retval = 1; + aliceid = j64bits(argjson,"aliceid"); + qprice = jdouble(argjson,"price"); + if ( strcmp(method,"reserved") == 0 ) { - if ( (rawasks= jarray(&numasks,orderbook,"asks")) != 0 ) + 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 ( 0 ) { - if ( (asks= LP_RTmetrics_sort(base,autxo->coin,rawasks,numasks,maxprice,dstr(autxo->S.satoshis))) == 0 ) - asks = rawasks; - for (i=0; i= 0 ) - continue; - //printf("[%d/%d] %s pubcmp %d price %.8f vs maxprice %.8f\n",i,numasks,jprint(item,0),bits256_cmp(pubkey,G.LP_mypub25519),price,maxprice); - if ( LP_pricevalid(price) > 0 && price <= maxprice ) + if (bits256_cmp(LP_Alicedestpubkey,Q.srchash) != 0 ) { - if ( bits256_nonz(destpubkey) == 0 ) - { - for (j=0; jtaddr,basecoin->pubtype,pubp->rmd160,sizeof(pubp->rmd160)); - asatoshis = autxo->S.satoshis; - LP_listunspent_query(base,coinaddr); - LP_listunspent_both(base,coinaddr,1); - for (j=0; jpubkey,gui)) != 0 ) - { - 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; - } - if ( j < maxiters ) - break; - } else printf("self trading or blacklisted peer\n"); - } - else + 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)); + } + } + if ( bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 ) + { + if ( Qtrades == 0 ) + { + if ( Q.quotetime > time(NULL)-20 && LP_alice_eligible(Q.quotetime) > 0 ) { - if ( i == 0 ) - printf("too expensive maxprice %.8f vs %.8f\n",maxprice,price); - break; + LP_trades_gotreserved(ctx,&Q,&Q2); + if ( LP_quotecmp(0,&Q,&LP_Alicequery) == 0 ) + LP_reserved(ctx,LP_myipaddr,LP_mypubsock,&Q); } - } - if ( asks != 0 && asks != rawasks ) - free_json(asks); + } else LP_tradecommandQ(&Q,jstr(argjson,"pair"),LP_RESERVED); } - free_json(orderbook); } - free(obookstr); + 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 ) + { + //printf("CONNECTED.(%s)\n",jprint(argjson,0)); + if ( (proof= jarray(&num,argjson,"proof")) != 0 && num > 0 ) + Q.othercredits = LP_instantdex_proofcheck(Q.coinaddr,proof,num); + if ( Qtrades == 0 ) + LP_trades_gotconnected(ctx,&Q,&Q2,jstr(argjson,"pair")); + else LP_tradecommandQ(&Q,jstr(argjson,"pair"),LP_CONNECTED); + } + } + price = LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin); + if ( (coin= LP_coinfind(Q.srccoin)) == 0 || coin->inactive != 0 ) + { + //printf("%s is not active\n",Q.srccoin); + return(retval); + } + if ( price <= SMALLVAL || ask <= SMALLVAL ) + { + //printf("this node has no price for %s/%s\n",Q.srccoin,Q.destcoin); + return(retval); + } + if ( LP_aliceonly(Q.srccoin) > 0 ) + { + printf("{\"error\":\"GAME can only be alice coin\"}\n"); + return(retval); + } + if ( strcmp(method,"request") == 0 ) + { + bestprice = LP_bob_competition(&counter,aliceid,qprice,-1); + if ( Qtrades == 0 ) + LP_trades_gotrequest(ctx,&Q,&Q2,jstr(argjson,"pair")); + else LP_tradecommandQ(&Q,jstr(argjson,"pair"),LP_REQUEST); + } + else if ( strcmp(method,"connect") == 0 ) + { + LP_bob_competition(&counter,aliceid,qprice,1000); + if ( bits256_cmp(G.LP_mypub25519,Q.srchash) == 0 && bits256_cmp(G.LP_mypub25519,Q.desthash) != 0 ) + { + printf("CONNECT.(%s)\n",jprint(argjson,0)); + if ( (proof= jarray(&num,argjson,"proof")) != 0 && num > 0 ) + Q.othercredits = LP_instantdex_proofcheck(Q.destaddr,proof,num); + if ( Qtrades == 0 ) + LP_trades_gotconnect(ctx,&Q,&Q2,jstr(argjson,"pair")); + else LP_tradecommandQ(&Q,jstr(argjson,"pair"),LP_CONNECT); + } + } + return(retval); } - free(utxos); - if ( *ordermatchpricep == 0. || *bestdestsatoshisp == 0 ) - return(0); - int32_t changed; - LP_mypriceset(&changed,autxo->coin,base,1. / *ordermatchpricep); - return(bestutxo); + return(retval); } -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) +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) { - uint64_t desttxfee,txfee; uint32_t lastnonce; int32_t i,maxiters,numpubs = 0; int64_t bestsatoshis=0,destsatoshis,bestdestsatoshis=0; struct iguana_info *basecoin,*relcoin; struct LP_utxoinfo *autxo,*bestutxo = 0; double qprice,ordermatchprice=0.; struct LP_quoteinfo Q; bits256 pubkeys[100]; + uint64_t desttxfee,txfee; uint32_t lastnonce; int64_t bestsatoshis=0,destsatoshis; struct iguana_info *basecoin,*relcoin; struct LP_utxoinfo *autxo,B,A; struct LP_quoteinfo Q; bits256 pubkeys[100]; struct LP_address_utxo *utxos[1000]; int32_t max=(int32_t)(sizeof(utxos)/sizeof(*utxos)); basecoin = LP_coinfind(base); relcoin = LP_coinfind(rel); if ( gui == 0 ) @@ -881,22 +1277,21 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel timeout = LP_AUTOTRADE_TIMEOUT; if ( basecoin->electrum != 0 && relcoin->electrum != 0 ) { - if ( timeout < 3*LP_AUTOTRADE_TIMEOUT ) - timeout = 3*LP_AUTOTRADE_TIMEOUT; + if ( timeout < 2*LP_AUTOTRADE_TIMEOUT ) + timeout = 2*LP_AUTOTRADE_TIMEOUT; } else if ( basecoin->electrum != 0 || relcoin->electrum != 0 ) { - if ( timeout < 2*LP_AUTOTRADE_TIMEOUT ) - timeout = 2*LP_AUTOTRADE_TIMEOUT; + 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 { - Alice_expiration = 0; - memset(&LP_Alicequery,0,sizeof(LP_Alicequery)); - LP_Alicemaxprice = 0.; - } + cJSON *retjson = cJSON_CreateObject(); + jaddstr(retjson,"error","only one pending request at a time"); + jaddnum(retjson,"wait",Alice_expiration-time(NULL)); + return(jprint(retjson,1)); + } else LP_alicequery_clear(); if ( maxprice <= 0. || relvolume <= 0. || LP_priceinfofind(base) == 0 || LP_priceinfofind(rel) == 0 ) return(clonestr("{\"error\":\"invalid parameter\"}")); if ( strcmp("BTC",rel) == 0 ) @@ -905,55 +1300,39 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel memset(pubkeys,0,sizeof(pubkeys)); LP_txfees(&txfee,&desttxfee,base,rel); destsatoshis = SATOSHIDEN * relvolume + 2*desttxfee; - if ( (autxo= LP_utxo_bestfit(rel,destsatoshis)) == 0 ) - return(clonestr("{\"error\":\"cant find alice utxo that is big enough\"}")); - if ( destsatoshis < autxo->S.satoshis ) - autxo->S.satoshis = destsatoshis; + memset(&A,0,sizeof(A)); + LP_address_utxo_reset(relcoin); + if ( (autxo= LP_address_myutxopair(&A,0,utxos,max,relcoin,relcoin->smartaddr,txfee,dstr(destsatoshis),maxprice,desttxfee)) == 0 ) + return(clonestr("{\"error\":\"cant find alice utxo that is close enough in size\"}")); + //printf("bestfit selected alice (%.8f %.8f) for %.8f sats %.8f\n",dstr(autxo->payment.value),dstr(autxo->fee.value),dstr(destsatoshis),dstr(autxo->swap_satoshis)); + if ( destsatoshis - desttxfee < autxo->swap_satoshis ) + { + destsatoshis -= desttxfee; + autxo->swap_satoshis = destsatoshis; + //printf("first path dest %.8f from %.8f\n",dstr(destsatoshis),dstr(autxo->swap_satoshis)); + } + else if ( autxo->swap_satoshis - desttxfee < destsatoshis ) + { + autxo->swap_satoshis -= desttxfee; + destsatoshis = autxo->swap_satoshis; + printf("second path dest %.8f from %.8f\n",dstr(destsatoshis),dstr(autxo->swap_satoshis)); + } if ( destsatoshis < (autxo->payment.value / LP_MINCLIENTVOL) || autxo->payment.value < desttxfee*LP_MINSIZE_TXFEEMULT ) { 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\"}")); } - LP_RTmetrics_update(base,rel); - while ( 1 ) - { - if ( (bestutxo= LP_buyutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,gui,pubkeys,numpubs,destpubkey)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) - { - 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\"}")); - } - return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration)); - } - return(clonestr("{\"error\":\"cant get here\"}")); + 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,G.LP_mypub25519,autxo->coinaddr) < 0 ) + return(clonestr("{\"error\":\"cant set ordermatch quote info\"}")); + int32_t changed; + LP_mypriceset(&changed,autxo->coin,base,1. / maxprice); + LP_mypriceset(&changed,base,autxo->coin,0.); + return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration,tradeid,destpubkey)); } diff --git a/iguana/exchanges/LP_peers.c b/iguana/exchanges/LP_peers.c index 33c776969..593046706 100644 --- a/iguana/exchanges/LP_peers.c +++ b/iguana/exchanges/LP_peers.c @@ -31,7 +31,7 @@ struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port) cJSON *LP_peerjson(struct LP_peerinfo *peer) { cJSON *item = cJSON_CreateObject(); - jaddstr(item,"ipaddr",peer->ipaddr); + jaddstr(item,"isLP",peer->ipaddr); jaddnum(item,"port",peer->port); if ( strcmp(peer->ipaddr,LP_myipaddr) == 0 ) { @@ -49,15 +49,15 @@ char *LP_peers() HASH_ITER(hh,LP_peerinfos,peer,tmp) { //if ( peer->errors < LP_MAXPEER_ERRORS ) + if ( peer->isLP != 0 ) jaddi(peersjson,LP_peerjson(peer)); } return(jprint(peersjson,1)); } -struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char *ipaddr,uint16_t port,uint16_t pushport,uint16_t subport,int32_t numpeers,int32_t numutxos,uint32_t sessionid) +struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char *ipaddr,uint16_t port,uint16_t pushport,uint16_t subport,int32_t isLP,uint32_t sessionid) { - uint32_t ipbits; int32_t valid,pushsock,subsock,timeout; char checkip[64],subaddr2[64],pushaddr[64],pushaddr2[64],subaddr[64]; struct LP_peerinfo *peer = 0; - printf("addpeer (%s:%u) pushport.%u subport.%u\n",ipaddr,port,pushport,subport); + uint32_t ipbits; int32_t valid,pushsock,subsock,timeout; char checkip[64],pushaddr[64],subaddr[64]; struct LP_peerinfo *peer = 0; #ifdef LP_STRICTPEERS if ( strncmp("5.9.253",ipaddr,strlen("5.9.253")) != 0 ) return(0); @@ -68,6 +68,8 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char { if ( (peer= LP_peerfind(ipbits,port)) != 0 ) { + if ( isLP != 0 ) + peer->isLP = isLP; /*if ( numpeers > peer->numpeers ) peer->numpeers = numpeers; if ( numutxos > peer->numutxos ) @@ -77,6 +79,7 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char } else { + //printf("addpeer (%s:%u) pushport.%u subport.%u\n",ipaddr,port,pushport,subport); peer = calloc(1,sizeof(*peer)); if ( strcmp(peer->ipaddr,LP_myipaddr) == 0 ) peer->sessionid = G.LP_sessionid; @@ -85,24 +88,25 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char strcpy(peer->ipaddr,ipaddr); //peer->profitmargin = profitmargin; peer->ipbits = ipbits; + peer->isLP = isLP; peer->port = port; peer->ip_port = ((uint64_t)port << 32) | ipbits; if ( pushport != 0 && subport != 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 ) { nanomsg_transportname(0,pushaddr,peer->ipaddr,pushport); - nanomsg_transportname2(0,pushaddr2,peer->ipaddr,pushport); + //nanomsg_transportname2(0,pushaddr2,peer->ipaddr,pushport); valid = 0; if ( nn_connect(pushsock,pushaddr) >= 0 ) valid++; - if ( nn_connect(pushsock,pushaddr2) >= 0 ) - valid++; + //if ( nn_connect(pushsock,pushaddr2) >= 0 ) + // valid++; if ( valid > 0 ) { timeout = 1; nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); //maxsize = 2 * 1024 * 1024; //nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDBUF,&maxsize,sizeof(maxsize)); - printf("connected to push.(%s %s) pushsock.%d valid.%d\n",pushaddr,pushaddr2,pushsock,valid); + printf("connected to push.(%s) pushsock.%d valid.%d | ",pushaddr,pushsock,valid); peer->connected = (uint32_t)time(NULL); peer->pushsock = pushsock; if ( (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 ) @@ -111,20 +115,20 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); nn_setsockopt(subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); nanomsg_transportname(0,subaddr,peer->ipaddr,subport); - nanomsg_transportname2(0,subaddr2,peer->ipaddr,subport); + //nanomsg_transportname2(0,subaddr2,peer->ipaddr,subport); valid = 0; if ( nn_connect(subsock,subaddr) >= 0 ) valid++; - if ( nn_connect(subsock,subaddr2) >= 0 ) - valid++; + //if ( nn_connect(subsock,subaddr2) >= 0 ) + // valid++; if ( valid > 0 ) { peer->subsock = subsock; - printf("connected to sub.(%s %s) subsock.%d valid.%d\n",subaddr,subaddr2,peer->subsock,valid); + printf("connected to sub.(%s) subsock.%d valid.%d\n",subaddr,peer->subsock,valid); } else { - printf("error connecting to subsock.%d (%s %s)\n",subsock,subaddr,subaddr2); + printf("error connecting to subsock.%d (%s)\n",subsock,subaddr); nn_close(subsock); subsock = -1; } @@ -134,26 +138,26 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char { nn_close(pushsock); pushsock = -1; - printf("error connecting to push.(%s %s)\n",pushaddr,pushaddr2); + printf("error connecting to push.(%s)\n",pushaddr); } } else printf("%s pushport.%u subport.%u pushsock.%d\n",ipaddr,pushport,subport,pushsock); if ( peer->pushsock >= 0 && peer->subsock >= 0 ) { - printf("add peer %s\n",peer->ipaddr); + //printf("add peer %s\n",peer->ipaddr); portable_mutex_lock(&LP_peermutex); HASH_ADD(hh,LP_peerinfos,ip_port,sizeof(peer->ip_port),peer); if ( mypeer != 0 ) { mypeer->numpeers++; - printf("_LPaddpeer %s -> numpeers.%d mypubsock.%d other.(%d %d)\n",ipaddr,mypeer->numpeers,mypubsock,numpeers,numutxos); + printf("_LPaddpeer %s -> numpeers.%d mypubsock.%d other.(%d)\n",ipaddr,mypeer->numpeers,mypubsock,isLP); } else peer->numpeers = 1; // will become mypeer portable_mutex_unlock(&LP_peermutex); if ( IAMLP != 0 && mypubsock >= 0 ) { - struct iguana_info *coin,*ctmp; bits256 zero; char busaddr[64]; - memset(zero.bytes,0,sizeof(zero)); + struct iguana_info *coin,*ctmp; char busaddr[64]; // + //memset(zero.bytes,0,sizeof(zero)); //LP_send(mypubsock,msg,(int32_t)strlen(msg)+1,1); - LP_reserved_msg("","",zero,jprint(LP_peerjson(peer),1)); + //LP_reserved_msg(0,"","",zero,jprint(LP_peerjson(peer),1)); if ( 0 ) { HASH_ITER(hh,LP_coins,coin,ctmp) @@ -202,67 +206,14 @@ int32_t LP_coinbus(uint16_t coin_busport) return(bussock); } -int32_t LP_peersparse(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now) -{ - struct LP_peerinfo *peer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - if ( (n= cJSON_GetArraySize(array)) > 0 ) - { - for (i=0; ilasttime = now; - if ( strcmp(argipaddr,destipaddr) == 0 && destport == argport && peer->numpeers != n ) - peer->numpeers = n; - } - } - } - } - free_json(array); - } - return(n); -} - -void LP_peersquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *myipaddr,uint16_t myport) +void LP_peer_recv(char *ipaddr,int32_t ismine) { - char *retstr; struct LP_peerinfo *peer,*tmp; bits256 zero; uint32_t now,flag = 0; - peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); - if ( (retstr= issue_LP_getpeers(destipaddr,destport,myipaddr,myport,mypeer!=0?mypeer->numpeers:0)) != 0 ) + struct LP_peerinfo *peer; + if ( (peer= LP_peerfind((uint32_t)calc_ipbits(ipaddr),RPC_port)) != 0 ) { - //printf("got.(%s)\n",retstr); - now = (uint32_t)time(NULL); - LP_peersparse(mypeer,mypubsock,destipaddr,destport,retstr,now); - free(retstr); - if ( IAMLP != 0 ) - { - HASH_ITER(hh,LP_peerinfos,peer,tmp) - { - if ( peer->lasttime != now ) - { - printf("{%s:%u}.%d ",peer->ipaddr,peer->port,peer->lasttime - now); - flag++; - memset(&zero,0,sizeof(zero)); - if ( (retstr= issue_LP_notify(destipaddr,destport,peer->ipaddr,peer->port,peer->numpeers,peer->sessionid,0,zero)) != 0 ) - free(retstr); - } - } - if ( flag != 0 ) - printf(" <- missing peers\n"); - } + peer->numrecv++; + //if ( ismine != 0 ) + peer->recvtime = (uint32_t)time(NULL); } } @@ -271,7 +222,8 @@ int32_t LP_numpeers() struct LP_peerinfo *peer,*tmp; int32_t numpeers = 0; HASH_ITER(hh,LP_peerinfos,peer,tmp) { - numpeers++; + if ( peer->isLP != 0 ) + numpeers++; } return(numpeers); } @@ -279,23 +231,51 @@ int32_t LP_numpeers() uint16_t LP_randpeer(char *destip) { struct LP_peerinfo *peer,*tmp; uint16_t port = 0; int32_t n,r,numpeers = 0; - HASH_ITER(hh,LP_peerinfos,peer,tmp) - { - numpeers++; - } + destip[0] = 0; + numpeers = LP_numpeers(); if ( numpeers > 0 ) { - r = rand() % numpeers; + r = LP_rand() % numpeers; n = 0; HASH_ITER(hh,LP_peerinfos,peer,tmp) { - if ( n++ == r ) + if ( peer->isLP != 0 ) { - strcpy(destip,peer->ipaddr); - port = peer->port; - break; + if ( n++ == r ) + { + strcpy(destip,peer->ipaddr); + port = peer->port; + break; + } } } } return(port); } + +uint16_t LP_rarestpeer(char *destip) +{ + struct LP_peerinfo *peer,*tmp,*rarest = 0; int32_t iter; uint32_t now; + now = (uint32_t)time(NULL); + destip[0] = 0; + for (iter=0; iter<2; iter++) + { + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + if ( strcmp(peer->ipaddr,LP_myipaddr) != 0 && iter == 0 && peer->recvtime < now-3600 ) + continue; + if ( peer->isLP != 0 ) + { + if ( rarest == 0 || peer->numrecv < rarest->numrecv ) + rarest = peer; + } + } + if ( rarest != 0 ) + break; + } + if ( rarest == 0 ) + LP_randpeer(destip); + else strcpy(destip,rarest->ipaddr); + return(rarest != 0 ? rarest->port : RPC_port); +} + diff --git a/iguana/exchanges/LP_portfolio.c b/iguana/exchanges/LP_portfolio.c index c67cda50a..9561bf1f3 100644 --- a/iguana/exchanges/LP_portfolio.c +++ b/iguana/exchanges/LP_portfolio.c @@ -18,9 +18,52 @@ // marketmaker // -char LP_portfolio_base[16],LP_portfolio_rel[16]; +struct LP_portfoliotrade { double metric; char buycoin[65],sellcoin[65]; }; + +struct LP_autoprice_ref +{ + char refbase[65],refrel[65],base[65],rel[65],fundbid[16],fundask[16]; + double margin,factor,offset; + cJSON *fundvalue; +} LP_autorefs[100]; + +int32_t LP_autoprices,num_LP_autorefs; +char LP_portfolio_base[128],LP_portfolio_rel[128]; double LP_portfolio_relvolume; +void LP_portfolio_reset() +{ + struct iguana_info *coin,*tmp; cJSON *fundjson; int32_t i; struct LP_autoprice_ref *ptr; + for (i=0; ifundvalue) != 0 ) + { + ptr->fundvalue = 0; + free_json(fundjson); + } + } + memset(LP_autorefs,0,sizeof(LP_autorefs)); + LP_autoprices = 0; + num_LP_autorefs = 0; + strcpy(LP_portfolio_base,""); + strcpy(LP_portfolio_rel,""); + LP_portfolio_relvolume = 0.; + HASH_ITER(hh,LP_coins,coin,tmp) + { + coin->maxamount = 0; + coin->perc = 0; + coin->goal = 0; + coin->goalperc = 0; + coin->relvolume = 0; + coin->force = 0; + coin->balanceA = 0; + coin->valuesumA = 0; + coin->balanceB = 0; + coin->valuesumB = 0; + } +} + cJSON *LP_portfolio_entry(struct iguana_info *coin) { cJSON *item = cJSON_CreateObject(); @@ -48,9 +91,10 @@ cJSON *LP_portfolio_entry(struct iguana_info *coin) uint64_t LP_balance(uint64_t *valuep,int32_t iambob,char *symbol,char *coinaddr) { - cJSON *array,*item; int32_t i,n; uint64_t valuesum,satoshisum,value; + cJSON *array,*item; bits256 zero; int32_t i,n; uint64_t valuesum,satoshisum,value; valuesum = satoshisum = 0; - if ( (array= LP_listunspent(symbol,coinaddr)) != 0 ) + memset(zero.bytes,0,sizeof(zero)); + if ( (array= LP_listunspent(symbol,coinaddr,zero,zero)) != 0 ) { if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) { @@ -63,7 +107,7 @@ uint64_t LP_balance(uint64_t *valuep,int32_t iambob,char *symbol,char *coinaddr) } free_json(array); } - if ( (array= LP_inventory(symbol)) != 0 ) + /*if ( (array= LP_inventory(symbol)) != 0 ) { if ( (n= cJSON_GetArraySize(array)) > 0 && is_cJSON_Array(array) != 0 ) { @@ -75,8 +119,9 @@ uint64_t LP_balance(uint64_t *valuep,int32_t iambob,char *symbol,char *coinaddr) } } free_json(array); - } + }*/ *valuep = valuesum; + satoshisum = valuesum; return(satoshisum); } @@ -94,7 +139,7 @@ char *LP_portfolio() if ( iter == 0 ) { //printf("from portfolio\n"); - LP_privkey_init(-1,coin,G.LP_privkey,G.LP_mypub25519); + //LP_privkey_init(-1,coin,G.LP_privkey,G.LP_mypub25519); coin->balanceA = LP_balance(&coin->valuesumA,0,coin->symbol,coin->smartaddr); coin->balanceB = LP_balance(&coin->valuesumB,1,coin->symbol,coin->smartaddr); if ( strcmp(coin->symbol,"KMD") != 0 ) @@ -199,13 +244,6 @@ char *LP_portfolio_goal(char *symbol,double goal) } else return(clonestr("{\"error\":\"cant set goal for inactive coin\"}")); } -int32_t LP_autoprices,num_LP_autorefs; - -struct LP_autoprice_ref -{ - char refbase[16],refrel[16],base[16],rel[16]; -} LP_autorefs[100]; - /*int32_t LP_autofill(char *base,char *rel,double maxprice,double totalrelvolume) { struct LP_priceinfo *basepp,*relpp; @@ -219,57 +257,19 @@ struct LP_autoprice_ref return(-1); }*/ -int32_t LP_autoprice(char *base,char *rel,cJSON *argjson) -{ - //curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"MNZ\",\"rel\":\"KMD\",\"offset\":0.1,\"refbase\":\"KMD\",\refrel\":\"BTC\",\"factor\":15000,\"margin\":0.01}" - struct LP_priceinfo *basepp,*relpp; int32_t i; char *refbase,*refrel; double minprice,margin,offset,factor; - //printf("autoprice.(%s %s) %s\n",base,rel,jprint(argjson,0)); - if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) - { - if ( jobj(argjson,"minprice") != 0 ) - minprice = jdouble(argjson,"minprice"); - else minprice = 0.; - margin = jdouble(argjson,"margin"); - offset = jdouble(argjson,"offset"); - factor = jdouble(argjson,"factor"); - basepp->minprices[relpp->ind] = minprice; - basepp->margins[relpp->ind] = margin; - basepp->offsets[relpp->ind] = offset; - basepp->factors[relpp->ind] = factor; - if ( (refbase= jstr(argjson,"refbase")) != 0 && (refrel= jstr(argjson,"refrel")) != 0 ) - { - for (i=0; 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. ) { offset = basepp->offsets[relpp->ind]; @@ -293,8 +293,6 @@ void LP_autopriceset(void *ctx,int32_t dir,struct LP_priceinfo *basepp,struct LP if ( dir > 0 ) newprice = (1. / price) * (1. + margin); else newprice = (price * (1. + margin)); - - //newprice = 1. / (price * (1. - margin)); if ( (minprice= basepp->minprices[relpp->ind]) == 0. || price >= minprice ) { LP_mypriceset(&changed,relpp->symbol,basepp->symbol,newprice); @@ -313,7 +311,7 @@ double LP_pricesparse(void *ctx,int32_t trexflag,char *retstr,struct LP_priceinf { //{"success":true,"message":"","result":[{"MarketName":"BTC-KMD","High":0.00040840,"Low":0.00034900,"Volume":328042.46061669,"Last":0.00037236,"BaseVolume":123.36439511,"TimeStamp":"2017-07-15T13:50:21.87","Bid":0.00035721,"Ask":0.00037069,"OpenBuyOrders":343,"OpenSellOrders":1690,"PrevDay":0.00040875,"Created":"2017-02-11T23:04:01.853"}, //{"TradePairId":4762,"Label":"WAVES/BTC","AskPrice":0.00099989,"BidPrice":0.00097350,"Low":0.00095000,"High":0.00108838,"Volume":6501.24403100,"LastPrice":0.00098028,"BuyVolume":1058994.86554882,"SellVolume":2067.87377158,"Change":-7.46,"Open":0.00105926,"Close":0.00098028,"BaseVolume":6.52057452,"BuyBaseVolume":2.33098660,"SellBaseVolume":1167.77655709}, - int32_t i,j,n,iter; double price,kmdbtc,bid,ask,nxtkmd=0.; struct LP_priceinfo *coinpp,*refpp; char symbol[16],*name,*refcoin; cJSON *retjson,*array,*item; + int32_t i,j,n,iter; double price,kmdbtc,bid,ask,nxtkmd=0.; struct LP_priceinfo *coinpp,*refpp; char symbol[65],*name,*refcoin; cJSON *retjson,*array,*item; if ( (retjson= cJSON_Parse(retstr)) != 0 ) { //printf("got.(%s)\n",retstr); @@ -404,7 +402,7 @@ double LP_pricesparse(void *ctx,int32_t trexflag,char *retstr,struct LP_priceinf void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp) { - char *retstr; cJSON *retjson,*bid,*ask; uint64_t bidsatoshis,asksatoshis; int32_t i; double nxtkmd,price; struct LP_priceinfo *kmdpp,*fiatpp,*nxtpp,*basepp,*relpp; + char *retstr,*base,*rel; cJSON *retjson,*bid,*ask,*fundjson,*argjson; uint64_t bidsatoshis,asksatoshis; int32_t i,changed; double nxtkmd,price,factor,offset,newprice,margin,price_btc,price_usd,kmd_btc,kmd_usd; struct LP_priceinfo *kmdpp,*fiatpp,*nxtpp,*basepp,*relpp; if ( (retstr= issue_curlt("https://bittrex.com/api/v1.1/public/getmarketsummaries",LP_HTTP_TIMEOUT*10)) == 0 ) { printf("trex error getting marketsummaries\n"); @@ -463,18 +461,157 @@ void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp) } } } + kmd_btc = LP_CMCbtcprice(&kmd_usd,"komodo"); for (i=0; i SMALLVAL ) + { + newprice = (1. / price) * (1. + margin); + LP_mypriceset(&changed,rel,base,newprice); + LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,rel,base,newprice); + //printf("fundbid %.8f margin %.8f newprice %.8f\n",price,margin,newprice); + } + if ( LP_autorefs[i].fundask[0] != 0 && (price= jdouble(fundjson,LP_autorefs[i].fundask)) > SMALLVAL ) + { + newprice = (price * (1. + margin)); + LP_mypriceset(&changed,base,rel,newprice); + LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,base,rel,newprice); + //printf("fundask %.8f margin %.8f newprice %.8f\n",price,margin,newprice); + } + } + free_json(fundjson); + } + } + else if ( strcmp(LP_autorefs[i].refrel,"coinmarketcap") == 0 ) + { + //printf("%s/%s for %s/%s margin %.8f\n",base,rel,LP_autorefs[i].refbase,LP_autorefs[i].refrel,margin); + if ( (price_btc= LP_CMCbtcprice(&price_usd,LP_autorefs[i].refbase)) > SMALLVAL ) + { + if ( strcmp(rel,"KMD") == 0 ) + price = kmd_btc / price_btc; + else if ( strcmp(rel,"BTC") == 0 ) + price = 1. / price_btc; + else continue; + if ( factor > 0. ) + price = (price * factor) + offset; + newprice = (price * (1. + margin)); + LP_mypriceset(&changed,rel,base,newprice); + LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,rel,base,newprice); + printf("price %.8f margin %.8f newprice %.8f %.8f\n",price,margin,newprice,(1. / price) * (1. + margin)); + newprice = (1. / price) * (1. + margin); + LP_mypriceset(&changed,base,rel,newprice); + LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,base,rel,newprice); + } + } + else + { + basepp = LP_priceinfofind(base); + relpp = LP_priceinfofind(rel); + if ( basepp != 0 && relpp != 0 ) + { + //printf("check ref-autoprice %s/%s %f %f\n",LP_autorefs[i].refbase,LP_autorefs[i].refrel,relpp->fixedprices[basepp->ind],basepp->fixedprices[relpp->ind]); + LP_autopriceset(ctx,1,basepp,relpp,0.,LP_autorefs[i].refbase,LP_autorefs[i].refrel); + } + } + } +} + +int32_t LP_autoprice(void *ctx,char *base,char *rel,cJSON *argjson) +{ + //curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"MNZ\",\"rel\":\"KMD\",\"offset\":0.1,\"refbase\":\"KMD\",\refrel\":\"BTC\",\"factor\":15000,\"margin\":0.01}" + struct LP_priceinfo *basepp,*relpp; int32_t i,retval = -1; char *fundvalue_bid,*fundvalue_ask,*refbase="",*refrel=""; double minprice,margin,offset,factor,fixedprice; cJSON *fundvalue; + //printf("autoprice.(%s %s) %s\n",base,rel,jprint(argjson,0)); + if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) + { + if ( jobj(argjson,"minprice") != 0 ) + minprice = jdouble(argjson,"minprice"); + else minprice = 0.; + margin = jdouble(argjson,"margin"); + offset = jdouble(argjson,"offset"); + factor = jdouble(argjson,"factor"); + fixedprice = jdouble(argjson,"fixed"); + basepp->fixedprices[relpp->ind] = fixedprice; + basepp->minprices[relpp->ind] = minprice; + basepp->margins[relpp->ind] = margin; + basepp->offsets[relpp->ind] = offset; + basepp->factors[relpp->ind] = factor; + refbase = jstr(argjson,"refbase"); + refrel = jstr(argjson,"refrel"); + fundvalue_bid = jstr(argjson,"fundvalue_bid"); + fundvalue_ask = jstr(argjson,"fundvalue_ask"); + if ( fundvalue_bid != 0 || fundvalue_ask != 0 || fixedprice > SMALLVAL || (refbase != 0 && refrel != 0) ) + { + if ( fixedprice > SMALLVAL ) + { + refbase = base; + refrel = rel; + } + for (i=0; isymbol,sell->symbol); requestid = quoteid = 0; LP_myprice(&bid,&ask,buy->symbol,sell->symbol); maxprice = ask; @@ -492,10 +629,11 @@ int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,str { if ( relvolume < dstr(LP_MIN_TXFEE) ) break; - if ( LP_utxo_bestfit(sell->symbol,SATOSHIDEN * relvolume) != 0 ) + if ( LP_address_myutxopair(&A,0,utxos,max,sell,sell->symbol,txfee,relvolume,maxprice,desttxfee) == 0 ) + //if ( LP_utxo_bestfit(sell->symbol,SATOSHIDEN * relvolume) != 0 ) { memset(zero.bytes,0,sizeof(zero)); - if ( (retstr2= LP_autobuy(ctx,"127.0.0.1",-1,buy->symbol,sell->symbol,maxprice,relvolume,60,24*3600,gui,LP_lastnonce+1,zero)) != 0 ) + if ( (retstr2= LP_autobuy(ctx,"127.0.0.1",-1,buy->symbol,sell->symbol,maxprice,relvolume,60,24*3600,gui,LP_lastnonce+1,zero,1)) != 0 ) { if ( (retjson2= cJSON_Parse(retstr2)) != 0 ) { @@ -516,7 +654,8 @@ int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,str for (i=0; i<100; i++) { relvolume *= .99; - if ( LP_utxo_bestfit(sell->symbol,SATOSHIDEN * relvolume) != 0 ) + if ( LP_address_myutxopair(&A,0,utxos,max,sell,sell->symbol,txfee,relvolume,maxprice,desttxfee) == 0 ) + //if ( LP_utxo_bestfit(sell->symbol,SATOSHIDEN * relvolume) != 0 ) { printf("i.%d relvolume %.8f from %.8f\n",i,relvolume,sell->relvolume); break; @@ -538,8 +677,6 @@ int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,str else return(-1); } -struct LP_portfoliotrade { double metric; char buycoin[16],sellcoin[16]; }; - int32_t LP_portfolio_order(struct LP_portfoliotrade *trades,int32_t max,cJSON *array) { int32_t i,j,m,n = 0; cJSON *item; struct LP_portfoliotrade coins[256]; @@ -586,15 +723,19 @@ int32_t LP_portfolio_order(struct LP_portfoliotrade *trades,int32_t max,cJSON *a return(n); } -void prices_loop(void *arg) +void prices_loop(void *ctx) { - char *retstr; cJSON *retjson,*array; char *buycoin,*sellcoin; struct iguana_info *buy,*sell; uint32_t requestid,quoteid; int32_t i,n,m; struct LP_portfoliotrade trades[256]; struct LP_priceinfo *btcpp; void *ctx = bitcoin_ctx(); + char *retstr; cJSON *retjson,*array; char *buycoin,*sellcoin; struct iguana_info *buy,*sell; uint32_t requestid,quoteid; int32_t i,n,m; struct LP_portfoliotrade trades[256]; struct LP_priceinfo *btcpp; + strcpy(prices_loop_stats.name,"prices_loop"); + prices_loop_stats.threshold = 91000.; while ( 1 ) { + //printf("prices loop autoprices.%d autorefs.%d\n",LP_autoprices,num_LP_autorefs); + LP_millistats_update(&prices_loop_stats); + LP_tradebots_timeslice(ctx); if ( (btcpp= LP_priceinfofind("BTC")) == 0 ) { - if ( arg == 0 ) - return; + printf("prices_loop BTC not in LP_priceinfofind\n"); sleep(60); continue; } @@ -628,9 +769,7 @@ void prices_loop(void *arg) } free(retstr); } - if ( arg == 0 ) - return; - sleep(60); + sleep(30); } } diff --git a/iguana/exchanges/LP_prices.c b/iguana/exchanges/LP_prices.c index 117667e28..51597b46c 100644 --- a/iguana/exchanges/LP_prices.c +++ b/iguana/exchanges/LP_prices.c @@ -18,23 +18,29 @@ // marketmaker // -struct LP_orderbookentry { bits256 pubkey; double price; uint64_t minsatoshis,maxsatoshis,depth; uint32_t timestamp; int32_t numutxos; char coinaddr[64]; }; +struct LP_orderbookentry +{ + bits256 pubkey; + double price; + int64_t avesatoshis,maxsatoshis,depth,dynamictrust; + uint32_t timestamp; + int32_t numutxos; + char coinaddr[64]; +}; struct LP_priceinfo { - char symbol[16]; + char symbol[68]; uint64_t coinbits; int32_t ind,pad; - double diagval,high[2],low[2],last[2],bid[2],ask[2]; //volume,btcvolume,prevday; // mostly bittrex info + double diagval,high[2],low[2],last[2],bid[2],ask[2]; double relvals[LP_MAXPRICEINFOS]; double myprices[LP_MAXPRICEINFOS]; double minprices[LP_MAXPRICEINFOS]; // autoprice + double fixedprices[LP_MAXPRICEINFOS]; // fixedprices double margins[LP_MAXPRICEINFOS]; double offsets[LP_MAXPRICEINFOS]; double factors[LP_MAXPRICEINFOS]; - //double maxprices[LP_MAXPRICEINFOS]; // autofill of base/rel - //double relvols[LP_MAXPRICEINFOS]; - FILE *fps[LP_MAXPRICEINFOS]; } LP_priceinfos[LP_MAXPRICEINFOS]; int32_t LP_numpriceinfos; @@ -47,6 +53,98 @@ struct LP_cacheinfo uint32_t timestamp; } *LP_cacheinfos; +void LP_priceinfos_clear() +{ + int32_t i; struct LP_priceinfo *pp; + for (i=0; imyprices,0,sizeof(pp->myprices)); + memset(pp->minprices,0,sizeof(pp->minprices)); + memset(pp->fixedprices,0,sizeof(pp->fixedprices)); + memset(pp->margins,0,sizeof(pp->margins)); + memset(pp->offsets,0,sizeof(pp->offsets)); + memset(pp->factors,0,sizeof(pp->factors)); + } +} + +float LP_pubkey_price(int32_t *numutxosp,int64_t *avesatoshisp,int64_t *maxsatoshisp,struct LP_pubkey_info *pubp,uint32_t baseind,uint32_t relind) +{ + struct LP_pubkey_quote *pq,*tmp; int32_t scale; int64_t scale64; + *numutxosp = 0; + *avesatoshisp = *maxsatoshisp = 0; + DL_FOREACH_SAFE(pubp->quotes,pq,tmp) + { + if ( baseind == pq->baseind && relind == pq->relind ) + { + if ( (scale= pq->scale) == 0 ) + pq->scale = scale = 6; + scale64 = 1; + while ( scale > 0 ) + { + scale64 *= 10; + scale--; + } + *numutxosp = pq->numutxos; + *avesatoshisp = pq->aveutxo * scale64; + *maxsatoshisp = pq->maxutxo * scale64; + return(pq->price); + } + } + return(0); +} + +void LP_pubkey_update(struct LP_pubkey_info *pubp,uint32_t baseind,uint32_t relind,float price,int64_t balance,char *utxocoin,int32_t numutxos,int64_t minutxo,int64_t maxutxo) +{ + struct LP_pubkey_quote *pq,*tmp; int64_t aveutxo,scale64,ave64,max64; int32_t scale; + DL_FOREACH_SAFE(pubp->quotes,pq,tmp) + { + if ( baseind == pq->baseind && relind == pq->relind ) + break; + pq = 0; + } + if ( pq == 0 ) + { + pq = calloc(1,sizeof(*pq)); + pq->baseind = baseind; + pq->relind = relind; + pq->scale = 6; // millions of SATOSHIS, ie. 0.01 + DL_APPEND(pubp->quotes,pq); // already serialized as only path is via stats_JSON() + //printf("create pubp quotes %d/%d\n",baseind,relind); + } + //printf("%d/%d price %.8f balance %.8f %s num.%d %.8f %.8f\n",baseind,relind,price,dstr(balance),utxocoin,numutxos,dstr(minutxo),dstr(maxutxo)); + pq->price = price; + if ( utxocoin != 0 && utxocoin[0] != 0 ) + { + if ( (scale= pq->scale) == 0 ) + pq->scale = scale = 6; + scale64 = 1; + while ( scale > 0 ) + { + scale64 *= 10; + scale--; + } + if ( numutxos >= 256 ) + pq->numutxos = 255; + else pq->numutxos = numutxos; + aveutxo = (balance + (scale64>>1)) / numutxos; + if ( (ave64= (aveutxo / scale64)) >= (1LL << 32) ) + ave64 = (1LL << 32) - 1; + max64 = ((maxutxo + (scale64>>1)) / scale64); + if ( max64 >= (1LL << 32) ) + max64 = (1LL << 32) - 1; + pq->aveutxo = (uint32_t)ave64; + pq->maxutxo = (uint32_t)max64; + if ( 0 ) + { + printf("price %.8f base.%s rel.%s utxocoin.%s balance %.8f numutxos.%u %u scale64 = %llu, ave %llu, ave32 %u (%llu) max32 %u (%llu)\n",price,LP_priceinfos[baseind].symbol,LP_priceinfos[relind].symbol,utxocoin,dstr(balance),numutxos,pq->numutxos,(long long)scale64,(long long)aveutxo,pq->aveutxo,(long long)pq->aveutxo * scale64,pq->maxutxo,(long long)pq->maxutxo * scale64); + int64_t avesatoshis,maxsatoshis; + price = LP_pubkey_price(&numutxos,&avesatoshis,&maxsatoshis,pubp,baseind,relind); + printf("checkprice %.8f numutxos.%d ave %.8f max %.8f\n",price,numutxos,dstr(avesatoshis),dstr(maxsatoshis)); + } + } +} + struct LP_priceinfo *LP_priceinfo(int32_t ind) { if ( ind < 0 || ind >= LP_MAXPRICEINFOS ) @@ -140,9 +238,9 @@ struct LP_cacheinfo *LP_cachefind(char *base,char *rel,bits256 txid,int32_t vout return(ptr); } -struct LP_pubkeyinfo *LP_pubkey_rmd160find(uint8_t rmd160[20]) +struct LP_pubkey_info *LP_pubkey_rmd160find(uint8_t rmd160[20]) { - struct LP_pubkeyinfo *pubp=0,*tmp; + struct LP_pubkey_info *pubp=0,*tmp; portable_mutex_lock(&LP_pubkeymutex); HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) { @@ -156,7 +254,7 @@ struct LP_pubkeyinfo *LP_pubkey_rmd160find(uint8_t rmd160[20]) struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr) { - uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkeyinfo *pubp; + uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkey_info *pubp; HASH_FIND(hh,coin->addresses,coinaddr,strlen(coinaddr),ap); if ( ap != 0 && bits256_nonz(ap->pubkey) == 0 ) { @@ -172,7 +270,7 @@ struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr) struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr) { - uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkeyinfo *pubp; + uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkey_info *pubp; ap = calloc(1,sizeof(*ap)); safecopy(ap->coinaddr,coinaddr,sizeof(ap->coinaddr)); bitcoin_addr2rmd160(coin->taddr,&addrtype,rmd160,coinaddr); @@ -186,18 +284,18 @@ struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr) return(ap); } -struct LP_pubkeyinfo *LP_pubkeyfind(bits256 pubkey) +struct LP_pubkey_info *LP_pubkeyfind(bits256 pubkey) { - struct LP_pubkeyinfo *pubp=0; + struct LP_pubkey_info *pubp=0; portable_mutex_lock(&LP_pubkeymutex); HASH_FIND(hh,LP_pubkeyinfos,&pubkey,sizeof(pubkey),pubp); portable_mutex_unlock(&LP_pubkeymutex); return(pubp); } -struct LP_pubkeyinfo *LP_pubkeyadd(bits256 pubkey) +struct LP_pubkey_info *LP_pubkeyadd(bits256 pubkey) { - char str[65]; struct LP_pubkeyinfo *pubp=0; + char str[65]; struct LP_pubkey_info *pubp=0; portable_mutex_lock(&LP_pubkeymutex); HASH_FIND(hh,LP_pubkeyinfos,&pubkey,sizeof(pubkey),pubp); if ( pubp == 0 ) @@ -220,7 +318,7 @@ struct LP_pubkeyinfo *LP_pubkeyadd(bits256 pubkey) int32_t LP_pubkey_istrusted(bits256 pubkey) { - struct LP_pubkeyinfo *pubp; + struct LP_pubkey_info *pubp; if ( (pubp= LP_pubkeyadd(pubkey)) != 0 ) return(pubp->istrusted != 0); return(0); @@ -228,7 +326,7 @@ int32_t LP_pubkey_istrusted(bits256 pubkey) char *LP_pubkey_trustset(bits256 pubkey,uint32_t trustval) { - struct LP_pubkeyinfo *pubp; + struct LP_pubkey_info *pubp; if ( (pubp= LP_pubkeyadd(pubkey)) != 0 ) { pubp->istrusted = trustval; @@ -239,7 +337,7 @@ char *LP_pubkey_trustset(bits256 pubkey,uint32_t trustval) char *LP_pubkey_trusted() { - struct LP_pubkeyinfo *pubp,*tmp; cJSON *array = cJSON_CreateArray(); + struct LP_pubkey_info *pubp,*tmp; cJSON *array = cJSON_CreateArray(); HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) { if ( pubp->istrusted != 0 ) @@ -248,10 +346,10 @@ char *LP_pubkey_trusted() return(jprint(array,1)); } -uint64_t LP_unspents_metric(struct iguana_info *coin,char *coinaddr) +int64_t LP_unspents_metric(struct iguana_info *coin,char *coinaddr) { - cJSON *array,*item; int32_t i,n; uint64_t metric=0,total; - LP_listunspent_both(coin->symbol,coinaddr,0); + cJSON *array,*item; int32_t i,n; int64_t metric=0,total; + //LP_listunspent_both(coin->symbol,coinaddr,0); if ( (array= LP_address_utxos(coin,coinaddr,1)) != 0 ) { total = 0; @@ -264,13 +362,14 @@ uint64_t LP_unspents_metric(struct iguana_info *coin,char *coinaddr) } } metric = _LP_unspents_metric(total,n); + free_json(array); } return(metric); } -cJSON *LP_pubkeyjson(struct LP_pubkeyinfo *pubp) +cJSON *LP_pubkeyjson(struct LP_pubkey_info *pubp) { - int32_t baseid,relid; char *base,hexstr[67],hexstr2[67],sigstr[256]; double price; cJSON *item,*array,*obj; + int32_t baseid,relid,numutxos; int64_t avesatoshis,maxsatoshis; char *base,hexstr[67],hexstr2[67],sigstr[256]; double price; cJSON *item,*array,*obj; obj = cJSON_CreateObject(); array = cJSON_CreateArray(); for (baseid=0; baseidmatrix[baseid][relid]; + price = LP_pubkey_price(&numutxos,&avesatoshis,&maxsatoshis,pubp,baseid,relid);//pubp->matrix[baseid][relid]; if ( LP_pricevalid(price) > 0 ) { item = cJSON_CreateArray(); @@ -305,7 +404,7 @@ cJSON *LP_pubkeyjson(struct LP_pubkeyinfo *pubp) char *LP_prices() { - struct LP_pubkeyinfo *pubp,*tmp; cJSON *array = cJSON_CreateArray(); + struct LP_pubkey_info *pubp,*tmp; cJSON *array = cJSON_CreateArray(); HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) { jaddi(array,LP_pubkeyjson(pubp)); @@ -313,79 +412,6 @@ char *LP_prices() return(jprint(array,1)); } -void LP_prices_parse(struct LP_peerinfo *peer,cJSON *obj) -{ - struct LP_pubkeyinfo *pubp; struct LP_priceinfo *basepp,*relpp; uint32_t timestamp; bits256 pubkey; cJSON *asks,*item; uint8_t rmd160[20]; int32_t i,n,relid,mismatch; char *base,*rel,*hexstr; double askprice; uint32_t now; - now = (uint32_t)time(NULL); - pubkey = jbits256(obj,"pubkey"); - if ( bits256_nonz(pubkey) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 ) - { - if ( (hexstr= jstr(obj,"rmd160")) != 0 && strlen(hexstr) == 2*sizeof(rmd160) ) - decode_hex(rmd160,sizeof(rmd160),hexstr); - if ( memcmp(pubp->rmd160,rmd160,sizeof(rmd160)) != 0 ) - mismatch = 1; - else mismatch = 0; - if ( bits256_cmp(pubkey,G.LP_mypub25519) == 0 && mismatch == 0 ) - peer->needping = 0; - LP_pubkey_sigcheck(pubp,obj); - timestamp = juint(obj,"timestamp"); - if ( timestamp > now ) - timestamp = now; - if ( timestamp >= pubp->timestamp && (asks= jarray(&n,obj,"asks")) != 0 ) - { - for (i=0; i 0 ) - { - if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 ) - { - //char str[65]; printf("gotprice %s %s/%s (%d/%d) %.8f\n",bits256_str(str,pubkey),base,rel,basepp->ind,relid,askprice); - pubp->matrix[basepp->ind][relid] = askprice; - pubp->timestamps[basepp->ind][relid] = timestamp; - if ( (relpp= LP_priceinfofind(rel)) != 0 ) - { - dxblend(&basepp->relvals[relpp->ind],askprice,0.9); - dxblend(&relpp->relvals[basepp->ind],1. / askprice,0.9); - } - } - } - } - } - } -} - -void LP_peer_pricesquery(struct LP_peerinfo *peer) -{ - char *retstr; cJSON *array; int32_t i,n; - if ( strcmp(peer->ipaddr,LP_myipaddr) == 0 ) - return; - peer->needping = (uint32_t)time(NULL); - if ( (retstr= issue_LP_getprices(peer->ipaddr,peer->port)) != 0 ) - { -#ifdef FROM_JS - printf("%s\n",retstr); -#endif - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - if ( is_cJSON_Array(array) && (n= cJSON_GetArraySize(array)) > 0 ) - { - for (i=0; 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) { struct LP_cacheinfo *ptr; @@ -393,14 +419,14 @@ double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,i { if ( qp != 0 ) (*qp) = ptr->Q; - if ( ptr->price == 0. && ptr->Q.satoshis != 0 ) + if ( ptr->price == 0. && ptr->Q.satoshis > ptr->Q.txfee ) { - ptr->price = (double)ptr->Q.destsatoshis / ptr->Q.satoshis; + ptr->price = (double)ptr->Q.destsatoshis / (ptr->Q.satoshis - ptr->Q.txfee); if ( LP_pricevalid(ptr->price) <= 0 ) ptr->price = 0.; printf("LP_pricecache: set %s/%s ptr->price %.8f\n",base,rel,ptr->price); } - printf(">>>>>>>>>> found %s/%s %.8f\n",base,rel,ptr->price); + //printf(">>>>>>>>>> found %s/%s %.8f\n",base,rel,ptr->price); return(ptr->price); } //char str[65]; printf("cachemiss %s/%s %s/v%d\n",base,rel,bits256_str(str,txid),vout); @@ -414,10 +440,10 @@ void LP_priceinfoupdate(char *base,char *rel,double price) { if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) { - //dxblend(&basepp->relvals[relpp->ind],price,0.9); - //dxblend(&relpp->relvals[basepp->ind],1. / price,0.9); - basepp->relvals[relpp->ind] = price; - relpp->relvals[basepp->ind] = 1. / price; + dxblend(&basepp->relvals[relpp->ind],price,0.9); + dxblend(&relpp->relvals[basepp->ind],1. / price,0.9); + //basepp->relvals[relpp->ind] = price; + //relpp->relvals[basepp->ind] = 1. / price; } } } @@ -483,21 +509,30 @@ char *LP_myprices() int32_t LP_mypriceset(int32_t *changedp,char *base,char *rel,double price) { - struct LP_priceinfo *basepp,*relpp; struct LP_pubkeyinfo *pubp; + struct LP_priceinfo *basepp,*relpp; struct LP_pubkey_info *pubp; *changedp = 0; if ( base != 0 && rel != 0 && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) { - if ( fabs(basepp->myprices[relpp->ind] - price)/price > 0.001 ) + if ( price == 0. || fabs(basepp->myprices[relpp->ind] - price)/price > 0.001 ) *changedp = 1; basepp->myprices[relpp->ind] = price; // ask + if ( price == 0. ) + { + relpp->minprices[basepp->ind] = 0.; + relpp->fixedprices[basepp->ind] = 0.; + relpp->margins[basepp->ind] = 0.; + relpp->offsets[basepp->ind] = 0.; + relpp->factors[basepp->ind] = 0.; + } //printf("LP_mypriceset base.%s rel.%s <- price %.8f\n",base,rel,price); //relpp->myprices[basepp->ind] = (1. / price); // bid if ( (pubp= LP_pubkeyadd(G.LP_mypub25519)) != 0 ) { pubp->timestamp = (uint32_t)time(NULL); - pubp->matrix[basepp->ind][relpp->ind] = price; - pubp->timestamps[basepp->ind][relpp->ind] = pubp->timestamp; + LP_pubkey_update(pubp,basepp->ind,relpp->ind,price,0,0,0,0,0); + //pubp->matrix[basepp->ind][relpp->ind] = price; + //pubp->timestamps[basepp->ind][relpp->ind] = pubp->timestamp; //pubp->matrix[relpp->ind][basepp->ind] = (1. / price); } return(0); @@ -672,16 +707,17 @@ cJSON *LP_orderbookjson(char *symbol,struct LP_orderbookentry *op) jaddstr(item,"address",op->coinaddr); jaddnum(item,"price",op->price); jaddnum(item,"numutxos",op->numutxos); - jaddnum(item,"minvolume",dstr(op->minsatoshis)*0.8); + jaddnum(item,"avevolume",dstr(op->avesatoshis)*0.8); jaddnum(item,"maxvolume",dstr(op->maxsatoshis)*0.8); jaddnum(item,"depth",dstr(op->depth)*0.8); jaddbits256(item,"pubkey",op->pubkey); jaddnum(item,"age",time(NULL)-op->timestamp); + jaddnum(item,"zcredits",dstr(op->dynamictrust)); } return(item); } -struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,double price,int32_t numutxos,uint64_t minsatoshis,uint64_t maxsatoshis,bits256 pubkey,uint32_t timestamp,uint64_t balance) +struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,double price,int32_t numutxos,int64_t avesatoshis,int64_t maxsatoshis,bits256 pubkey,uint32_t timestamp,int64_t balance,int64_t dynamictrust) { struct LP_orderbookentry *op; if ( (op= calloc(1,sizeof(*op))) != 0 ) @@ -689,38 +725,38 @@ struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,d safecopy(op->coinaddr,address,sizeof(op->coinaddr)); op->price = price; op->numutxos = numutxos; - op->minsatoshis = minsatoshis; + op->avesatoshis = avesatoshis; op->maxsatoshis = maxsatoshis; op->pubkey = pubkey; op->timestamp = timestamp; op->depth = balance; + op->dynamictrust = dynamictrust; } return(op); } void LP_pubkeys_query() { - static uint32_t lasttime; - uint8_t zeroes[20]; bits256 zero; cJSON *reqjson; struct LP_pubkeyinfo *pubp=0,*tmp; + uint8_t zeroes[20]; bits256 zero; cJSON *reqjson; struct LP_pubkey_info *pubp=0,*tmp; memset(zero.bytes,0,sizeof(zero)); memset(zeroes,0,sizeof(zeroes)); HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) { - if ( memcmp(zeroes,pubp->rmd160,sizeof(pubp->rmd160)) == 0 && time(NULL) > lasttime+30 ) + if ( memcmp(zeroes,pubp->rmd160,sizeof(pubp->rmd160)) == 0 && time(NULL) > pubp->lasttime+60 ) { - lasttime = (uint32_t)time(NULL); + pubp->lasttime = (uint32_t)time(NULL); reqjson = cJSON_CreateObject(); jaddstr(reqjson,"method","wantnotify"); jaddbits256(reqjson,"pub",pubp->pubkey); //printf("LP_pubkeys_query %s\n",jprint(reqjson,0)); - LP_reserved_msg("","",zero,jprint(reqjson,1)); + LP_reserved_msg(0,"","",zero,jprint(reqjson,1)); } } } int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *rel,struct LP_orderbookentry *(**arrayp),int32_t num,int32_t cachednum,int32_t duration) { - char coinaddr[64]; uint8_t zeroes[20]; struct LP_pubkeyinfo *pubp=0,*tmp; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; struct LP_address *ap; struct iguana_info *basecoin; uint32_t oldest; double price; int32_t baseid,relid,n; uint64_t minsatoshis,maxsatoshis,balance; + char coinaddr[64]; uint8_t zeroes[20]; struct LP_pubkey_info *pubp=0,*tmp; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; struct LP_address *ap; struct iguana_info *basecoin; uint32_t oldest; double price; int32_t baseid,relid,n; int64_t maxsatoshis,balance,avesatoshis; if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 ) baseid = basepp->ind; else return(num); @@ -739,23 +775,23 @@ int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char * if ( pubp->timestamp < oldest ) continue; bitcoin_address(coinaddr,basecoin->taddr,basecoin->pubtype,pubp->rmd160,sizeof(pubp->rmd160)); - minsatoshis = maxsatoshis = n = 0; + avesatoshis = maxsatoshis = n = 0; ap = 0; - if ( (price= pubp->matrix[baseid][relid]) > SMALLVAL && pubp->timestamps[baseid][relid] >= oldest ) + if ( (price= LP_pubkey_price(&n,&avesatoshis,&maxsatoshis,pubp,baseid,relid)) > SMALLVAL ) //pubp->matrix[baseid][relid]) > SMALLVAL )//&& pubp->timestamps[baseid][relid] >= oldest ) { - balance = 0; - if ( (ap= LP_addressfind(basecoin,coinaddr)) != 0 ) + balance = avesatoshis * n; + //if ( (ap= LP_addressfind(basecoin,coinaddr)) != 0 ) { - n = LP_address_minmax(&balance,&minsatoshis,&maxsatoshis,ap); + //n = LP_address_minmax(&balance,&minsatoshis,&maxsatoshis,ap); if ( polarity > 0 ) { balance *= price; - minsatoshis *= price; + avesatoshis *= price; maxsatoshis *= price; } //printf("%s/%s %s n.%d ap->n.%d %.8f\n",base,rel,coinaddr,n,ap->n,dstr(ap->total)); } - if ( (op= LP_orderbookentry(coinaddr,base,rel,polarity > 0 ? price : 1./price,n,minsatoshis,maxsatoshis,pubp->pubkey,pubp->timestamps[baseid][relid],balance)) != 0 ) + if ( (op= LP_orderbookentry(coinaddr,base,rel,polarity > 0 ? price : 1./price,n,avesatoshis,maxsatoshis,pubp->pubkey,pubp->timestamp,balance,pubp->dynamictrust)) != 0 ) { *arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1)); (*arrayp)[num++] = op; @@ -768,7 +804,7 @@ int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char * char *LP_orderbook(char *base,char *rel,int32_t duration) { - uint32_t now,i; uint64_t depth; struct LP_priceinfo *basepp=0,*relpp=0; struct LP_orderbookentry **bids = 0,**asks = 0; cJSON *retjson,*array; struct iguana_info *basecoin,*relcoin; int32_t n,numbids=0,numasks=0,cachenumbids,cachenumasks,baseid,relid,suppress_prefetch=0; + uint32_t now,i; int64_t depth,askdepth=0,biddepth=0; struct LP_priceinfo *basepp=0,*relpp=0; struct LP_orderbookentry **bids = 0,**asks = 0; cJSON *retjson,*array; struct iguana_info *basecoin,*relcoin; int32_t n,numbids=0,numasks=0,cachenumbids,cachenumasks,baseid,relid,suppress_prefetch=0; basecoin = LP_coinfind(base); relcoin = LP_coinfind(rel); if ( basecoin == 0 || relcoin == 0 ) @@ -815,16 +851,26 @@ char *LP_orderbook(char *base,char *rel,int32_t duration) } for (i=n=0; idepth; jaddi(array,LP_orderbookjson(rel,bids[i])); - if ( suppress_prefetch == 0 && n < 7 && bids[i]->numutxos == 0 ) + if ( suppress_prefetch == 0 && n < 3 && bids[i]->numutxos == 0 ) { //printf("bid ping %s %s\n",rel,bids[i]->coinaddr); LP_address(relcoin,bids[i]->coinaddr); - if ( relcoin->electrum == 0 ) + /*if ( 0 && relcoin->electrum == 0 ) + { LP_listunspent_issue(rel,bids[i]->coinaddr,0); - LP_listunspent_query(rel,bids[i]->coinaddr); + //else if ( (tmpjson= LP_listunspent(rel,bids[i]->coinaddr)) != 0 ) + // free_json(tmpjson); + LP_listunspent_query(rel,bids[i]->coinaddr); + }*/ n++; } + if ( i == 0 ) + { + LP_priceinfoupdate(rel,base,1. / bids[i]->price); + //printf("update %s/%s %.8f [%.8f]\n",rel,base,1./bids[i]->price,bids[i]->price); + } free(bids[i]); bids[i] = 0; } @@ -832,19 +878,30 @@ char *LP_orderbook(char *base,char *rel,int32_t duration) relcoin->lastmonitor -= 3600; jadd(retjson,"bids",array); jaddnum(retjson,"numbids",numbids); + jaddnum(retjson,"biddepth",dstr(biddepth)); array = cJSON_CreateArray(); for (i=n=0; idepth; jaddi(array,LP_orderbookjson(base,asks[i])); - if ( suppress_prefetch == 0 && n < 7 && asks[i]->numutxos == 0 ) + if ( suppress_prefetch == 0 && n < 3 && asks[i]->numutxos == 0 ) { //printf("ask ping %s %s\n",base,asks[i]->coinaddr); LP_address(basecoin,asks[i]->coinaddr); - if ( basecoin->electrum == 0 ) + /*if ( 0 && basecoin->electrum == 0 ) + { LP_listunspent_issue(base,asks[i]->coinaddr,0); - LP_listunspent_query(base,asks[i]->coinaddr); + //else if ( (tmpjson= LP_listunspent(base,asks[i]->coinaddr)) != 0 ) + // free_json(tmpjson); + LP_listunspent_query(base,asks[i]->coinaddr); + }*/ n++; } + if ( i == 0 ) + { + LP_priceinfoupdate(base,rel,asks[i]->price); + //printf("update %s/%s %.8f [%.8f]\n",base,rel,asks[i]->price,1./asks[i]->price); + } free(asks[i]); asks[i] = 0; } @@ -852,6 +909,7 @@ char *LP_orderbook(char *base,char *rel,int32_t duration) basecoin->lastmonitor -= 3600; jadd(retjson,"asks",array); jaddnum(retjson,"numasks",numasks); + jaddnum(retjson,"askdepth",dstr(askdepth)); jaddstr(retjson,"base",base); jaddstr(retjson,"rel",rel); jaddnum(retjson,"timestamp",now); @@ -862,41 +920,32 @@ char *LP_orderbook(char *base,char *rel,int32_t duration) return(jprint(retjson,1)); } -uint64_t LP_KMDvalue(struct iguana_info *coin,uint64_t balance) +int64_t LP_KMDvalue(struct iguana_info *coin,int64_t balance) { - cJSON *bids,*asks,*orderbook,*item; double bid=0,ask=0,price = 0.; int32_t numasks,numbids; char *retstr; uint64_t KMDvalue=0; + double price = 0.; int64_t KMDvalue=0; if ( balance != 0 ) { if ( strcmp(coin->symbol,"KMD") == 0 ) KMDvalue = balance; - else if ( (retstr= LP_orderbook(coin->symbol,"KMD",-1)) != 0 ) + else { - if ( (orderbook= cJSON_Parse(retstr)) != 0 ) - { - if ( (asks= jarray(&numasks,orderbook,"asks")) != 0 && numasks > 0 ) - { - item = jitem(asks,0); - price = ask = jdouble(item,"price"); - //printf("%s/%s ask %.8f\n",coin->symbol,"KMD",ask); - } - if ( (bids= jarray(&numbids,orderbook,"bids")) != 0 && numbids > 0 ) - { - item = jitem(asks,0); - bid = jdouble(item,"price"); - if ( price == 0. ) - price = bid; - else price = (bid + ask) * 0.5; - //printf("%s/%s bid %.8f ask %.8f price %.8f\n",coin->symbol,"KMD",bid,ask,price); - } + if ( (price= LP_price(coin->symbol,"KMD")) > SMALLVAL ) KMDvalue = price * balance; - free_json(orderbook); - } - free(retstr); } } return(KMDvalue); } +int64_t LP_kmdvalue(char *symbol,int64_t satoshis) +{ + struct iguana_info *coin; int64_t kmdvalue = 0; + if ( (coin= LP_coinfind(symbol)) != 0 ) + kmdvalue = LP_KMDvalue(coin,satoshis); + if ( kmdvalue == 0 ) + kmdvalue = satoshis; + return(kmdvalue); +} + void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32]) { LP_priceinfoupdate(base,rel,price); @@ -921,7 +970,7 @@ void LP_priceitemadd(cJSON *retarray,uint32_t timestamp,double avebid,double ave cJSON *LP_pricearray(char *base,char *rel,uint32_t firsttime,uint32_t lasttime,int32_t timescale) { - cJSON *retarray; char askfname[1024],bidfname[1024]; uint64_t bidprice64,askprice64; uint32_t bidnow,asknow,bidi,aski,lastbidi,lastaski; int32_t numbids,numasks; double bidemit,askemit,bidsum,asksum,bid,ask,highbid,lowbid,highask,lowask,bidemit2,askemit2; FILE *askfp=0,*bidfp=0; + cJSON *retarray; char askfname[1024],bidfname[1024]; int64_t bidprice64,askprice64; uint32_t bidnow,asknow,bidi,aski,lastbidi,lastaski; int32_t numbids,numasks; double bidemit,askemit,bidsum,asksum,bid,ask,highbid,lowbid,highask,lowask,bidemit2,askemit2; FILE *askfp=0,*bidfp=0; if ( timescale <= 0 ) timescale = 60; if ( lasttime == 0 ) @@ -1030,16 +1079,16 @@ cJSON *LP_pricearray(char *base,char *rel,uint32_t firsttime,uint32_t lasttime,i return(retarray); } -void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price) +void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price,char *utxocoin,int32_t numrelutxos,int64_t balance,int64_t minutxo,int64_t maxutxo,int64_t unconfcredits) { - struct LP_priceinfo *basepp,*relpp; uint32_t now; uint64_t price64; struct LP_pubkeyinfo *pubp; char str[65],fname[512]; FILE *fp; + struct LP_priceinfo *basepp,*relpp; uint32_t now; int64_t price64; struct LP_pubkey_info *pubp; char str[65],fname[512]; FILE *fp; //printf("check PRICEFEED UPDATE.(%s/%s) %.8f %s\n",base,rel,price,bits256_str(str,pubkey)); if ( LP_pricevalid(price) > 0 && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) { - if ( (fp= basepp->fps[relpp->ind]) == 0 ) + //if ( (fp= basepp->fps[relpp->ind]) == 0 ) { LP_pricefname(fname,base,rel); - fp = basepp->fps[relpp->ind] = OS_appendfile(fname); + fp = OS_appendfile(fname); //basepp->fps[relpp->ind] = } if ( fp != 0 ) { @@ -1047,12 +1096,12 @@ void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price) price64 = price * SATOSHIDEN; fwrite(&now,1,sizeof(now),fp); fwrite(&price64,1,sizeof(price64),fp); - fflush(fp); + fclose(fp); } - if ( (fp= relpp->fps[basepp->ind]) == 0 ) + //if ( (fp= relpp->fps[basepp->ind]) == 0 ) { sprintf(fname,"%s/PRICES/%s_%s",GLOBAL_DBDIR,rel,base); - fp = relpp->fps[basepp->ind] = OS_appendfile(fname); + fp = OS_appendfile(fname); //relpp->fps[basepp->ind] = } if ( fp != 0 ) { @@ -1060,17 +1109,21 @@ void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price) price64 = (1. / price) * SATOSHIDEN; fwrite(&now,1,sizeof(now),fp); fwrite(&price64,1,sizeof(price64),fp); - fflush(fp); + fclose(fp); } if ( (pubp= LP_pubkeyadd(pubkey)) != 0 ) { - if ( (rand() % 1000) == 0 ) + if ( (LP_rand() % 1000) == 0 ) printf("PRICEFEED UPDATE.(%-6s/%6s) %12.8f %s %12.8f\n",base,rel,price,bits256_str(str,pubkey),1./price); + if ( unconfcredits > pubp->unconfcredits ) + pubp->unconfcredits = unconfcredits; pubp->timestamp = (uint32_t)time(NULL); - if ( fabs(pubp->matrix[basepp->ind][relpp->ind] - price) > SMALLVAL ) + LP_pubkey_update(pubp,basepp->ind,relpp->ind,price,balance,utxocoin,numrelutxos,minutxo,maxutxo); + //pubp->depthinfo[basepp->ind][relpp->ind] = LP_depthinfo_compact(); + //if ( fabs(pubp->matrix[basepp->ind][relpp->ind] - price) > SMALLVAL ) { - pubp->matrix[basepp->ind][relpp->ind] = price; - pubp->timestamps[basepp->ind][relpp->ind] = pubp->timestamp; + //pubp->matrix[basepp->ind][relpp->ind] = price; + //pubp->timestamps[basepp->ind][relpp->ind] = pubp->timestamp; dxblend(&basepp->relvals[relpp->ind],price,0.9); dxblend(&relpp->relvals[basepp->ind],1. / price,0.9); } @@ -1080,3 +1133,105 @@ void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price) // printf("error finding %s/%s %.8f\n",base,rel,price); } +double LP_CMCbtcprice(double *price_usdp,char *symbol) +{ + char *retstr; cJSON *ticker,*item; double price_btc = 0.; + *price_usdp = 0.; + if ( (retstr= cmc_ticker(symbol)) != 0 ) + { + if ( (ticker= cJSON_Parse(retstr)) != 0 ) + { + item = jitem(ticker,0); + price_btc = jdouble(item,"price_btc"); + *price_usdp = jdouble(item,"price_usd"); + //printf("%.8f item.(%s)\n",price_btc,jprint(item,0)); + free_json(ticker); + } + free(retstr); + } + return(price_btc); +} + +cJSON *LP_fundvalue(cJSON *argjson) +{ + cJSON *holdings,*item,*newitem,*array,*retjson; int32_t i,iter,n,missing=0; double usdprice,divisor,btcprice,balance,btcsum,KMDholdings,numKMD; struct iguana_info *coin; char *symbol,*coinaddr; int64_t fundvalue,KMDvalue = 0; + fundvalue = 0; + KMDholdings = btcsum = 0.; + array = cJSON_CreateArray(); + for (iter=0; iter<2; iter++) + { + if ( iter == 0 ) + holdings = jarray(&n,argjson,"holdings"); + else + { + if ( (coinaddr= jstr(argjson,"address")) != 0 ) + { + holdings = LP_balances(coinaddr); + n = cJSON_GetArraySize(holdings); + } else break; + } + if ( holdings != 0 ) + { + for (i=0; i SMALLVAL ) + { + newitem = cJSON_CreateObject(); + jaddstr(newitem,"coin",symbol); + jaddnum(newitem,"balance",balance); + if ( (coin= LP_coinfind(symbol)) != 0 && (KMDvalue= LP_KMDvalue(coin,SATOSHIDEN * balance)) > 0 ) + { + jaddnum(newitem,"KMD",dstr(KMDvalue)); + fundvalue += KMDvalue; + if ( strcmp(symbol,"KMD") == 0 ) + KMDholdings += dstr(KMDvalue); + } + else if ( iter == 0 && (btcprice= LP_CMCbtcprice(&usdprice,symbol)) > SMALLVAL ) + { + btcsum += btcprice * balance; + jaddnum(newitem,"BTC",btcprice * balance); + } + else jaddstr(newitem,"error","no price source"); + jaddi(array,newitem); + } else missing++; + } + } + } + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jaddnum(retjson,"missing",missing); + jadd(retjson,"holdings",array); + btcprice = LP_CMCbtcprice(&usdprice,"komodo"); + divisor = jdouble(argjson,"divisor"); + jaddnum(retjson,"KMDholdings",KMDholdings); + if ( btcsum != 0 ) + { + if ( btcprice > SMALLVAL ) + { + numKMD = (btcsum / btcprice); + fundvalue += numKMD * SATOSHIDEN; + jaddnum(retjson,"KMD_BTC",btcprice); + jaddnum(retjson,"btcsum",btcsum); + numKMD += KMDholdings; + jaddnum(retjson,"btc2kmd",numKMD); + if ( divisor != 0 ) + { + jaddnum(retjson,"NAV_KMD",numKMD/divisor); + jaddnum(retjson,"NAV_BTC",(btcsum + (KMDholdings * btcprice))/divisor); + jaddnum(retjson,"NAV_USD",(usdprice * numKMD)/divisor); + } + } + } + jaddnum(retjson,"fundvalue",dstr(fundvalue)); + if ( divisor != 0 ) + { + jaddnum(retjson,"divisor",divisor); + numKMD = dstr(fundvalue); + jaddnum(retjson,"assetNAV_KMD",numKMD/divisor); + jaddnum(retjson,"assetNAV_BTC",(btcprice * numKMD)/divisor); + jaddnum(retjson,"assetNAV_USD",(usdprice * numKMD)/divisor); + } + return(retjson); +} + diff --git a/iguana/exchanges/LP_privkey.c b/iguana/exchanges/LP_privkey.c new file mode 100644 index 000000000..db3659602 --- /dev/null +++ b/iguana/exchanges/LP_privkey.c @@ -0,0 +1,337 @@ + +/****************************************************************************** + * Copyright © 2014-2017 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ +// +// LP_utxos.c +// marketmaker +// + +int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 myprivkey,bits256 mypub) +{ + int32_t enable_utxos = 0; + char *script,destaddr[64]; cJSON *array,*item; bits256 txid,deposittxid,zero; int32_t used,i,flag=0,height,n,cmpflag,iambob,vout,depositvout; uint64_t *values=0,satoshis,txfee,biggerval,value,total = 0; int64_t targetval; //struct LP_utxoinfo *utxo; + if ( coin == 0 || (IAMLP == 0 && coin->inactive != 0) ) + { + //printf("coin not active\n"); + return(0); + } + if ( coin->privkeydepth > 0 ) + return(0); + coin->privkeydepth++; + LP_address(coin,coin->smartaddr); + //if ( coin->inactive == 0 ) + // LP_listunspent_issue(coin->symbol,coin->smartaddr,0); + memset(zero.bytes,0,sizeof(zero)); + array = LP_listunspent(coin->symbol,coin->smartaddr,zero,zero); + if ( array != 0 ) + { + txfee = LP_txfeecalc(coin,0,0); + if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) + { + coin->numutxos = n; + //printf("LP_privkey_init %s %d\n",coin->symbol,n); + for (iambob=0; iambob<=1; iambob++) + { + if ( iambob == 0 ) + values = calloc(n,sizeof(*values)); + else memset(values,0,n * sizeof(*values)); + used = 0; + for (i=0; isymbol,txid,vout); + if ( satoshis != 0 && satoshis != value ) + printf("%s %s privkey_init value %.8f vs %.8f (%s) %.8f %.8f\n",coin->symbol,coin->smartaddr,dstr(satoshis),dstr(value),jprint(item,0),jdouble(item,"amount"),jdouble(item,"interest")); + if ( coin->electrum != 0 || LP_inventory_prevent(iambob,coin->symbol,txid,vout) == 0 )//&& height > 0 ) + { + values[i] = satoshis; + //flag += LP_address_utxoadd(coin,destaddr,txid,vout,satoshis,height,-1); + } else used++; + } + //printf("array.%d\n",n); + while ( used < n-1 ) + { + //for (i=0; i= 0 ) + { + item = jitem(array,i); + if ( coin->electrum == 0 ) + { + deposittxid = jbits256(item,"txid"); + depositvout = juint(item,"vout"); + script = jstr(item,"scriptPubKey"); + } + else + { + deposittxid = jbits256(item,"tx_hash"); + depositvout = juint(item,"tx_pos"); + script = coin->smartaddr; + } + biggerval = values[i]; + values[i] = 0, used++; + if ( iambob == 0 ) + targetval = (biggerval / 776) + txfee; + else targetval = (biggerval / 9) * 8 + 2*txfee; + if ( targetval < txfee*2 ) + targetval = txfee*2; + //printf("iambob.%d i.%d deposit %.8f min %.8f target %.8f\n",iambob,i,dstr(biggerval),dstr((1+LP_MINSIZE_TXFEEMULT)*txfee),dstr(targetval)); + if ( biggerval < (1+LP_MINSIZE_TXFEEMULT)*txfee ) + continue; + i = -1; + if ( iambob != 0 ) + { + if ( (i= LP_nearestvalue(iambob,values,n,targetval)) < 0 ) + targetval /= 4; + if ( targetval < txfee*(1+LP_MINSIZE_TXFEEMULT) ) + continue; + } + if ( i >= 0 || (i= LP_nearestvalue(iambob,values,n,targetval)) >= 0 ) + { + //printf("iambob.%d i.%d %.8f target %.8f\n",iambob,i,dstr(biggerval),dstr(targetval)); + item = jitem(array,i); + cmpflag = 0; + if ( coin->electrum == 0 ) + { + txid = jbits256(item,"txid"); + vout = juint(item,"vout"); + if ( jstr(item,"scriptPubKey") != 0 && strcmp(script,jstr(item,"scriptPubKey")) == 0 ) + cmpflag = 1; + } + else + { + txid = jbits256(item,"tx_hash"); + vout = juint(item,"tx_pos"); + cmpflag = 1; + } + if ( cmpflag != 0 ) + { + value = values[i]; + values[i] = 0, used++; + /*portable_mutex_lock(&LP_UTXOmutex); + if ( iambob != 0 ) + { + if ( (utxo= LP_utxoadd(1,coin->symbol,txid,vout,value,deposittxid,depositvout,biggerval,coin->smartaddr,mypub,LP_gui,G.LP_sessionid,value)) != 0 ) + { + } + } + else + { + //printf("call utxoadd\n"); + if ( (utxo= LP_utxoadd(0,coin->symbol,deposittxid,depositvout,biggerval,txid,vout,value,coin->smartaddr,mypub,LP_gui,G.LP_sessionid,biggerval)) != 0 ) + { + } + } + portable_mutex_unlock(&LP_UTXOmutex);*/ + total += value; + } // else printf("scriptmismatch.(%s) vs %s\n",script,jprint(item,0)); + } //else printf("nothing near i.%d\n",i); + } else break; + } + if ( enable_utxos == 0 ) + break; + } + } + free_json(array); + if ( 0 && flag != 0 ) + LP_postutxos(coin->symbol,coin->smartaddr); + } + if ( values != 0 ) + free(values); + if ( coin->privkeydepth > 0 ) + coin->privkeydepth--; + //printf("privkey.%s %.8f\n",symbol,dstr(total)); + return(flag); +} + +char *LP_secretaddresses(void *ctx,char *prefix,char *passphrase,int32_t n,uint8_t taddr,uint8_t pubtype) +{ + int32_t i; uint8_t tmptype,pubkey33[33],rmd160[20]; char output[777*45],str[65],str2[65],buf[8192],wifstr[128],coinaddr[64]; bits256 checkprivkey,privkey,pubkey; cJSON *retjson; + retjson = cJSON_CreateObject(); + if ( prefix == 0 || prefix[0] == 0 ) + prefix = "secretaddress"; + if ( passphrase == 0 || passphrase[0] == 0 ) + passphrase = "password"; + if ( n <= 0 ) + n = 16; + else if ( n > 777 ) + n = 777; + conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); + bitcoin_priv2pub(ctx,pubkey33,coinaddr,privkey,taddr,pubtype); + printf("generator (%s) secrets.[%d] <%s> t.%u p.%u\n",coinaddr,n,passphrase,taddr,pubtype); + sprintf(output,"\"addresses\":["); + for (i=0; i %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); + if ( 0 ) + { + char str[65],str2[65]; + checkkey = iguana_wif2privkey(wifstr); + if ( bits256_cmp(checkkey,privkey) != 0 ) + printf("WIF.(%s) -> %s or %s?\n",wifstr,bits256_str(str,privkey),bits256_str(str2,checkkey)); + } + } + privkey.bytes[0] &= 248, privkey.bytes[31] &= 127, privkey.bytes[31] |= 64; + bitcoin_priv2pub(ctx,coin->pubkey33,coin->smartaddr,privkey,coin->taddr,coin->pubtype); + if ( coin->counter == 0 ) + { + coin->counter++; + memcpy(G.LP_pubsecp,coin->pubkey33,33); + bitcoin_priv2wif(coin->wiftaddr,tmpstr,privkey,coin->wiftype); + bitcoin_addr2rmd160(coin->taddr,&tmptype,G.LP_myrmd160,coin->smartaddr); + LP_privkeyadd(privkey,G.LP_myrmd160); + G.LP_privkey = privkey; + if ( 0 && (coin->pubtype != 60 || strcmp(coin->symbol,"KMD") == 0) ) + printf("%s (%s) %d wif.(%s) (%s)\n",coin->symbol,coin->smartaddr,coin->pubtype,tmpstr,passphrase); + if ( G.counter++ == 0 ) + { + bitcoin_priv2wif(coin->wiftaddr,G.USERPASS_WIFSTR,privkey,188); + bitcoin_wif2priv(coin->wiftaddr,&tmptype,&checkkey,G.USERPASS_WIFSTR); + if ( bits256_cmp(checkkey,privkey) != 0 ) + { + char str[65],str2[65]; + printf("FATAL ERROR converting USERPASS_WIFSTR %s -> %s != %s\n",G.USERPASS_WIFSTR,bits256_str(str,checkkey),bits256_str(str2,privkey)); + exit(-1); + } + conv_NXTpassword(userpass.bytes,pubkeyp->bytes,(uint8_t *)G.USERPASS_WIFSTR,(int32_t)strlen(G.USERPASS_WIFSTR)); + userpub = curve25519(userpass,curve25519_basepoint9()); + printf("userpass.(%s)\n",bits256_str(G.USERPASS,userpub)); + } + } + if ( coin->importedprivkey == 0 && coin->electrum == 0 && coin->userpass[0] != 0 && LP_getheight(¬arized,coin) > 0 ) + { + memset(zero.bytes,0,sizeof(zero)); + LP_listunspent_issue(coin->symbol,coin->smartaddr,0,zero,zero); + if ( (retjson= LP_importprivkey(coin->symbol,tmpstr,coin->smartaddr,-1)) != 0 ) + { + if ( jobj(retjson,"error") != 0 ) + { + printf("cant importprivkey.%s -> (%s), abort session\n",coin->symbol,jprint(retjson,1)); + exit(-1); + } + free_json(retjson); + } + coin->importedprivkey = (uint32_t)time(NULL); + } + vcalc_sha256(0,checkkey.bytes,privkey.bytes,sizeof(privkey)); + checkkey.bytes[0] &= 248, checkkey.bytes[31] &= 127, checkkey.bytes[31] |= 64; + G.LP_mypub25519 = *pubkeyp = curve25519(checkkey,curve25519_basepoint9()); + G.LP_mypriv25519 = checkkey; + LP_pubkeyadd(G.LP_mypub25519); + return(privkey); +} + +void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase) +{ + struct iguana_info *coin,*tmp; bits256 pubkey,privkey; uint8_t pubkey33[33]; int32_t initonly; + initonly = (passphrase != 0); + memset(privkey.bytes,0,sizeof(privkey)); + memset(pubkey.bytes,0,sizeof(pubkey)); + //printf("Total coins: %d\n", HASH_COUNT(LP_coins)); + //int num_iter = 0; + HASH_ITER(hh,LP_coins,coin,tmp) + { + //printf("LP_privkey_updates [%02d / %02d]\n", num_iter++, HASH_COUNT(LP_coins)); + if ( initonly != 0 ) + { + coin->counter = 0; + memset(coin->smartaddr,0,sizeof(coin->smartaddr)); + if ( bits256_nonz(privkey) == 0 || coin->smartaddr[0] == 0 ) + privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,coin,passphrase,""); + } + //printf("i.%d of %d\n",i,LP_numcoins); + else if ( IAMLP == 0 || coin->inactive == 0 ) + { + //printf("from updates %s\n",coin->symbol); + if ( 0 && LP_privkey_init(pubsock,coin,G.LP_privkey,G.LP_mypub25519) == 0 && (LP_rand() % 10) == 0 ) + { + //LP_postutxos(coin->symbol,coin->smartaddr); + } + } + } +} + +int32_t LP_passphrase_init(char *passphrase,char *gui) +{ + static void *ctx; int32_t counter; //iambob,; struct LP_utxoinfo *utxo,*tmp; + if ( ctx == 0 ) + ctx = bitcoin_ctx(); + if ( G.LP_pendingswaps != 0 ) + return(-1); + G.initializing = 1; + if ( gui == 0 ) + gui = "cli"; + counter = G.USERPASS_COUNTER; + while ( G.waiting == 0 ) + { + printf("waiting for G.waiting\n"); + sleep(5); + } + memset(&G,0,sizeof(G)); + LP_privkey_updates(ctx,LP_mypubsock,passphrase); + init_hexbytes_noT(G.LP_myrmd160str,G.LP_myrmd160,20); + G.LP_sessionid = (uint32_t)time(NULL); + safecopy(G.gui,gui,sizeof(G.gui)); + LP_tradebot_pauseall(); + LP_portfolio_reset(); + LP_priceinfos_clear(); + G.USERPASS_COUNTER = counter; + G.initializing = 0; + return(0); +} + + diff --git a/iguana/exchanges/LP_remember.c b/iguana/exchanges/LP_remember.c index 8f5272f20..988d47ba8 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->bobcoin,coinaddr,0,rawtx->txbytes,rawtx->I.datalen,0); + LP_swap_coinaddr(bobcoin,coinaddr,0,rawtx->txbytes,rawtx->I.datalen,0); if ( coinaddr[0] != 0 ) { - LP_importaddress(swap->bobcoin.symbol,coinaddr); + LP_importaddress(swap->I.bobstr,coinaddr); if ( rawtx == &swap->bobdeposit ) safecopy(swap->Bdeposit,coinaddr,sizeof(swap->Bdeposit)); else safecopy(swap->Bpayment,coinaddr,sizeof(swap->Bpayment)); @@ -63,16 +65,16 @@ void basilisk_dontforget(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx fprintf(fp,",\"%s\":\"%s\"","Bpayment",swap->Bpayment); fprintf(fp,",\"expiration\":%u",swap->I.expiration); fprintf(fp,",\"iambob\":%d",swap->I.iambob); - fprintf(fp,",\"bobcoin\":\"%s\"",swap->bobcoin.symbol); - fprintf(fp,",\"alicecoin\":\"%s\"",swap->alicecoin.symbol); + fprintf(fp,",\"bobcoin\":\"%s\"",swap->I.bobstr); + fprintf(fp,",\"alicecoin\":\"%s\"",swap->I.alicestr); fprintf(fp,",\"lock\":%u",locktime); fprintf(fp,",\"amount\":%.8f",dstr(rawtx->I.amount)); if ( bits256_nonz(triggertxid) != 0 ) fprintf(fp,",\"trigger\":\"%s\"",bits256_str(str,triggertxid)); if ( bits256_nonz(swap->I.pubAm) != 0 && bits256_nonz(swap->I.pubBn) != 0 ) { - basilisk_alicescript(redeemscript,&len,script,0,coinaddr,swap->alicecoin.taddr,swap->alicecoin.p2shtype,swap->I.pubAm,swap->I.pubBn); - LP_importaddress(swap->alicecoin.symbol,coinaddr); + basilisk_alicescript(redeemscript,&len,script,0,coinaddr,alicecoin->taddr,alicecoin->p2shtype,swap->I.pubAm,swap->I.pubBn); + LP_importaddress(swap->I.alicestr,coinaddr); fprintf(fp,",\"Apayment\":\"%s\"",coinaddr); } if ( rawtx->I.redeemlen > 0 ) @@ -93,7 +95,11 @@ void basilisk_dontforget(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid), OS_compatible_path(fname); if ( (fp= fopen(fname,"wb")) != 0 ) { - fprintf(fp,"{\"aliceid\":\"%llu\",\"src\":\"%s\",\"srcamount\":%.8f,\"dest\":\"%s\",\"destamount\":%.8f,\"requestid\":%u,\"quoteid\":%u,\"iambob\":%d,\"state\":%u,\"otherstate\":%u,\"expiration\":%u,\"dlocktime\":%u,\"plocktime\":%u,\"Atxfee\":%llu,\"Btxfee\":%llu",(long long)swap->aliceid,swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount),swap->I.req.requestid,swap->I.req.quoteid,swap->I.iambob,swap->I.statebits,swap->I.otherstatebits,swap->I.expiration,swap->bobdeposit.I.locktime,swap->bobpayment.I.locktime,(long long)swap->I.Atxfee,(long long)swap->I.Btxfee); + fprintf(fp,"{\"tradeid\":%u,\"aliceid\":\"%llu\",\"src\":\"%s\",\"srcamount\":%.8f,\"dest\":\"%s\",\"destamount\":%.8f,\"requestid\":%u,\"quoteid\":%u,\"iambob\":%d,\"state\":%u,\"otherstate\":%u,\"expiration\":%u,\"dlocktime\":%u,\"plocktime\":%u,\"Atxfee\":%llu,\"Btxfee\":%llu",swap->tradeid,(long long)swap->aliceid,swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount),swap->I.req.requestid,swap->I.req.quoteid,swap->I.iambob,swap->I.statebits,swap->I.otherstatebits,swap->I.expiration,swap->bobdeposit.I.locktime,swap->bobpayment.I.locktime,(long long)swap->I.Atxfee,(long long)swap->I.Btxfee); + if ( swap->I.iambob == 0 ) + fprintf(fp,",\"Agui\":\"%s\"",G.gui); + else fprintf(fp,",\"Bgui\":\"%s\"",G.gui); + fprintf(fp,",\"gui\":\"%s\"",G.gui); if ( memcmp(zeroes,swap->I.secretAm,20) != 0 ) { init_hexbytes_noT(secretAmstr,swap->I.secretAm,20); @@ -237,6 +243,7 @@ bits256 basilisk_swap_privbob_extract(char *symbol,bits256 spendtxid,int32_t vin bits256 basilisk_swap_privBn_extract(bits256 *bobrefundp,char *bobcoin,bits256 bobdeposit,bits256 privBn) { char destaddr[64]; + destaddr[0] = 0; if ( bits256_nonz(privBn) == 0 ) { if ( bits256_nonz(bobdeposit) != 0 ) @@ -247,23 +254,45 @@ bits256 basilisk_swap_privBn_extract(bits256 *bobrefundp,char *bobcoin,bits256 b return(privBn); } -bits256 basilisk_swap_spendupdate(int32_t iambob,char *symbol,char *spentaddr,int32_t *sentflags,bits256 *txids,int32_t utxoind,int32_t alicespent,int32_t bobspent,int32_t vout,char *aliceaddr,char *bobaddr,char *Adest,char *dest) +bits256 basilisk_swap_spendupdate(int32_t iambob,char *symbol,char *spentaddr,int32_t *sentflags,bits256 *txids,int32_t utxoind,int32_t alicespent,int32_t bobspent,int32_t utxovout,char *aliceaddr,char *bobaddr,char *Adest,char *dest) { - bits256 spendtxid,txid; char destaddr[64],str[65]; struct iguana_info *coin; cJSON *histobj; - if ( (coin= LP_coinfind(symbol)) != 0 && coin->electrum != 0 ) + bits256 spendtxid,txid; char destaddr[64],str[65]; int32_t i,n; struct iguana_info *coin; cJSON *array,*txobj; + memset(&spendtxid,0,sizeof(spendtxid)); + destaddr[0] = 0; + if ( (coin= LP_coinfind(symbol)) == 0 ) + return(spendtxid); + //printf("spentaddr.%s aliceaddr.%s bobaddr.%s Adest.%s Bdest.%s\n",spentaddr,aliceaddr,bobaddr,Adest,dest); + if ( coin->electrum != 0 ) { - if ( (histobj= electrum_address_gethistory(symbol,coin->electrum,&histobj,spentaddr)) != 0 ) + if ( (array= electrum_address_gethistory(symbol,coin->electrum,&array,spentaddr,txids[utxoind])) != 0 ) { - //printf("processed history.(%s)\n",jprint(histobj,0)); - free_json(histobj); + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; iexpiration);// - INSTANTDEX_LOCKTIME*2); + jaddnum(item,"tradeid",rswap->tradeid); jaddnum(item,"requestid",rswap->requestid); jaddnum(item,"quoteid",rswap->quoteid); jaddnum(item,"iambob",rswap->iambob); + jaddstr(item,"Bgui",rswap->Bgui); + jaddstr(item,"Agui",rswap->Agui); + jaddstr(item,"gui",rswap->gui); jaddstr(item,"bob",rswap->src); jaddnum(item,"srcamount",dstr(rswap->srcamount)); jaddnum(item,"bobtxfee",dstr(rswap->Btxfee)); @@ -491,7 +514,7 @@ cJSON *LP_swap_json(struct LP_swap_remember *rswap) if ( rswap->sentflags[i] != 0 ) jaddistr(array,txnames[i]); if ( rswap->txbytes[i] != 0 ) - free(rswap->txbytes[i]); + free(rswap->txbytes[i]), rswap->txbytes[i] = 0; } jadd(item,"sentflags",array); array = cJSON_CreateArray(); @@ -500,7 +523,10 @@ cJSON *LP_swap_json(struct LP_swap_remember *rswap) jadd(item,"values",array); jaddstr(item,"result","success"); if ( rswap->finishedflag != 0 ) + { jaddstr(item,"status","finished"); + jaddnum(item,"finishtime",rswap->finishtime); + } else jaddstr(item,"status","pending"); jaddbits256(item,"bobdeposit",rswap->txids[BASILISK_BOBDEPOSIT]); jaddbits256(item,"alicepayment",rswap->txids[BASILISK_ALICEPAYMENT]); @@ -511,7 +537,7 @@ cJSON *LP_swap_json(struct LP_swap_remember *rswap) return(item); } -int32_t LP_rswap_init(struct LP_swap_remember *rswap,uint32_t requestid,uint32_t quoteid) +int32_t LP_rswap_init(struct LP_swap_remember *rswap,uint32_t requestid,uint32_t quoteid,int32_t forceflag) { char fname[1024],*fstr,*secretstr,*srcstr,*deststr,*dest33,*txname; long fsize; cJSON *item,*txobj,*array; bits256 privkey; struct iguana_info *coin; uint32_t r,q; int32_t i,j,n; uint8_t other33[33]; memset(rswap,0,sizeof(*rswap)); @@ -523,6 +549,10 @@ int32_t LP_rswap_init(struct LP_swap_remember *rswap,uint32_t requestid,uint32_t if ( (item= cJSON_Parse(fstr)) != 0 ) { rswap->iambob = jint(item,"iambob"); + safecopy(rswap->Bgui,jstr(item,"Bgui"),sizeof(rswap->Bgui)); + safecopy(rswap->Agui,jstr(item,"Agui"),sizeof(rswap->Agui)); + safecopy(rswap->gui,jstr(item,"gui"),sizeof(rswap->gui)); + rswap->tradeid = juint(item,"tradeid"); rswap->aliceid = j64bits(item,"aliceid"); if ( (secretstr= jstr(item,"secretAm")) != 0 && strlen(secretstr) == 40 ) decode_hex(rswap->secretAm,20,secretstr); @@ -638,9 +668,12 @@ int32_t LP_rswap_init(struct LP_swap_remember *rswap,uint32_t requestid,uint32_t } } } + free_json(txobj); } rswap->origfinishedflag = basilisk_swap_isfinished(rswap->iambob,rswap->txids,rswap->sentflags,rswap->paymentspent,rswap->Apaymentspent,rswap->depositspent); rswap->finishedflag = rswap->origfinishedflag; + if ( forceflag != 0 ) + rswap->finishedflag = rswap->origfinishedflag = 0; free(fstr); } return(rswap->iambob); @@ -671,7 +704,7 @@ int32_t LP_refht_update(char *symbol,bits256 txid) return(0); } -int32_t LP_swap_load(struct LP_swap_remember *rswap) +int32_t LP_swap_load(struct LP_swap_remember *rswap,int32_t forceflag) { int32_t i,needflag,addflag; long fsize; char fname[1024],*fstr,*symbol,*rstr; cJSON *txobj,*sentobj,*fileobj; bits256 txid,checktxid; uint64_t value; rswap->iambob = -1; @@ -680,7 +713,9 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap) { if ( (fileobj= cJSON_Parse(fstr)) != 0 ) { - rswap->origfinishedflag = rswap->finishedflag = 1; + rswap->finishtime = juint(fileobj,"finishtime"); + if ( forceflag == 0 ) + rswap->origfinishedflag = rswap->finishedflag = 1; free_json(fileobj); } free(fstr); @@ -701,7 +736,11 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap) rswap->iambob = jint(txobj,"iambob"); txid = jbits256(txobj,"txid"); if ( bits256_nonz(txid) == 0 ) + { + free(fstr); + free_json(txobj); continue; + } rswap->txids[i] = txid; if ( jstr(txobj,"Apayment") != 0 ) safecopy(rswap->alicepaymentaddr,jstr(txobj,"Apayment"),sizeof(rswap->alicepaymentaddr)); @@ -753,7 +792,7 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap) safecopy(rswap->alicecoin,symbol,sizeof(rswap->alicecoin)); if ( rswap->finishedflag == 0 ) { - if ( (sentobj= LP_gettx(symbol,txid)) == 0 ) + if ( (sentobj= LP_gettx(symbol,txid,1)) == 0 ) { char str2[65]; printf("%s %s ready to broadcast\n",symbol,bits256_str(str2,txid)); } @@ -773,6 +812,7 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap) //printf("%s %s %.8f\n",txnames[i],bits256_str(str,txid),dstr(value)); } } + free_json(txobj); } //else printf("no symbol\n"); free(fstr); } else if ( 0 && rswap->finishedflag == 0 ) @@ -847,23 +887,30 @@ int32_t LP_spends_set(struct LP_swap_remember *rswap) return(numspent); } -cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requestid,uint32_t quoteid) +cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requestid,uint32_t quoteid,int32_t forceflag,int32_t pendingonly) { static void *ctx; struct LP_swap_remember rswap; int32_t i,j,flag,numspent,len,secretstart,redeemlen; char str[65],*srcAdest,*srcBdest,*destAdest,*destBdest,otheraddr[64]; cJSON *item,*txoutobj; bits256 rev,signedtxid,zero,deadtxid; struct iguana_info *bob=0,*alice=0; uint8_t redeemscript[1024],userdata[1024]; if ( ctx == 0 ) ctx = bitcoin_ctx(); - if ( (rswap.iambob= LP_rswap_init(&rswap,requestid,quoteid)) < 0 ) + if ( requestid == 0 || quoteid == 0 ) + return(cJSON_Parse("{\"error\":\"null requestid or quoteid\"}")); + if ( (rswap.iambob= LP_rswap_init(&rswap,requestid,quoteid,forceflag)) < 0 ) return(cJSON_Parse("{\"error\":\"couldnt initialize rswap, are all coins active?\"}")); decode_hex(deadtxid.bytes,32,"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"); - LP_swap_load(&rswap); + LP_swap_load(&rswap,forceflag); memset(zero.bytes,0,sizeof(zero)); otheraddr[0] = 0; srcAdest = srcBdest = destAdest = destBdest = 0; if ( rswap.bobcoin[0] == 0 || rswap.alicecoin[0] == 0 || strcmp(rswap.bobcoin,rswap.src) != 0 || strcmp(rswap.alicecoin,rswap.dest) != 0 ) { - printf("legacy DB SWAPS files BOB.(%s) Alice.(%s) src.(%s) dest.(%s)\n",rswap.bobcoin,rswap.alicecoin,rswap.src,rswap.dest); - return(cJSON_Parse("{\"error\":\"mismatched bob/alice vs src/dest coins??\"}")); + //printf("legacy r%u-q%u DB SWAPS.(%u %u) %llu files BOB.(%s) Alice.(%s) src.(%s) dest.(%s)\n",requestid,quoteid,rswap.requestid,rswap.quoteid,(long long)rswap.aliceid,rswap.bobcoin,rswap.alicecoin,rswap.src,rswap.dest); + cJSON *retjson = cJSON_CreateObject(); + jaddstr(retjson,"error","swap never started"); + jaddnum(retjson,"requestid",requestid); + jaddnum(retjson,"quoteid",quoteid); + return(retjson); + //return(cJSON_Parse("{\"error\":\"mismatched bob/alice vs src/dest coins??\"}")); } alice = LP_coinfind(rswap.alicecoin); bob = LP_coinfind(rswap.bobcoin); @@ -876,6 +923,15 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti bitcoin_address(otheraddr,alice->taddr,alice->pubtype,rswap.other33,33); destBdest = otheraddr; destAdest = rswap.Adestaddr; + if ( strcmp(alice->smartaddr,rswap.Adestaddr) != 0 ) + { + printf("this isnt my swap! alice.(%s vs %s)\n",alice->smartaddr,rswap.Adestaddr); + cJSON *retjson = cJSON_CreateObject(); + jaddstr(retjson,"error","swap for different account"); + jaddnum(retjson,"requestid",requestid); + jaddnum(retjson,"quoteid",quoteid); + return(retjson); + } } if ( (bob= LP_coinfind(rswap.bobcoin)) != 0 ) { @@ -891,6 +947,15 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti bitcoin_address(otheraddr,bob->taddr,bob->pubtype,rswap.other33,33); srcAdest = otheraddr; srcBdest = rswap.destaddr; + if ( strcmp(bob->smartaddr,rswap.destaddr) != 0 ) + { + printf("this isnt my swap! bob.(%s vs %s)\n",bob->smartaddr,rswap.destaddr); + cJSON *retjson = cJSON_CreateObject(); + jaddstr(retjson,"error","swap for different account"); + jaddnum(retjson,"requestid",requestid); + jaddnum(retjson,"quoteid",quoteid); + return(retjson); + } } if ( (alice= LP_coinfind(rswap.alicecoin)) != 0 ) { @@ -969,7 +1034,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti } if ( rswap.sentflags[BASILISK_ALICECLAIM] == 0 && rswap.sentflags[BASILISK_BOBDEPOSIT] != 0 && bits256_nonz(rswap.txids[BASILISK_BOBDEPOSIT]) != 0 && bits256_nonz(rswap.depositspent) == 0 ) { - if ( time(NULL) > rswap.expiration ) + if ( time(NULL) > rswap.expiration+777 ) { flag = 0; if ( bob->electrum == 0 ) @@ -1058,7 +1123,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti free_json(txoutobj), flag = 0; else flag = -1, rswap.paymentspent = deadtxid; } - if ( flag == 0 && time(NULL) > rswap.expiration ) + if ( flag == 0 && time(NULL) > rswap.expiration+777 ) { // bobreclaim redeemlen = basilisk_swap_bobredeemscript(0,&secretstart,redeemscript,rswap.plocktime,rswap.pubA0,rswap.pubB0,rswap.pubB1,zero,rswap.privBn,rswap.secretAm,rswap.secretAm256,rswap.secretBn,rswap.secretBn256); @@ -1087,7 +1152,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti free_json(txoutobj), flag = 0; else flag = -1, rswap.depositspent = deadtxid; } - if ( flag == 0 && (bits256_nonz(rswap.Apaymentspent) != 0 || time(NULL) > rswap.expiration) ) + if ( flag == 0 && (bits256_nonz(rswap.Apaymentspent) != 0 || time(NULL) > rswap.expiration+777) ) { printf("do the refund! paymentspent.%s now.%u vs expiration.%u\n",bits256_str(str,rswap.paymentspent),(uint32_t)time(NULL),rswap.expiration); //if ( txbytes[BASILISK_BOBREFUND] == 0 ) @@ -1101,7 +1166,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti } LP_txbytes_update("bobrefund",rswap.bobcoin,rswap.txbytes[BASILISK_BOBREFUND],&rswap.txids[BASILISK_BOBREFUND],&rswap.depositspent,&rswap.sentflags[BASILISK_BOBREFUND]); } - else if ( flag == 0 ) + else if ( 0 && flag == 0 ) printf("bobrefund's time %u vs expiration %u\n",(uint32_t)time(NULL),rswap.expiration); } } @@ -1126,29 +1191,48 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti if ( (numspent= LP_spends_set(&rswap)) == 3 ) rswap.finishedflag = 1; else rswap.finishedflag = basilisk_swap_isfinished(rswap.iambob,rswap.txids,rswap.sentflags,rswap.paymentspent,rswap.Apaymentspent,rswap.depositspent); - item = LP_swap_json(&rswap); if ( rswap.origfinishedflag == 0 && rswap.finishedflag != 0 ) { char fname[1024],*itemstr; FILE *fp; - printf("SWAP %u-%u finished!\n",requestid,quoteid); + LP_numfinished++; + printf("SWAP %u-%u finished LP_numfinished.%d !\n",requestid,quoteid,LP_numfinished); + if ( rswap.finishtime == 0 ) + rswap.finishtime = (uint32_t)time(NULL); + if ( rswap.tradeid != 0 ) + LP_tradebot_finished(rswap.tradeid,rswap.requestid,rswap.quoteid); sprintf(fname,"%s/SWAPS/%u-%u.finished",GLOBAL_DBDIR,rswap.requestid,rswap.quoteid), OS_compatible_path(fname); + item = LP_swap_json(&rswap); if ( (fp= fopen(fname,"wb")) != 0 ) { jaddstr(item,"method","tradestatus"); + jaddnum(item,"finishtime",rswap.finishtime); + jaddstr(item,"gui",G.gui); + //jaddbits256(item,"srchash",rswap.Q.srchash); + //jaddbits256(item,"desthash",rswap.desthash); itemstr = jprint(item,0); fprintf(fp,"%s\n",itemstr); LP_tradecommand_log(item); - LP_reserved_msg(rswap.src,rswap.dest,zero,clonestr(itemstr)); - LP_broadcast_message(LP_mypubsock,rswap.src,rswap.dest,zero,itemstr); + LP_reserved_msg(1,rswap.src,rswap.dest,zero,clonestr(itemstr)); + sleep(1); + LP_reserved_msg(0,rswap.src,rswap.dest,zero,itemstr); + //LP_broadcast_message(LP_mypubsock,rswap.src,rswap.dest,zero,itemstr); fclose(fp); } + } else item = LP_swap_json(&rswap); + for (i=0; i> 32); - q = (uint32_t)G.LP_skipstatus[i]; - if ( r == requestid && q == quoteid ) + 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 ) @@ -1198,7 +1285,7 @@ char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid) { if ( count < sizeof(ridqids)/sizeof(*ridqids) ) ridqids[count++] = ridqid; - if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid)) != 0 ) + if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid,0,pendingonly)) != 0 ) jaddi(array,item); } } @@ -1227,43 +1314,18 @@ char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid) else if ( Ktotal < 0 && Btotal > 0 ) jaddnum(retjson,"avesell",(double)-Btotal/Ktotal); } - /*array = cJSON_CreateArray(); - for (i=0; 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])); - } - jadd(retjson,"quotes",array);*/ portable_mutex_unlock(&LP_swaplistmutex); return(jprint(retjson,1)); } -char *basilisk_swapentry(uint32_t requestid,uint32_t quoteid) +char *basilisk_swapentry(uint32_t requestid,uint32_t quoteid,int32_t forceflag) { - char *liststr,*retstr = 0; cJSON *retjson,*array,*item; int32_t i,n; - if ( (liststr= basilisk_swaplist(requestid,quoteid)) != 0 ) - { - //printf("swapentry.(%s)\n",liststr); - if ( (retjson= cJSON_Parse(liststr)) != 0 ) - { - if ( (array= jarray(&n,retjson,"swaps")) != 0 ) - { - for (i=0; i= 0 && (relind= LP_priceinfoind(rel)) >= 0 ) + { + srcamount = jdouble(swapjson,"srcamount"); + destamount = jdouble(swapjson,"destamount"); + if ( jint(swapjson,"iambob") != 0 ) + srcamount = -srcamount; + else destamount = -destamount; + if ( srcamount != 0. && destamount != 0. ) + { + netamounts[baseind] += srcamount; + netamounts[relind] += destamount; + subitem = cJSON_CreateObject(); + jaddnum(subitem,base,srcamount); + jaddnum(subitem,rel,destamount); + jaddnum(subitem,"price",-destamount/srcamount); + jaddi(item,subitem); + } + } else printf("base.%p rel.%p statusstr.%p baseind.%d relind.%d\n",base,rel,statusstr,baseind,relind); + free_json(swapjson); + } else printf("error parsing.(%s)\n",retstr); + free(retstr); + } jaddi(array,item); } else break; } else break; @@ -1302,11 +1397,23 @@ char *LP_recent_swaps(int32_t limit) retjson = cJSON_CreateObject(); jaddstr(retjson,"result","success"); jadd(retjson,"swaps",array); + array = cJSON_CreateArray(); + for (i=0; ierrors < maxerrs || peer->good >= LP_MINPEER_GOOD) ) - { - if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) == 0 ) - { - if ( peer != 0 ) - { - peer->errors++; - peer->good *= LP_PEERGOOD_ERRORDECAY; - } else printf("%s error on (%s:%u) without peer\n",debugstr,destip,port); - } - else if ( peer != 0 ) - peer->good++; - } - return(retstr); -} - char *LP_isitme(char *destip,uint16_t destport) { if ( LP_mypeer != 0 && strcmp(destip,LP_mypeer->ipaddr) == 0 && LP_mypeer->port == destport ) @@ -48,59 +26,6 @@ char *LP_isitme(char *destip,uint16_t destport) } else return(0); } -char *issue_LP_getpeers(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers) -{ - char url[512],*retstr; - sprintf(url,"http://%s:%u/api/stats/getpeers?ipaddr=%s&port=%u&numpeers=%d",destip,destport,ipaddr,port,numpeers); - retstr = LP_issue_curl("getpeers",destip,port,url); - //printf("%s -> getpeers.(%s)\n",destip,retstr); - return(retstr); -} - -char *issue_LP_uitem(char *destip,uint16_t destport,char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t height,uint64_t value) -{ - char url[512],*retstr,str[65]; - if ( (retstr= LP_isitme(destip,destport)) != 0 ) - return(retstr); - sprintf(url,"http://%s:%u/api/stats/uitem?coin=%s&coinaddr=%s&txid=%s&vout=%d&ht=%d&value=%llu",destip,destport,symbol,coinaddr,bits256_str(str,txid),vout,height,(long long)value); - retstr = LP_issue_curl("uitem",destip,destport,url); - //printf("uitem.(%s)\n",retstr); - return(retstr); -} - -char *issue_LP_notify(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers,uint32_t sessionid,char *rmd160str,bits256 pub) -{ - char url[512],*retstr,str[65]; - if ( (retstr= LP_isitme(destip,destport)) != 0 ) - return(retstr); - sprintf(url,"http://%s:%u/api/stats/notify?ipaddr=%s&port=%u&numpeers=%d&session=%u",destip,destport,ipaddr,port,numpeers,sessionid); - if ( rmd160str != 0 && bits256_nonz(pub) != 0 ) - { - sprintf(url+strlen(url),"&rmd160=%s&pub=%s",rmd160str,bits256_str(str,pub)); - //printf("SEND (%s)\n",url); - } - return(LP_issue_curl("notify",destip,destport,url)); - //return(issue_curlt(url,LP_HTTP_TIMEOUT)); -} - -char *issue_LP_getprices(char *destip,uint16_t destport) -{ - char url[512]; - sprintf(url,"http://%s:%u/api/stats/getprices",destip,destport); - //printf("getutxo.(%s)\n",url); - return(LP_issue_curl("getprices",destip,destport,url)); - //return(issue_curlt(url,LP_HTTP_TIMEOUT)); -} - -char *issue_LP_listunspent(char *destip,uint16_t destport,char *symbol,char *coinaddr) -{ - char url[512],*retstr; - sprintf(url,"http://%s:%u/api/stats/listunspent?coin=%s&address=%s",destip,destport,symbol,coinaddr); - retstr = LP_issue_curl("listunspent",destip,destport,url); - //printf("listunspent.(%s) -> (%s)\n",url,retstr); - return(retstr); -} - char *LP_apicall(struct iguana_info *coin,char *method,char *params) { cJSON *retjson; char *retstr; @@ -110,7 +35,7 @@ char *LP_apicall(struct iguana_info *coin,char *method,char *params) { if ( (retjson= electrum_submit(coin->symbol,coin->electrum,&retjson,method,params,ELECTRUM_TIMEOUT)) != 0 ) { - retstr = jprint(retjson,0); + retstr = jprint(retjson,1); //printf("got.%p (%s)\n",retjson,retstr); return(retstr); } return(clonestr("{\"error\":\"electrum no response\"}")); @@ -127,7 +52,7 @@ cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params) //printf("issue.(%s, %s, %s, %s, %s)\n",coin->symbol,coin->serverport,coin->userpass,method,params); if ( coin->electrum != 0 && (strcmp(method,"getblock") == 0 || strcmp(method,"paxprice") == 0 || strcmp(method,"getrawmempool") == 0) ) return(cJSON_Parse("{\"error\":\"illegal electrum call\"}")); - if ( coin->inactive == 0 || strcmp(method,"importprivkey") == 0 || strcmp(method,"validateaddress") == 0 ) + if ( coin->inactive == 0 || strcmp(method,"importprivkey") == 0 || strcmp(method,"validateaddress") == 0 || strcmp(method,"getrawtransaction") == 0 || strcmp(method,"getblock") == 0 || strcmp(method,"getinfo") == 0 ) { if ( coin->electrum == 0 ) { @@ -149,13 +74,6 @@ cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params) free_json(retjson); retjson = 0; } - //printf("electrum %s.%s -> (%s)\n",method,params,jprint(retjson,0)); - /*if ( (resultjson= jobj(retjson,"result")) != 0 ) - { - resultjson = jduplicate(resultjson); - free_json(retjson); - retjson = resultjson; - }*/ } } } else retjson = cJSON_Parse("{\"result\":\"disabled\"}"); @@ -165,167 +83,17 @@ cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params) void LP_unspents_mark(char *symbol,cJSON *vins) { - printf("LOCK (%s)\n",jprint(vins,0)); -} - -char *NXTnodes[] = { "62.75.159.113", "91.44.203.238", "82.114.88.225", "78.63.207.76", "188.174.110.224", "91.235.72.49", "213.144.130.91", "209.222.98.250", "216.155.128.10", "178.33.203.157", "162.243.122.251", "69.163.47.173", "193.151.106.129", "78.94.2.74", "192.3.196.10", "173.33.112.87", "104.198.173.28", "35.184.154.126", "174.140.167.239", "23.88.113.131", "198.71.84.173", "178.150.207.53", "23.88.61.53", "192.157.233.106", "192.157.241.212", "23.89.192.88", "23.89.200.27", "192.157.241.139", "23.89.200.63", "23.89.192.98", "163.172.214.102", "176.9.85.5", "80.150.243.88", "80.150.243.92", "80.150.243.98", "109.70.186.198", "146.148.84.237", "104.155.56.82", "104.197.157.140", "37.48.73.249", "146.148.77.226", "84.57.170.200", "107.161.145.131", "80.150.243.97", "80.150.243.93", "80.150.243.100", "80.150.243.95", "80.150.243.91", "80.150.243.99", "80.150.243.96", "93.231.187.177", "212.237.23.85", "35.158.179.254", "46.36.66.41", "185.170.113.79", "163.172.68.112", "78.47.35.210", "77.90.90.75", "94.177.196.134", "212.237.22.215", "94.177.234.11", "167.160.180.199", "54.68.189.9", "94.159.62.14", "195.181.221.89", "185.33.145.94", "195.181.209.245", "195.181.221.38", "195.181.221.162", "185.33.145.12", "185.33.145.176", "178.79.128.235", "94.177.214.120", "94.177.199.41", "94.177.214.200", "94.177.213.201", "212.237.13.162", "195.181.221.236", "195.181.221.185", "185.28.103.187", "185.33.146.244", "217.61.123.71", "195.181.214.45", "195.181.212.99", "195.181.214.46", "195.181.214.215", "195.181.214.68", "217.61.123.118", "195.181.214.79", "217.61.123.14", "217.61.124.100", "195.181.214.111", "85.255.0.176", "81.2.254.116", "217.61.123.184", "195.181.212.231", "94.177.214.110", "195.181.209.164", "104.129.56.238", "85.255.13.64", "167.160.180.206", "217.61.123.226", "167.160.180.208", "93.186.253.127", "212.237.6.208", "94.177.207.190", "217.61.123.119", "85.255.1.245", "217.61.124.157", "37.59.57.141", "167.160.180.58", "104.223.53.14", "217.61.124.69", "195.181.212.103", "85.255.13.141", "104.207.133.204", "71.90.7.107", "107.150.18.108", "23.94.134.161", "80.150.243.13", "80.150.243.11", "185.81.165.52", "80.150.243.8" }; - -static char *assetids[][4] = -{ - { "13502152099823770958", "SUPERNETx2", "10000", "10000" }, - { "12071612744977229797", "SUPERNET", "10000", "10000" }, - { "12071612744977229797", "UNITY", "10000", "10000" }, - { "15344649963748848799", "DEX", "1", "100000000" }, - { "6883271355794806507", "PANGEA", "10000", "10000" }, - { "17911762572811467637", "JUMBLR", "10000", "10000" }, - { "17083334802666450484", "BET", "10000", "10000" }, - { "13476425053110940554", "CRYPTO", "1000", "100000" }, - { "6932037131189568014", "HODL", "1", "100000000" }, - { "3006420581923704757", "SHARK", "10000", "10000" }, - { "17571711292785902558", "BOTS", "1", "100000000" }, - { "10524562908394749924", "MGW", "1", "100000000" }, -}; - -uint64_t LP_assetid_mult(int32_t *assetindp,char *name,uint64_t assetid) -{ - int32_t i; uint64_t mult = 0; - name[0] = 0; - *assetindp = -1; - for (i=0; i= 0 ) - totals[ind] += qty * mult; - if ( msgstr != 0 && assetname[0] != 0 && qty != 0 ) - printf("%-4d: (%35s) <- %13.5f %10s tx.%llu\n",i,msgstr!=0?msgstr:jprint(item,0),dstr(qty * mult),assetname,(long long)txnum); - if ( msgjson != 0 ) - free_json(msgjson); - } - if ( txnum == calc_nxt64bits("7256847492742571143") ) - break; - } - } - free_json(retjson); - } - free(retstr); - } - printf("\nTotal redeemed\n"); - for (i=0; iheight; - if ( coin->electrum == 0 && time(NULL) > coin->heighttime+60 ) + if ( coin->electrum == 0 && time(NULL) > coin->heighttime+60 && coin->userpass[0] != 0 ) { if ( strcmp(coin->symbol,"BTC") == 0 ) method = "getblockchaininfo"; @@ -334,6 +102,13 @@ int32_t LP_getheight(struct iguana_info *coin) { retjson = cJSON_Parse(retstr); coin->height = height = jint(retjson,"blocks"); + if ( (*notarizedp= jint(retjson,"notarized")) != 0 && *notarizedp != coin->notarized ) + { + printf("new notarized %s %d -> %d\n",coin->symbol,coin->notarized,*notarizedp); + coin->notarized = *notarizedp; + coin->notarizationtxid = jbits256(retjson,"notarizedtxid"); + coin->notarizedhash = jbits256(retjson,"notarizedhash"); + } free_json(retjson); if ( coin->height > 0 ) coin->heighttime = (uint32_t)time(NULL); @@ -343,7 +118,7 @@ int32_t LP_getheight(struct iguana_info *coin) return(height); } -uint64_t LP_smartbalance(struct iguana_info *coin) +uint64_t LP_RTsmartbalance(struct iguana_info *coin) { cJSON *array,*item; char buf[512],*retstr; int32_t i,n; uint64_t valuesum,value; valuesum = 0; @@ -366,7 +141,7 @@ uint64_t LP_smartbalance(struct iguana_info *coin) return(valuesum); } -cJSON *LP_getmempool(char *symbol,char *coinaddr) +cJSON *LP_getmempool(char *symbol,char *coinaddr,bits256 txid,bits256 txid2) { cJSON *array; struct iguana_info *coin; if ( symbol == 0 || symbol[0] == 0 ) @@ -376,7 +151,7 @@ cJSON *LP_getmempool(char *symbol,char *coinaddr) return(cJSON_Parse("{\"error\":\"no native coin\"}")); if ( coin->electrum == 0 ) return(bitcoin_json(coin,"getrawmempool","[]")); - else return(electrum_address_getmempool(symbol,coin->electrum,&array,coinaddr)); + else return(electrum_address_getmempool(symbol,coin->electrum,&array,coinaddr,txid,txid2)); } cJSON *LP_paxprice(char *fiat) @@ -388,9 +163,9 @@ cJSON *LP_paxprice(char *fiat) return(bitcoin_json(coin,"paxprice",buf)); } -cJSON *LP_gettx(char *symbol,bits256 txid) +cJSON *LP_gettx(char *symbol,bits256 txid,int32_t suppress_errors) { - struct iguana_info *coin; char buf[512],str[65]; cJSON *retjson; + struct iguana_info *coin; char buf[512],str[65]; int32_t height; cJSON *retjson; //printf("LP_gettx %s %s\n",symbol,bits256_str(str,txid)); if ( symbol == 0 || symbol[0] == 0 ) return(cJSON_Parse("{\"error\":\"null symbol\"}")); @@ -407,9 +182,10 @@ cJSON *LP_gettx(char *symbol,bits256 txid) } else { - if ( (retjson= electrum_transaction(symbol,coin->electrum,&retjson,txid)) != 0 ) + if ( (retjson= electrum_transaction(&height,symbol,coin->electrum,&retjson,txid,0)) != 0 ) return(retjson); - else printf("failed blockchain.transaction.get %s %s\n",coin->symbol,bits256_str(str,txid)); + else if ( suppress_errors == 0 ) + printf("failed blockchain.transaction.get %s %s\n",coin->symbol,bits256_str(str,txid)); return(cJSON_Parse("{\"error\":\"no transaction bytes\"}")); } } @@ -417,7 +193,7 @@ cJSON *LP_gettx(char *symbol,bits256 txid) uint32_t LP_locktime(char *symbol,bits256 txid) { cJSON *txobj; uint32_t locktime = 0; - if ( (txobj= LP_gettx(symbol,txid)) != 0 ) + if ( (txobj= LP_gettx(symbol,txid,0)) != 0 ) { locktime = juint(txobj,"locktime"); free_json(txobj); @@ -446,7 +222,7 @@ cJSON *LP_gettxout_json(bits256 txid,int32_t vout,int32_t height,char *coinaddr, cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout) { - char buf[128],str[65]; cJSON *item,*array,*vouts,*txobj,*retjson=0; int32_t i,v,n; bits256 t; struct iguana_info *coin; struct LP_transaction *tx; struct LP_address_utxo *up; + char buf[128],str[65]; cJSON *item,*array,*vouts,*txobj,*retjson=0; int32_t i,v,height,n; bits256 t,zero; struct iguana_info *coin; struct LP_transaction *tx; struct LP_address_utxo *up; if ( symbol == 0 || symbol[0] == 0 ) return(cJSON_Parse("{\"error\":\"null symbol\"}")); if ( (coin= LP_coinfind(symbol)) == 0 ) @@ -468,7 +244,7 @@ cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout) } if ( coinaddr[0] == 0 ) { - if ( (txobj= electrum_transaction(symbol,coin->electrum,&txobj,txid)) != 0 ) + if ( (txobj= electrum_transaction(&height,symbol,coin->electrum,&txobj,txid,0)) != 0 ) { if ( (vouts= jarray(&n,txobj,"vout")) != 0 && n > 0 ) LP_destaddr(coinaddr,jitem(vouts,vout)); @@ -483,7 +259,8 @@ cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout) return(0); //return(LP_gettxout_json(txid,vout,up->U.height,coinaddr,up->U.value)); } - if ( (array= electrum_address_listunspent(coin->symbol,0,&array,coinaddr,1)) != 0 ) + memset(zero.bytes,0,sizeof(zero)); + if ( (array= electrum_address_listunspent(coin->symbol,0,&array,coinaddr,1,txid,zero)) != 0 ) { //printf("array.(%s)\n",jprint(array,0)); if ( array != 0 && (n= cJSON_GetArraySize(array)) > 0 ) @@ -505,22 +282,11 @@ cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout) return(retjson); } } - printf("couldnt find %s/v%d\n",bits256_str(str,txid),vout); + //printf("couldnt find %s (%s) %s/v%d\n",symbol,coinaddr,bits256_str(str,txid),vout); return(cJSON_Parse("{\"error\":\"couldnt get tx\"}")); } } -/*cJSON *LP_listtransactions(char *symbol,char *coinaddr,int32_t count,int32_t skip) -{ - char buf[128]; struct iguana_info *coin = LP_coinfind(symbol); - if ( coin == 0 ) - return(cJSON_Parse("{\"error\":\"no coin\"}")); - if ( count == 0 ) - count = 100; - sprintf(buf,"[\"%s\", %d, %d, true]",coinaddr,count,skip); - return(bitcoin_json(coin,"listtransactions",buf)); -}*/ - cJSON *LP_validateaddress(char *symbol,char *address) { char buf[512],coinaddr[64],checkaddr[64],script[128]; int32_t i; uint8_t rmd160[20],addrtype; cJSON *retjson; struct iguana_info *coin; @@ -547,7 +313,7 @@ cJSON *LP_validateaddress(char *symbol,char *address) } bitcoin_address(coinaddr,coin->taddr,coin->pubtype,G.LP_myrmd160,20); jadd(retjson,"ismine",strcmp(address,coin->smartaddr) == 0 ? cJSON_CreateTrue() : cJSON_CreateFalse()); - jadd(retjson,"iswatchonly",cJSON_CreateFalse()); + jadd(retjson,"iswatchonly",cJSON_CreateTrue()); jadd(retjson,"isscript",addrtype == coin->p2shtype ? cJSON_CreateTrue() : cJSON_CreateFalse()); return(retjson); } @@ -560,12 +326,12 @@ cJSON *LP_validateaddress(char *symbol,char *address) int32_t LP_address_ismine(char *symbol,char *address) { - int32_t doneflag = 0; cJSON *retjson; + int32_t doneflag = 0; cJSON *retjson,*obj; if ( symbol == 0 || symbol[0] == 0 ) return(0); if ( (retjson= LP_validateaddress(symbol,address)) != 0 ) { - if ( jobj(retjson,"ismine") != 0 && is_cJSON_True(jobj(retjson,"ismine")) != 0 ) + if ( (obj= jobj(retjson,"ismine")) != 0 && is_cJSON_True(obj) != 0 ) { doneflag = 1; //printf("%s ismine (%s)\n",address,jprint(retjson,0)); @@ -576,6 +342,24 @@ int32_t LP_address_ismine(char *symbol,char *address) return(doneflag); } +int32_t LP_address_iswatchonly(char *symbol,char *address) +{ + int32_t doneflag = 0; cJSON *retjson,*obj; + if ( symbol == 0 || symbol[0] == 0 ) + return(0); + if ( (retjson= LP_validateaddress(symbol,address)) != 0 ) + { + if ( (obj= jobj(retjson,"iswatchonly")) != 0 && is_cJSON_True(obj) != 0 ) + { + doneflag = 1; + //printf("%s iswatchonly (%s)\n",address,jprint(retjson,0)); + } + //printf("%s\n",jprint(retjson,0)); + free_json(retjson); + } + return(doneflag); +} + int32_t LP_address_isvalid(char *symbol,char *address) { int32_t isvalid = 0; cJSON *retjson; @@ -594,38 +378,110 @@ int32_t LP_address_isvalid(char *symbol,char *address) return(isvalid); } -cJSON *LP_listunspent(char *symbol,char *coinaddr) +cJSON *LP_listunspent(char *symbol,char *coinaddr,bits256 reftxid,bits256 reftxid2) { - char buf[128]; cJSON *retjson; int32_t numconfs; struct iguana_info *coin; + char buf[128],*retstr; struct LP_address *ap; cJSON *retjson; int32_t numconfs,usecache=1; struct iguana_info *coin; if ( symbol == 0 || symbol[0] == 0 ) return(cJSON_Parse("{\"error\":\"null symbol\"}")); coin = LP_coinfind(symbol); - //printf("LP_listunspent.(%s %s)\n",symbol,coinaddr); if ( coin == 0 || (IAMLP == 0 && coin->inactive != 0) ) return(cJSON_Parse("{\"error\":\"no coin\"}")); if ( coin->electrum == 0 ) { - if ( LP_address_ismine(symbol,coinaddr) > 0 ) + if ( (ap= LP_addressfind(coin,coinaddr)) != 0 ) + { + if ( ap->unspenttime == 0 ) + usecache = 0; + else if ( G.LP_pendingswaps != 0 && time(NULL) > ap->unspenttime+1 ) + usecache = 0; + if ( usecache != 0 && (retstr= LP_unspents_filestr(symbol,coinaddr)) != 0 ) + { + retjson = cJSON_Parse(retstr); + free(retstr); + return(retjson); + } + } + //printf("%s %s usecache.%d iswatched.%d\n",coin->symbol,coinaddr,usecache,LP_address_iswatchonly(symbol,coinaddr)); + if ( LP_address_ismine(symbol,coinaddr) > 0 || LP_address_iswatchonly(symbol,coinaddr) > 0 ) { if ( strcmp(symbol,"BTC") == 0 ) numconfs = 0; else numconfs = 1; sprintf(buf,"[%d, 99999999, [\"%s\"]]",numconfs,coinaddr); - return(bitcoin_json(coin,"listunspent",buf)); +//printf("LP_listunspent.(%s %s)\n",symbol,coinaddr); + retjson = bitcoin_json(coin,"listunspent",buf); + retstr = jprint(retjson,0); + LP_unspents_cache(coin->symbol,coinaddr,retstr,1); + free(retstr); + if ( ap != 0 ) + ap->unspenttime = (uint32_t)time(NULL); + return(retjson); } else return(LP_address_utxos(coin,coinaddr,0)); - } else return(electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,1)); + } else return(electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,1,reftxid,reftxid2)); } -int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag) +cJSON *LP_listreceivedbyaddress(char *symbol,char *coinaddr) { - struct iguana_info *coin; int32_t n = 0; cJSON *retjson=0; char *retstr=0,destip[64]; uint16_t destport; + char buf[128],*addr; bits256 zero; cJSON *retjson,*array,*item; int32_t i,n; struct iguana_info *coin; + if ( symbol == 0 || symbol[0] == 0 ) + return(cJSON_Parse("{\"error\":\"null symbol\"}")); + coin = LP_coinfind(symbol); + if ( coin == 0 || (IAMLP == 0 && coin->inactive != 0) ) + return(cJSON_Parse("{\"error\":\"no coin\"}")); + memset(zero.bytes,0,sizeof(zero)); + if ( coin->electrum == 0 ) + { + sprintf(buf,"[1, false, true]"); + if ( (array= bitcoin_json(coin,"listreceivedbyaddress",buf)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; ielectrum,&retjson,coinaddr,zero)); +} + +int64_t LP_listunspent_parseitem(struct iguana_info *coin,bits256 *txidp,int32_t *voutp,int32_t *heightp,cJSON *item) +{ + int64_t satoshis = 0; + if ( coin->electrum == 0 ) + { + *txidp = jbits256(item,"txid"); + *voutp = juint(item,"vout"); + satoshis = LP_value_extract(item,0); + *heightp = LP_txheight(coin,*txidp); + } + else + { + *txidp = jbits256(item,"tx_hash"); + *voutp = juint(item,"tx_pos"); + satoshis = j64bits(item,"value"); + *heightp = jint(item,"height"); + } + return(satoshis); +} + +int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag,bits256 reftxid,bits256 reftxid2) +{ + struct iguana_info *coin; struct LP_address *ap; int32_t n = 0; cJSON *retjson=0; char *retstr=0; if ( symbol == 0 || symbol[0] == 0 ) return(0); if ( (coin= LP_coinfind(symbol)) != 0 ) { if ( coin->electrum != 0 ) { - if ( (retjson= electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,1)) != 0 ) + if ( (retjson= electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,fullflag,reftxid,reftxid2)) != 0 ) { n = cJSON_GetArraySize(retjson); //printf("LP_listunspent_issue.%s %s.%d %s\n",symbol,coinaddr,n,jprint(retjson,0)); @@ -633,29 +489,14 @@ int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag) } else { - if ( strcmp(coin->smartaddr,coinaddr) == 0 ) - { - retjson = LP_listunspent(symbol,coinaddr); - //printf("SELF_LISTUNSPENT.(%s %s)\n",symbol,coinaddr); - } - else if ( IAMLP == 0 ) - { - printf("LP_listunspent_query.(%s %s)\n",symbol,coinaddr); - LP_listunspent_query(coin->symbol,coin->smartaddr); - if ( fullflag != 0 ) - { - if ( (destport= LP_randpeer(destip)) > 0 ) - { - retstr = issue_LP_listunspent(destip,destport,symbol,coinaddr); - //printf("issue %s %s %s -> (%s)\n",coin->symbol,coinaddr,destip,retstr); - retjson = cJSON_Parse(retstr); - } else printf("LP_listunspent_issue couldnt get a random peer?\n"); - } - } + if ( fullflag == 2 && (ap= LP_addressfind(coin,coinaddr)) != 0 ) + ap->unspenttime = 0; + retjson = LP_listunspent(symbol,coinaddr,reftxid,reftxid2); + coin->numutxos = cJSON_GetArraySize(retjson); if ( retjson != 0 ) { n = cJSON_GetArraySize(retjson); - if ( electrum_process_array(coin,0,coinaddr,retjson,1) != 0 ) + if ( electrum_process_array(coin,0,coinaddr,retjson,1,reftxid,reftxid2) != 0 ) { //LP_postutxos(symbol,coinaddr); // might be good to not saturate } @@ -714,10 +555,10 @@ int32_t LP_importaddress(char *symbol,char *address) if ( coin->electrum != 0 ) { /*if ( (retjson= electrum_address_subscribe(symbol,coin->electrum,&retjson,address)) != 0 ) - { - printf("importaddress.(%s) -> %s\n",address,jprint(retjson,0)); - free_json(retjson); - }*/ + { + printf("importaddress.(%s) -> %s\n",address,jprint(retjson,0)); + free_json(retjson); + }*/ return(0); } else @@ -747,11 +588,21 @@ int32_t LP_importaddress(char *symbol,char *address) double _LP_getestimatedrate(struct iguana_info *coin) { - char buf[512],*retstr; cJSON *errjson; double rate = 0.00000020; + char buf[512],*retstr=0; int32_t numblocks; cJSON *errjson,*retjson; double rate = 0.00000020; if ( coin->rate < 0. || time(NULL) > coin->ratetime+30 ) { - sprintf(buf,"[%d]",strcmp(coin->symbol,"BTC") == 0 ? 6 : 2); - if ( (retstr= LP_apicall(coin,coin->electrum==0?"estimatefee" : "blockchain.estimatefee",buf)) != 0 ) + numblocks = strcmp(coin->symbol,"BTC") == 0 ? 6 : 2; + if ( coin->electrum == 0 ) + { + sprintf(buf,"[%d]",numblocks); + retstr = LP_apicall(coin,"estimatefee",buf); + } + else + { + if ( (retjson= electrum_estimatefee(coin->symbol,coin->electrum,&retjson,numblocks)) != 0 ) + retstr = jprint(retjson,1); + } + if ( retstr != 0 ) { if ( retstr[0] == '{' && (errjson= cJSON_Parse(retstr)) != 0 ) { @@ -764,16 +615,16 @@ double _LP_getestimatedrate(struct iguana_info *coin) rate = atof(retstr) / 1024.; if ( rate < 0.00000020 ) rate = 0.00000020; - rate *= 1.1; + rate *= 1.5; if ( coin->electrum != 0 ) - rate *= 1.667; + rate *= 1.5; if ( fabs(rate - coin->rate) > SMALLVAL ) printf("t%u estimated rate.(%s) (%s) -> %.8f %.8f\n",coin->ratetime,coin->symbol,retstr,rate,coin->rate); coin->rate = rate; coin->ratetime = (uint32_t)time(NULL); } free(retstr); - } + } else rate = coin->rate; } else rate = coin->rate; return(rate); } @@ -808,7 +659,7 @@ char *LP_sendrawtransaction(char *symbol,char *signedtx) jaddistr(array,signedtx); paramstr = jprint(array,1); retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"sendrawtransaction",paramstr); - printf(">>>>>>>>>>> %s dpow_sendrawtransaction.(%s) -> (%s)\n",coin->symbol,paramstr,retstr); + //printf(">>>>>>>>>>> %s dpow_sendrawtransaction.(%s) -> (%s)\n",coin->symbol,paramstr,retstr); free(paramstr); } else @@ -825,6 +676,7 @@ char *LP_sendrawtransaction(char *symbol,char *signedtx) errobj = cJSON_CreateObject(); jaddstr(errobj,"error","rejected"); jaddnum(errobj,"code",-27); + free(retstr); retstr = jprint(errobj,1); } else @@ -881,36 +733,38 @@ char *LP_signrawtx(char *symbol,bits256 *signedtxidp,int32_t *completedp,cJSON * return(jprint(retjson,1)); } return(signedtx); - - array = cJSON_CreateArray(); - jaddistr(array,rawtx); - jaddi(array,jduplicate(vins)); - jaddi(array,jduplicate(privkeys)); - paramstr = jprint(array,1); - //printf("signrawtransaction\n"); - if ( (retstr= bitcoind_passthru(symbol,coin->serverport,coin->userpass,"signrawtransaction",paramstr)) != 0 ) + if ( (0) ) { - if ( (json= cJSON_Parse(retstr)) != 0 ) + array = cJSON_CreateArray(); + jaddistr(array,rawtx); + jaddi(array,jduplicate(vins)); + jaddi(array,jduplicate(privkeys)); + paramstr = jprint(array,1); + //printf("signrawtransaction\n"); + if ( (retstr= bitcoind_passthru(symbol,coin->serverport,coin->userpass,"signrawtransaction",paramstr)) != 0 ) { - if ( (hexstr= jstr(json,"hex")) != 0 ) + if ( (json= cJSON_Parse(retstr)) != 0 ) { - len = (int32_t)strlen(hexstr); - signedtx = calloc(1,len+1); - strcpy(signedtx,hexstr); - *completedp = is_cJSON_True(jobj(json,"complete")); - len >>= 1; - data = malloc(len); - decode_hex(data,len,hexstr); - *signedtxidp = bits256_doublesha256(0,data,len); + if ( (hexstr= jstr(json,"hex")) != 0 ) + { + len = (int32_t)strlen(hexstr); + signedtx = calloc(1,len+1); + strcpy(signedtx,hexstr); + *completedp = is_cJSON_True(jobj(json,"complete")); + len >>= 1; + data = malloc(len); + decode_hex(data,len,hexstr); + *signedtxidp = bits256_doublesha256(0,data,len); + } + //else + printf("%s signrawtransaction.(%s) params.(%s)\n",coin->symbol,retstr,paramstr); + free_json(json); } - //else - printf("%s signrawtransaction.(%s) params.(%s)\n",coin->symbol,retstr,paramstr); - free_json(json); + free(retstr); } - free(retstr); + free(paramstr); + return(signedtx); } - free(paramstr); - return(signedtx); } cJSON *LP_getblock(char *symbol,bits256 txid) @@ -948,23 +802,25 @@ bits256 LP_getbestblockhash(struct iguana_info *coin) decode_hex(blockhash.bytes,sizeof(blockhash),retstr); free(retstr); } - } + } else printf("electrum mode doesnt support block level scanning\n"); return(blockhash); } char *LP_blockhashstr(char *symbol,int32_t height) { - cJSON *array; char *paramstr,*retstr; struct iguana_info *coin; + char params[64],*retstr; struct iguana_info *coin; //cJSON *array; if ( symbol == 0 || symbol[0] == 0 ) return(0); coin = LP_coinfind(symbol); if ( coin == 0 || coin->electrum != 0 ) return(0); - array = cJSON_CreateArray(); - jaddinum(array,height); - paramstr = jprint(array,1); - retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"getblockhash",paramstr); - free(paramstr); + //array = cJSON_CreateArray(); + //jaddinum(array,height); + //paramstr = jprint(array,1); + sprintf(params,"[%d]",height); + retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"getblockhash",params); + //free(paramstr); + //printf("blockhashstr.(%s)\n",retstr); return(retstr); } @@ -980,6 +836,37 @@ cJSON *LP_getblockhashstr(char *symbol,char *blockhashstr) return(bitcoin_json(coin,"getblock",buf)); } +uint32_t LP_heighttime(char *symbol,int32_t height) +{ + struct electrum_info *ep; uint32_t timestamp = 0; cJSON *retjson; char *blockhashstr; struct iguana_info *coin = LP_coinfind(symbol); + if ( coin != 0 ) + { + if ( (ep= coin->electrum) == 0 ) + { + if ( (blockhashstr= LP_blockhashstr(symbol,height)) != 0 ) + { + if ( (retjson= cJSON_Parse(blockhashstr)) != 0 ) + { + //printf("height.(%s)\n",jprint(retjson,0)); + timestamp = juint(retjson,"time"); + free_json(retjson); + } + free(blockhashstr); + } + } + else + { + if ( (retjson= electrum_getheader(coin->symbol,ep,&retjson,height)) != 0 ) + { + //printf("%s\n",jprint(retjson,0)); + timestamp = juint(retjson,"timestamp"); + free_json(retjson); + } + } + } + return(timestamp); +} + cJSON *LP_blockjson(int32_t *heightp,char *symbol,char *blockhashstr,int32_t height) { cJSON *json = 0; int32_t flag = 0; struct iguana_info *coin; @@ -1002,7 +889,7 @@ cJSON *LP_blockjson(int32_t *heightp,char *symbol,char *blockhashstr,int32_t hei *heightp = juint(json,"height"); if ( height >= 0 && *heightp != height ) { - printf("unexpected height %d vs %d for %s (%s)\n",*heightp,height,blockhashstr,jprint(json,0)); + //printf("unexpected height %d vs %d for %s (%s)\n",*heightp,height,blockhashstr,jprint(json,0)); *heightp = -1; free_json(json); json = 0; @@ -1083,10 +970,11 @@ const char *Notaries_elected[][2] = { "xxspot2_XX", "03d85b221ea72ebcd25373e7961f4983d12add66a92f899deaf07bab1d8b6f5573" } }; -int32_t LP_txhasnotarization(struct iguana_info *coin,bits256 txid) +int32_t LP_txhasnotarization(bits256 *notarizedhashp,struct iguana_info *coin,bits256 txid) { - cJSON *txobj,*vins,*vin,*vouts,*vout,*spentobj,*sobj; char *hexstr; uint8_t script[35]; bits256 spenttxid; uint64_t notarymask; int32_t i,j,numnotaries,len,spentvout,numvins,numvouts,hasnotarization = 0; - if ( (txobj= LP_gettx(coin->symbol,txid)) != 0 ) + cJSON *txobj,*vins,*vin,*vouts,*vout,*spentobj,*sobj; char *hexstr; uint8_t script[1024]; bits256 spenttxid; uint64_t notarymask; int32_t i,j,numnotaries,len,spentvout,numvins,numvouts,hasnotarization = 0; + memset(notarizedhashp,0,sizeof(*notarizedhashp)); + if ( (txobj= LP_gettx(coin->symbol,txid,0)) != 0 ) { if ( (vins= jarray(&numvins,txobj,"vin")) != 0 ) { @@ -1098,14 +986,14 @@ int32_t LP_txhasnotarization(struct iguana_info *coin,bits256 txid) vin = jitem(vins,i); spenttxid = jbits256(vin,"txid"); spentvout = jint(vin,"vout"); - if ( (spentobj= LP_gettx(coin->symbol,spenttxid)) != 0 ) + if ( (spentobj= LP_gettx(coin->symbol,spenttxid,0)) != 0 ) { if ( (vouts= jarray(&numvouts,spentobj,"vout")) != 0 ) { if ( spentvout < numvouts ) { vout = jitem(vouts,spentvout); - if ( (sobj= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(sobj,"hex")) != 0 && (len= is_hexstr(hexstr,0)) == sizeof(script)*2 ) + if ( (sobj= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(sobj,"hex")) != 0 && (len= is_hexstr(hexstr,0)) == 35*2 ) { len >>= 1; decode_hex(script,len,hexstr); @@ -1139,20 +1027,76 @@ int32_t LP_txhasnotarization(struct iguana_info *coin,bits256 txid) } } } + if ( (vouts= jarray(&numvouts,txobj,"vout")) != 0 ) + { + vout = jitem(vouts,1); + if ( (sobj= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(sobj,"hex")) != 0 && (len= is_hexstr(hexstr,0)) >= 35 ) + { + len >>= 1; + decode_hex(script,len,hexstr); + iguana_rwbignum(0,&script[2],32,(uint8_t *)notarizedhashp); + } + } free_json(txobj); } return(hasnotarization); } +int32_t LP_notarization_validate(char *symbol,int32_t notarized,bits256 notarizedhash,bits256 notarizationtxid) +{ + struct iguana_info *coin; int32_t valid = 0; cJSON *blockjson; bits256 notarizedhash2; char str[65],str2[65]; + if ( strcmp(symbol,"KMD") == 0 ) + coin = LP_coinfind("BTC"); + else coin = LP_coinfind("KMD"); + if ( coin != 0 ) + { + if (LP_txhasnotarization(¬arizedhash2,coin,notarizationtxid) == 0 ) + { + printf("missing %s notarization txid %s\n",symbol,bits256_str(str,notarizationtxid)); + return(-1); + } + else if ( bits256_cmp(notarizedhash,notarizedhash2) != 0 ) + { + printf("mismatched %s notarizedhash %s vs %s\n",symbol,bits256_str(str,notarizedhash),bits256_str(str2,notarizedhash2)); + return(-1); + } + } + if ( (coin= LP_coinfind(symbol)) != 0 ) + { + if ( coin->electrum == 0 ) + { + if ( (blockjson= LP_getblock(coin->symbol,notarizedhash)) != 0 ) + { + if ( jint(blockjson,"height") != notarized ) + valid = 1; + free_json(blockjson); + } + } + else + { + if ( (blockjson= electrum_getheader(symbol,coin->electrum,&blockjson,notarized+1)) != 0 ) + { + notarizedhash2 = jbits256(blockjson,"prev_block_hash"); + if ( bits256_cmp(notarizedhash,notarizedhash2) == 0 ) + valid = 1; + free_json(blockjson); + } + } + } + if ( valid == 1 ) + return(0); + else return(-1); +} + int32_t LP_hasnotarization(struct iguana_info *coin,cJSON *blockjson) { - int32_t i,n,hasnotarization = 0; bits256 txid; cJSON *txarray; + int32_t i,n,hasnotarization = 0; bits256 txid,notarizedhash; cJSON *txarray; if ( (txarray= jarray(&n,blockjson,"tx")) != 0 ) { for (i=0; isymbol,height,numtx); for (iter=0; iter<2; iter++) { txobj = 0; @@ -127,7 +128,7 @@ int sort_balance(void *a,void *b) cJSON *LP_snapshot(struct iguana_info *coin,int32_t height) { - static bits256 bannedarray[64]; static int32_t numbanned,indallvouts,maxsnapht; static char lastcoin[16]; + static bits256 bannedarray[64]; static int32_t numbanned,indallvouts,maxsnapht; static char lastcoin[65]; struct LP_transaction *tx,*tmp; struct LP_address *ap,*atmp; int32_t isKMD,i,j,n,skipflag=0,startht,endht,ht; uint64_t banned_balance=0,balance=0,noaddr_balance=0; cJSON *retjson,*array,*item; if ( bannedarray[0].txid == 0 ) numbanned = komodo_bannedset(&indallvouts,bannedarray,(int32_t)(sizeof(bannedarray)/sizeof(*bannedarray))); @@ -413,10 +414,11 @@ int32_t LP_spendsearch(char *coinaddr,bits256 *spendtxidp,int32_t *indp,char *sy int32_t LP_mempoolscan(char *symbol,bits256 searchtxid) { - int32_t i,n; cJSON *array,*txobj; bits256 txid; struct iguana_info *coin; struct LP_transaction *tx; + int32_t i,n; cJSON *array,*txobj; bits256 txid,zero; struct iguana_info *coin; struct LP_transaction *tx; if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 || coin->electrum != 0 ) return(-1); - if ( (array= LP_getmempool(symbol,0)) != 0 ) + memset(zero.bytes,0,sizeof(zero)); + if ( (array= LP_getmempool(symbol,0,searchtxid,zero)) != 0 ) { if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) { @@ -444,7 +446,7 @@ int32_t LP_mempoolscan(char *symbol,bits256 searchtxid) int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t duration) { - struct iguana_info *coin; cJSON *array,*item; uint32_t expiration,i,n; int32_t numconfirms = -1; + struct iguana_info *coin; bits256 zero; cJSON *array,*item; uint32_t expiration,i,n; int32_t numconfirms = -1; if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) { printf("LP_waitmempool missing coin.%p or inactive\n",coin); @@ -464,9 +466,10 @@ int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int } else { - if ( (array= electrum_address_getmempool(symbol,coin->electrum,&array,coinaddr)) != 0 ) + memset(zero.bytes,0,sizeof(zero)); + if ( (array= electrum_address_getmempool(symbol,coin->electrum,&array,coinaddr,txid,zero)) != 0 ) { - char str[65]; printf("check %s mempool.(%s)\n",bits256_str(str,txid),jprint(array,0)); + //char str[65]; printf("check %s mempool.(%s)\n",bits256_str(str,txid),jprint(array,0)); if ( (n= cJSON_GetArraySize(array)) > 0 ) { for (i=0; isymbol,coinaddr,1); + LP_listunspent_issue(coin->symbol,coinaddr,1,txid,zero); struct LP_address_utxo *up; if ( (up= LP_address_utxofind(coin,coinaddr,txid,vout)) != 0 ) { char str[65]; printf("address_utxofind found confirmed %s %s %s ht.%d vs %d\n",symbol,coinaddr,bits256_str(str,txid),up->U.height,coin->height); - if ( coin->electrum != 0 && (array= electrum_address_gethistory(symbol,coin->electrum,&array,coinaddr)) != 0 ) + if ( coin->electrum != 0 && (array= electrum_address_gethistory(symbol,coin->electrum,&array,coinaddr,txid)) != 0 ) free_json(array); if ( coin->height >= up->U.height ) numconfirms = (coin->height - up->U.height + 1); @@ -512,7 +515,7 @@ int32_t LP_mempool_vinscan(bits256 *spendtxidp,int32_t *spendvinp,char *symbol,c return(-1); if ( time(NULL) > coin->lastmempool+LP_MEMPOOL_TIMEINCR ) { - if ( (array= LP_getmempool(symbol,coinaddr)) != 0 ) + if ( (array= LP_getmempool(symbol,coinaddr,searchtxid,searchtxid2)) != 0 ) { free_json(array); coin->lastmempool = (uint32_t)time(NULL); diff --git a/iguana/exchanges/LP_signatures.c b/iguana/exchanges/LP_signatures.c index be24aae78..668551325 100644 --- a/iguana/exchanges/LP_signatures.c +++ b/iguana/exchanges/LP_signatures.c @@ -35,7 +35,7 @@ struct basilisk_request *LP_requestinit(struct basilisk_request *rp,bits256 srch rp->desthash = desthash; rp->destamount = destsatoshis; rp->quoteid = basilisk_quoteid(rp); - printf("r.%u %u, q.%u %u: %s %.8f -> %s %.8f\n",rp->timestamp,rp->requestid,rp->quotetime,rp->quoteid,rp->src,dstr(rp->srcamount),rp->dest,dstr(rp->destamount)); + //printf("r.%u %u, q.%u %u: %s %.8f -> %s %.8f\n",rp->timestamp,rp->requestid,rp->quotetime,rp->quoteid,rp->src,dstr(rp->srcamount),rp->dest,dstr(rp->destamount)); return(rp); } @@ -44,6 +44,7 @@ cJSON *LP_quotejson(struct LP_quoteinfo *qp) double price; cJSON *retjson = cJSON_CreateObject(); jaddstr(retjson,"gui",qp->gui[0] != 0 ? qp->gui : LP_gui); jadd64bits(retjson,"aliceid",qp->aliceid); + jaddnum(retjson,"tradeid",qp->tradeid); jaddstr(retjson,"base",qp->srccoin); jaddstr(retjson,"rel",qp->destcoin); if ( qp->coinaddr[0] != 0 ) @@ -103,12 +104,14 @@ cJSON *LP_quotejson(struct LP_quoteinfo *qp) int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson) { uint32_t rid,qid; + memset(qp,0,sizeof(*qp)); safecopy(qp->gui,LP_gui,sizeof(qp->gui)); safecopy(qp->srccoin,jstr(argjson,"base"),sizeof(qp->srccoin)); safecopy(qp->coinaddr,jstr(argjson,"address"),sizeof(qp->coinaddr)); safecopy(qp->destcoin,jstr(argjson,"rel"),sizeof(qp->destcoin)); safecopy(qp->destaddr,jstr(argjson,"destaddr"),sizeof(qp->destaddr)); qp->aliceid = j64bits(argjson,"aliceid"); + qp->tradeid = juint(argjson,"tradeid"); qp->timestamp = juint(argjson,"timestamp"); qp->quotetime = juint(argjson,"quotetime"); qp->txid = jbits256(argjson,"txid"); @@ -129,14 +132,16 @@ int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson) qp->R.quoteid = juint(argjson,"quoteid"); if ( qp->R.requestid == 0 ) { - rid= basilisk_requestid(&qp->R); - //printf("requestid.%u -> %u\n",qp->R.requestid,rid); + rid = basilisk_requestid(&qp->R); + if ( qp->R.requestid != 0 && qp->R.requestid != rid ) + printf("requestid.%u -> %u\n",qp->R.requestid,rid); qp->R.requestid = rid; } if ( qp->R.quoteid == 0 ) { - qid= basilisk_quoteid(&qp->R); - //printf("quoteid.%u -> %u\n",qp->R.quoteid,qid); + qid = basilisk_quoteid(&qp->R); + if ( qp->R.quoteid != 0 && qp->R.quoteid != qid ) + printf("quoteid.%u -> %u\n",qp->R.quoteid,qid); qp->R.quoteid = qid; } return(0); @@ -146,7 +151,7 @@ void LP_txfees(uint64_t *txfeep,uint64_t *desttxfeep,char *base,char *rel) { *txfeep = LP_txfeecalc(LP_coinfind(base),0,0); *desttxfeep = LP_txfeecalc(LP_coinfind(rel),0,0); - printf("LP_txfees(%.8f %.8f)\n",dstr(*txfeep),dstr(*desttxfeep)); + //printf("LP_txfees(%.8f %.8f)\n",dstr(*txfeep),dstr(*desttxfeep)); } int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char *destcoin,double price,uint64_t satoshis,uint64_t destsatoshis) @@ -189,15 +194,15 @@ int32_t LP_quotedestinfo(struct LP_quoteinfo *qp,bits256 desttxid,int32_t destvo return(0); } -char *LP_quotereceived(cJSON *argjson) +char *LP_quotereceived(struct LP_quoteinfo *qp) { - struct LP_cacheinfo *ptr; double price; struct LP_quoteinfo Q; - LP_quoteparse(&Q,argjson); - price = (double)Q.destsatoshis / (Q.satoshis - Q.txfee); - if ( (ptr= LP_cacheadd(Q.srccoin,Q.destcoin,Q.txid,Q.vout,price,&Q)) != 0 ) + struct LP_cacheinfo *ptr; double price; + //LP_quoteparse(&Q,argjson); + price = (double)qp->destsatoshis / (qp->satoshis - qp->txfee); + if ( (ptr= LP_cacheadd(qp->srccoin,qp->destcoin,qp->txid,qp->vout,price,qp)) != 0 ) { - ptr->Q = Q; - printf(">>>>>>>>>> received quote %s/%s %.8f\n",Q.srccoin,Q.destcoin,price); + ptr->Q = *qp; + printf(">>>>>>>>>> received quote %s/%s %.8f\n",qp->srccoin,qp->destcoin,price); return(clonestr("{\"result\":\"updated\"}")); } else return(clonestr("{\"error\":\"nullptr\"}")); } @@ -271,7 +276,7 @@ bits256 LP_utxos_sighash(uint32_t timestamp,uint8_t *pubsecp,bits256 pubkey,bits int32_t LP_utxos_sigcheck(uint32_t timestamp,char *sigstr,char *pubsecpstr,bits256 pubkey,bits256 utxoshash) { - static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash; char str[65]; struct LP_pubkeyinfo *pubp; + static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash; char str[65]; struct LP_pubkey_info *pubp; if ( ctx == 0 ) ctx = bitcoin_ctx(); pubp = LP_pubkeyfind(pubkey); @@ -284,11 +289,12 @@ int32_t LP_utxos_sigcheck(uint32_t timestamp,char *sigstr,char *pubsecpstr,bits2 if ( memcmp(pub33,pubsecp,33) != 0 || retval != 0 ) { static uint32_t counter; - if ( counter++ < 10 ) + if ( counter++ <= LP_MAXPUBKEY_ERRORS ) { if ( pubp != 0 ) pubp->numerrors++; - printf("LP_utxos_sigcheck failure.%d, probably from %s with older version\n",pubp!=0?pubp->numerrors:-1,bits256_str(str,pubkey)); + if ( pubp != 0 && pubp->numerrors > LP_MAXPUBKEY_ERRORS/2 ) + printf("LP_utxos_sigcheck failure.%d, probably from %s with older version\n",pubp!=0?pubp->numerrors:-1,bits256_str(str,pubkey)); } retval = -1; } else retval = 0; @@ -324,6 +330,7 @@ int32_t LP_utxos_sigadd(cJSON *item,uint32_t timestamp,bits256 priv,uint8_t *pub void LP_postutxos(char *symbol,char *coinaddr) { bits256 zero; uint32_t timestamp; bits256 utxoshash; char pubsecpstr[67]; struct iguana_info *coin; cJSON *array,*reqjson = cJSON_CreateObject(); +return; if ( (coin= LP_coinfind(symbol)) != 0 && (array= LP_address_utxos(coin,coinaddr,1)) != 0 ) { //printf("LP_postutxos pubsock.%d %s %s\n",pubsock,symbol,coin->smartaddr); @@ -345,70 +352,14 @@ void LP_postutxos(char *symbol,char *coinaddr) //char str[65]; printf("utxoshash add %s\n",bits256_str(str,utxoshash)); LP_utxos_sigadd(reqjson,timestamp,G.LP_privkey,G.LP_pubsecp,G.LP_mypub25519,utxoshash); //printf("post (%s) -> %d\n",msg,LP_mypubsock); - LP_reserved_msg(symbol,symbol,zero,jprint(reqjson,1)); - } - } -} - -queue_t utxosQ; -struct LP_utxos_qitem { struct queueitem DL; cJSON *argjson; }; - -char *LP_postutxos_recv(cJSON *argjson) -{ - struct LP_utxos_qitem *uitem; struct iguana_info *coin; char *coinaddr,*symbol; bits256 utxoshash,pubkey; cJSON *obj; struct LP_pubkeyinfo *pubp; - pubkey = jbits256(argjson,"pubkey"); - pubp = LP_pubkeyfind(pubkey); - if ( pubp != 0 && pubp->numerrors > LP_MAXPUBKEY_ERRORS ) - return(clonestr("{\"error\":\"blacklisted\"}")); - if ( (coinaddr= jstr(argjson,"coinaddr")) != 0 && (symbol= jstr(argjson,"coin")) != 0 && (coin= LP_coinfind(symbol)) != 0 ) - { - if ( strcmp(coinaddr,coin->smartaddr) == 0 ) - { - //printf("ignore my utxo from external source %s %s\n",symbol,coinaddr); - return(clonestr("{\"result\":\"success\"}")); - } - } - if ( (obj= jobj(argjson,"utxos")) != 0 ) - { - utxoshash = LP_utxoshash_calc(obj); - //char str[65]; printf("got utxoshash %s\n",bits256_str(str,utxoshash)); - if ( LP_utxos_sigcheck(juint(argjson,"timestamp"),jstr(argjson,"sig"),jstr(argjson,"pubsecp"),pubkey,utxoshash) == 0 ) - { - uitem = calloc(1,sizeof(*uitem)); - uitem->argjson = jduplicate(argjson); - queue_enqueue("utxosQ",&utxosQ,&uitem->DL); - return(clonestr("{\"result\":\"success\"}")); + LP_reserved_msg(0,symbol,symbol,zero,jprint(reqjson,1)); } } - return(clonestr("{\"error\":\"sig failure\"}")); -} - -int32_t LP_utxosQ_process() -{ - struct LP_utxos_qitem *uitem; int32_t n; char *symbol,*coinaddr; struct LP_address *ap; struct iguana_info *coin; cJSON *array; - if ( (uitem= queue_dequeue(&utxosQ)) != 0 ) - { - //printf("LP_utxosQ_process.(%s)\n",jprint(uitem->argjson,0)); - if ( (coinaddr= jstr(uitem->argjson,"coinaddr")) != 0 && (symbol= jstr(uitem->argjson,"coin")) != 0 && (coin= LP_coinfind(symbol)) != 0 ) // addsig - { - if ( coin->electrum == 0 || (ap= LP_addressfind(coin,coinaddr)) != 0 ) - { - if ( (array= jarray(&n,uitem->argjson,"utxos")) != 0 ) - LP_unspents_array(coin,coinaddr,array); - } - else if ( (array= electrum_address_listunspent(symbol,coin->electrum,&array,coinaddr,1)) != 0 ) - free_json(array); - } - free_json(uitem->argjson); - free(uitem); - return(1); - } - return(0); } int32_t LP_price_sigcheck(uint32_t timestamp,char *sigstr,char *pubsecpstr,bits256 pubkey,char *base,char *rel,uint64_t price64) { - static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash; struct LP_pubkeyinfo *pubp; + static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash; struct LP_pubkey_info *pubp; if ( ctx == 0 ) ctx = bitcoin_ctx(); pubp = LP_pubkeyfind(pubkey); @@ -443,9 +394,10 @@ int32_t LP_price_sigadd(cJSON *item,uint32_t timestamp,bits256 priv,uint8_t *pub char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *rel,double price) { - struct iguana_info *basecoin,*relcoin; char pubsecpstr[67]; uint32_t timestamp; uint64_t price64; bits256 zero; cJSON *reqjson = cJSON_CreateObject(); + struct iguana_info *basecoin,*relcoin,*kmd; struct LP_address *ap; char pubsecpstr[67]; uint32_t numutxos,timestamp; uint64_t price64,balance,minsize,maxsize; bits256 zero; cJSON *reqjson; + reqjson = cJSON_CreateObject(); // LP_addsig - if ( (basecoin= LP_coinfind(base)) != 0 && (relcoin= LP_coinfind(rel)) != 0 && basecoin->electrum == 0 && relcoin->electrum == 0 ) + if ( (basecoin= LP_coinfind(base)) != 0 && (relcoin= LP_coinfind(rel)) != 0 )//&& basecoin->electrum == 0 )//&& relcoin->electrum == 0 ) { memset(zero.bytes,0,sizeof(zero)); jaddbits256(reqjson,"pubkey",G.LP_mypub25519); @@ -459,8 +411,19 @@ char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *re jaddnum(reqjson,"timestamp",timestamp); init_hexbytes_noT(pubsecpstr,G.LP_pubsecp,33); jaddstr(reqjson,"pubsecp",pubsecpstr); + if ( (kmd= LP_coinfind("KMD")) != 0 && (ap= LP_address(kmd,kmd->smartaddr)) != 0 && ap->instantdex_credits != 0 ) + jaddnum(reqjson,"credits",dstr(ap->instantdex_credits)); + if ( (numutxos= LP_address_minmax(&balance,&minsize,&maxsize,basecoin,basecoin->smartaddr)) != 0 ) + { + //printf("send %s numutxos.%d balance %.8f min %.8f max %.8f\n",base,numutxos,dstr(balance),dstr(minsize),dstr(maxsize)); + jaddstr(reqjson,"utxocoin",base); + jaddnum(reqjson,"n",numutxos); + jaddnum(reqjson,"bal",dstr(balance)); + jaddnum(reqjson,"min",dstr(minsize)); + jaddnum(reqjson,"max",dstr(maxsize)); + } LP_price_sigadd(reqjson,timestamp,G.LP_privkey,G.LP_pubsecp,G.LP_mypub25519,base,rel,price64); - LP_reserved_msg(base,rel,zero,jprint(reqjson,1)); + LP_reserved_msg(0,base,rel,zero,jprint(reqjson,1)); return(clonestr("{\"result\":\"success\"}")); } else return(clonestr("{\"error\":\"electrum node cant post bob asks\"}")); } @@ -476,9 +439,15 @@ char *LP_postprice_recv(cJSON *argjson) { if ( LP_price_sigcheck(juint(argjson,"timestamp"),jstr(argjson,"sig"),jstr(argjson,"pubsecp"),pubkey,base,rel,j64bits(argjson,"price64")) == 0 ) { - LP_pricefeedupdate(pubkey,base,rel,price); + //printf("call pricefeed update\n"); + LP_pricefeedupdate(pubkey,base,rel,price,jstr(argjson,"utxocoin"),jint(argjson,"n"),jdouble(argjson,"bal")*SATOSHIDEN,jdouble(argjson,"min")*SATOSHIDEN,jdouble(argjson,"max")*SATOSHIDEN,jdouble(argjson,"credits")*SATOSHIDEN); return(clonestr("{\"result\":\"success\"}")); - } else return(clonestr("{\"error\":\"sig failure\"}")); + } + else + { + printf("sig failure\n"); + return(clonestr("{\"error\":\"sig failure\"}")); + } } } return(clonestr("{\"error\":\"missing fields in posted price\"}")); @@ -500,7 +469,7 @@ int32_t LP_pubkey_sigadd(cJSON *item,uint32_t timestamp,bits256 priv,bits256 pub return(LP_bitcoinsig_add(item,priv,pubsecp,sighash)); } -int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *pubp,cJSON *item) +int32_t LP_pubkey_sigcheck(struct LP_pubkey_info *pubp,cJSON *item) { int32_t i,len,siglen,retval=-1; uint8_t rmd160[20],checkrmd160[20],pubsecp[33],sig[65],zeroes[20]; char *sigstr,*hexstr,*pubsecpstr; if ( (hexstr= jstr(item,"rmd160")) != 0 && strlen(hexstr) == 2*sizeof(rmd160) ) @@ -525,20 +494,20 @@ int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *pubp,cJSON *item) { if ( memcmp(rmd160,pubp->rmd160,20) != 0 ) { - for (i=0; i<20; i++) - printf("%02x",pubp->rmd160[i]); + //for (i=0; i<20; i++) + // printf("%02x",pubp->rmd160[i]); memcpy(pubp->rmd160,rmd160,sizeof(pubp->rmd160)); memcpy(pubp->pubsecp,pubsecp,sizeof(pubp->pubsecp)); memcpy(pubp->sig,sig,sizeof(pubp->sig)); pubp->siglen = siglen; - char str[65]; printf(" -> rmd160.(%s) for %s (%s) sig.%s\n",hexstr,bits256_str(str,pubp->pubkey),pubsecpstr,sigstr); - pubp->timestamp = (uint32_t)time(NULL); + //char str[65]; printf(" -> rmd160.(%s) for %s (%s) sig.%s\n",hexstr,bits256_str(str,pubp->pubkey),pubsecpstr,sigstr); } + pubp->timestamp = juint(item,"timestamp"); retval = 0; } else pubp->numerrors++; } } - else + else if ( 0 ) { for (i=0; i<20; i++) printf("%02x",rmd160[i]); @@ -548,7 +517,7 @@ int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *pubp,cJSON *item) printf(" for %s\n",pubsecpstr); } } - }// else pubp->timestamp = (uint32_t)time(NULL); + } } } return(retval); @@ -556,7 +525,7 @@ int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *pubp,cJSON *item) void LP_notify_pubkeys(void *ctx,int32_t pubsock) { - bits256 zero; uint32_t timestamp; char secpstr[67]; cJSON *reqjson = cJSON_CreateObject(); + bits256 zero; uint32_t timestamp; char LPipaddr[64],secpstr[67]; cJSON *reqjson = cJSON_CreateObject(); memset(zero.bytes,0,sizeof(zero)); jaddstr(reqjson,"method","notify"); jaddstr(reqjson,"rmd160",G.LP_myrmd160str); @@ -566,17 +535,42 @@ void LP_notify_pubkeys(void *ctx,int32_t pubsock) timestamp = (uint32_t)time(NULL); jaddnum(reqjson,"timestamp",timestamp); LP_pubkey_sigadd(reqjson,timestamp,G.LP_privkey,G.LP_mypub25519,G.LP_myrmd160,G.LP_pubsecp); - LP_reserved_msg("","",zero,jprint(reqjson,1)); + if ( IAMLP != 0 ) + { + if ( LP_rarestpeer(LPipaddr) != 0 ) + { + jaddstr(reqjson,"isLP",LPipaddr); + if ( strcmp(LPipaddr,LP_myipaddr) == 0 ) + jaddnum(reqjson,"ismine",1); + } + else printf("no LPipaddr\n"); + } + jaddnum(reqjson,"session",G.LP_sessionid); + LP_reserved_msg(0,"","",zero,jprint(reqjson,1)); } char *LP_notify_recv(cJSON *argjson) { - bits256 pub; struct LP_pubkeyinfo *pubp; + bits256 pub; struct LP_pubkey_info *pubp; char *ipaddr; pub = jbits256(argjson,"pub"); if ( bits256_nonz(pub) != 0 ) { if ( (pubp= LP_pubkeyadd(pub)) != 0 ) LP_pubkey_sigcheck(pubp,argjson); + if ( (ipaddr= jstr(argjson,"isLP")) != 0 ) + { + //printf("notify got isLP %s %d\n",ipaddr,jint(argjson,"ismine")); + LP_peer_recv(ipaddr,jint(argjson,"ismine")); + if ( IAMLP != 0 && G.LP_IAMLP == 0 && strcmp(ipaddr,LP_myipaddr) == 0 ) + { + if ( bits256_cmp(pub,G.LP_mypub25519) != 0 ) + { + char str[65]; printf("that's me! and it is from %s which isnt me\n",bits256_str(str,pub)); + G.LP_IAMLP = 1; + } + } + LP_addpeer(LP_mypeer,LP_mypubsock,ipaddr,RPC_port,RPC_port+10,RPC_port+20,1,juint(argjson,"session")); + } //char str[65]; printf("%.3f NOTIFIED pub %s rmd160 %s\n",OS_milliseconds()-millis,bits256_str(str,pub),rmd160str); } return(clonestr("{\"result\":\"success\",\"notify\":\"received\"}")); @@ -584,7 +578,8 @@ char *LP_notify_recv(cJSON *argjson) void LP_smartutxos_push(struct iguana_info *coin) { - struct LP_peerinfo *peer,*tmp; uint64_t value; bits256 zero,txid; int32_t i,vout,height,n; char *retstr; cJSON *array,*item,*req; + uint64_t value; bits256 zero,txid; int32_t i,vout,height,n; cJSON *array,*item,*req; +return; if ( coin->smartaddr[0] == 0 ) return; //LP_notify_pubkeys(coin->ctx,LP_mypubsock); @@ -601,14 +596,6 @@ void LP_smartutxos_push(struct iguana_info *coin) vout = jint(item,"tx_pos"); value = j64bits(item,"value"); height = jint(item,"height"); - if ( 0 && (rand() % 100) == 0 && IAMLP == 0 ) - { - HASH_ITER(hh,LP_peerinfos,peer,tmp) - { - if ( (retstr= issue_LP_uitem(peer->ipaddr,peer->port,coin->symbol,coin->smartaddr,txid,vout,height,value)) != 0 ) - free(retstr); - } - } req = cJSON_CreateObject(); jaddstr(req,"method","uitem"); jaddstr(req,"coin",coin->symbol); @@ -618,7 +605,7 @@ void LP_smartutxos_push(struct iguana_info *coin) jaddnum(req,"ht",height); jadd64bits(req,"value",value); //printf("ADDR_UNSPENTS[] <- %s\n",jprint(req,0)); - LP_reserved_msg("","",zero,jprint(req,1)); + LP_reserved_msg(0,"","",zero,jprint(req,1)); } } free_json(array); @@ -628,6 +615,7 @@ void LP_smartutxos_push(struct iguana_info *coin) char *LP_uitem_recv(cJSON *argjson) { bits256 txid; int32_t vout,height; uint64_t value; struct iguana_info *coin; char *coinaddr,*symbol; +printf("LP_uitem_recv deprecated\n"); txid = jbits256(argjson,"txid"); vout = jint(argjson,"vout"); height = jint(argjson,"ht"); @@ -637,7 +625,7 @@ char *LP_uitem_recv(cJSON *argjson) { //char str[65]; printf("uitem %s %s %s/v%d %.8f ht.%d\n",symbol,coinaddr,bits256_str(str,txid),vout,dstr(value),height); if ( strcmp(coin->smartaddr,coinaddr) != 0 ) - LP_address_utxoadd("LP_uitem_recv",coin,coinaddr,txid,vout,value,height,-1); + LP_address_utxoadd((uint32_t)time(NULL),"LP_uitem_recv",coin,coinaddr,txid,vout,value,height,-1); //else printf("ignore external uitem %s %s\n",symbol,coin->smartaddr); } return(clonestr("{\"result\":\"success\"}")); @@ -650,16 +638,19 @@ void LP_listunspent_query(char *symbol,char *coinaddr) jaddstr(reqjson,"method","addr_unspents"); jaddstr(reqjson,"coin",symbol); jaddstr(reqjson,"address",coinaddr); - LP_reserved_msg("","",zero,jprint(reqjson,1)); + LP_reserved_msg(0,"","",zero,jprint(reqjson,1)); } void LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct LP_quoteinfo *qp) { - cJSON *reqjson; bits256 zero; char *msg,*msg2; int32_t flag = 0; struct LP_utxoinfo *utxo; + cJSON *reqjson; bits256 zero; char *msg; struct iguana_info *coin; int32_t flag = 0; if ( strcmp(method,"request") == 0 ) { - if ( (utxo= LP_utxofind(0,qp->desttxid,qp->destvout)) != 0 && LP_ismine(utxo) > 0 && LP_isavailable(utxo) > 0 ) - LP_unavailableset(utxo,qp->srchash); + if ( LP_allocated(qp->desttxid,qp->destvout) == 0 && LP_allocated(qp->feetxid,qp->feevout) == 0 ) + { + LP_unavailableset(qp->desttxid,qp->destvout,qp->timestamp+LP_AUTOTRADE_TIMEOUT*4,qp->srchash); + LP_unavailableset(qp->feetxid,qp->feevout,qp->timestamp+LP_AUTOTRADE_TIMEOUT*4,qp->srchash); + } else { printf("couldnt find my txid to make request\n"); @@ -671,19 +662,33 @@ void LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct LP_ flag = 1; jaddbits256(reqjson,"pubkey",qp->srchash); jaddstr(reqjson,"method",method); - jaddnum(reqjson,"timestamp",time(NULL)); + if ( jobj(reqjson,"timestamp") == 0 ) + jaddnum(reqjson,"timestamp",time(NULL)); + if ( strcmp(method,"connect") == 0 ) + { + if ( (coin= LP_coinfind("KMD")) != 0 ) + jadd(reqjson,"proof",LP_instantdex_txids(0,coin->smartaddr)); + } msg = jprint(reqjson,1); - msg2 = clonestr(msg); - // LP_addsig printf("QUERY.(%s)\n",msg); - memset(&zero,0,sizeof(zero)); - portable_mutex_lock(&LP_reservedmutex); - if ( num_Reserved_msgs < sizeof(Reserved_msgs)/sizeof(*Reserved_msgs)-2 ) + //if ( bits256_nonz(qp->srchash) == 0 || strcmp(method,"request") != 0 ) { - Reserved_msgs[num_Reserved_msgs++] = msg; - //Reserved_msgs[num_Reserved_msgs++] = msg2; - } - LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,zero,msg2); - portable_mutex_unlock(&LP_reservedmutex); + memset(&zero,0,sizeof(zero)); + LP_reserved_msg(1,qp->srccoin,qp->destcoin,zero,clonestr(msg)); + if ( strcmp(method,"request") == 0 ) + { + sleep(1); + LP_reserved_msg(1,qp->srccoin,qp->destcoin,zero,clonestr(msg)); + sleep(1); + LP_reserved_msg(1,qp->srccoin,qp->destcoin,zero,clonestr(msg)); + } + free(msg); + /*portable_mutex_lock(&LP_reservedmutex); + if ( num_Reserved_msgs[1] < sizeof(Reserved_msgs[1])/sizeof(*Reserved_msgs[1])-2 ) + Reserved_msgs[1][num_Reserved_msgs[1]++] = msg; + if ( num_Reserved_msgs[0] < sizeof(Reserved_msgs[0])/sizeof(*Reserved_msgs[0])-2 ) + Reserved_msgs[0][num_Reserved_msgs[0]++] = msg2; + portable_mutex_unlock(&LP_reservedmutex);*/ + } //else LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,qp->srchash,msg); } diff --git a/iguana/exchanges/LP_socket.c b/iguana/exchanges/LP_socket.c index af5cfb11e..c3fe17a4a 100644 --- a/iguana/exchanges/LP_socket.c +++ b/iguana/exchanges/LP_socket.c @@ -98,7 +98,7 @@ int32_t LP_socket(int32_t bindflag,char *hostname,uint16_t port) #endif expand_ipbits(checkipaddr,saddr.sin_addr.s_addr); if ( strcmp(ipaddr,checkipaddr) != 0 ) - printf("bindflag.%d iguana_socket mismatch (%s) -> (%s)?\n",bindflag,checkipaddr,ipaddr); + printf("bindflag.%d iguana_socket mismatch (%s) -> (%s)\n",bindflag,checkipaddr,ipaddr); //#endif if ( (sock= socket(AF_INET,SOCK_STREAM,0)) < 0 ) { @@ -124,9 +124,9 @@ int32_t LP_socket(int32_t bindflag,char *hostname,uint16_t port) #endif if ( bindflag == 0 ) { - printf("call connect sock.%d\n",sock); + //printf("call connect sock.%d\n",sock); result = connect(sock,(struct sockaddr *)&saddr,addrlen); - printf("called connect result.%d\n",result); + //printf("called connect result.%d\n",result); timeout.tv_sec = 2; timeout.tv_usec = 0; setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(void *)&timeout,sizeof(timeout)); @@ -238,18 +238,7 @@ int32_t LP_socketrecv(int32_t sock,uint8_t *recvbuf,int32_t maxlen) return(recvlen); } -struct electrum_info -{ - queue_t sendQ,pendingQ; - portable_mutex_t mutex,txmutex; - struct electrum_info *prev; - int32_t bufsize,sock,*heightp,numerrors; - struct iguana_info *coin; - uint32_t stratumid,lasttime,pending,*heighttimep; - char ipaddr[64],symbol[16]; - uint16_t port; - uint8_t buf[]; -} *Electrums[8192]; +struct electrum_info *Electrums[8192]; int32_t Num_electrums; struct electrum_info *electrum_server(char *symbol,struct electrum_info *ep) @@ -283,7 +272,7 @@ struct electrum_info *electrum_server(char *symbol,struct electrum_info *ep) ep = recent_ep; if ( n > 0 ) { - i = (rand() % n); + i = (LP_rand() % n); ep = rbuf[i]; } } @@ -294,7 +283,7 @@ struct electrum_info *electrum_server(char *symbol,struct electrum_info *ep) return(ep); } -int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep,char *coinaddr,cJSON *array,int32_t electrumflag) +int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep,char *coinaddr,cJSON *array,int32_t electrumflag,bits256 reftxid,bits256 reftxid2) { int32_t i,v,n,ht,flag = 0; char str[65]; uint64_t value; bits256 txid; cJSON *item,*retjson,*txobj; struct LP_transaction *tx; if ( array != 0 && coin != 0 && (n= cJSON_GetArraySize(array)) > 0 ) @@ -314,7 +303,7 @@ int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep else { //printf("external unspent has no gettxout\n"); - flag += LP_address_utxoadd("electrum process",coin,coinaddr,txid,v,value,0,1); + flag += LP_address_utxoadd((uint32_t)time(NULL),"electrum process",coin,coinaddr,txid,v,value,0,1); } } else @@ -328,17 +317,25 @@ int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep continue; if ( (tx= LP_transactionfind(coin,txid)) == 0 ) { - txobj = LP_transactioninit(coin,txid,0,0); - LP_transactioninit(coin,txid,1,txobj); - free_json(txobj); - tx = LP_transactionfind(coin,txid); + if ( (bits256_nonz(reftxid) == 0 || bits256_cmp(reftxid,txid) == 0) && (bits256_nonz(reftxid2) == 0 || bits256_cmp(reftxid2,txid) == 0) ) + { + txobj = LP_transactioninit(coin,txid,0,0); + LP_transactioninit(coin,txid,1,txobj); + free_json(txobj); + tx = LP_transactionfind(coin,txid); + } } if ( tx != 0 ) { if (tx->height <= 0 ) { tx->height = ht; - //printf("%s %s >>>>>>>>>> set %s <- height %d\n",coin->symbol,coinaddr,bits256_str(str,txid),tx->height); + if ( ep != 0 && coin != 0 && tx->SPV == 0 ) + { + if ( 0 && strcmp(coinaddr,coin->smartaddr) == 0 ) + tx->SPV = LP_merkleproof(coin,coin->smartaddr,ep,txid,tx->height); + //printf("%s %s >>>>>>>>>> set %s <- height %d\n",coin->symbol,coinaddr,bits256_str(str,txid),tx->height); + } } if ( v >= 0 && v < tx->numvouts ) { @@ -351,7 +348,7 @@ int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep if ( tx->height > 0 ) { //printf("from electrum_process_array\n"); - flag += LP_address_utxoadd("electrum process2",coin,coinaddr,txid,v,value,tx->height,-1); + flag += LP_address_utxoadd((uint32_t)time(NULL),"electrum process2",coin,coinaddr,txid,v,value,tx->height,-1); } //printf("v.%d numvouts.%d %.8f (%s)\n",v,tx->numvouts,dstr(tx->outpoints[jint(item,"tx_pos")].value),jprint(item,0)); } //else printf("cant find tx\n"); @@ -360,6 +357,55 @@ int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep return(flag); } +cJSON *electrum_version(char *symbol,struct electrum_info *ep,cJSON **retjsonp); +cJSON *electrum_headers_subscribe(char *symbol,struct electrum_info *ep,cJSON **retjsonp); + +struct stritem *electrum_sitem(struct electrum_info *ep,char *stratumreq,int32_t timeout,cJSON **retjsonp) +{ + struct stritem *sitem = (struct stritem *)queueitem(stratumreq); + sitem->expiration = timeout; + sitem->DL.type = ep->stratumid++; + sitem->retptrp = (void **)retjsonp; + queue_enqueue("sendQ",&ep->sendQ,&sitem->DL); + return(sitem); +} + +void electrum_initial_requests(struct electrum_info *ep) +{ + cJSON *retjson; char stratumreq[1024]; + retjson = 0; + sprintf(stratumreq,"{ \"jsonrpc\":\"2.0\", \"id\": %u, \"method\":\"%s\", \"params\": %s }\n",ep->stratumid,"blockchain.headers.subscribe","[]"); + electrum_sitem(ep,stratumreq,3,&retjson); + + retjson = 0; + sprintf(stratumreq,"{ \"jsonrpc\":\"2.0\", \"id\": %u, \"method\":\"%s\", \"params\": %s }\n",ep->stratumid,"server.version","[\"barterDEX\", [\"1.1\", \"1.1\"]]"); + electrum_sitem(ep,stratumreq,3,&retjson); + + retjson = 0; + sprintf(stratumreq,"{ \"jsonrpc\":\"2.0\", \"id\": %u, \"method\":\"%s\", \"params\": %s }\n",ep->stratumid,"blockchain.estimatefee","[2]"); + electrum_sitem(ep,stratumreq,3,&retjson); +} + +int32_t electrum_kickstart(struct electrum_info *ep) +{ + closesocket(ep->sock);//, ep->sock = -1; + if ( (ep->sock= LP_socket(0,ep->ipaddr,ep->port)) < 0 ) + { + printf("error RE-connecting to %s:%u\n",ep->ipaddr,ep->port); + return(-1); + } + else + { + ep->stratumid = 0; + electrum_initial_requests(ep); + printf("RECONNECT ep.%p %s numerrors.%d too big -> new %s:%u sock.%d\n",ep,ep->symbol,ep->numerrors,ep->ipaddr,ep->port,ep->sock); + ep->numerrors = 0; + } + return(0); +} + +int32_t zeroval(); + cJSON *electrum_submit(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *method,char *params,int32_t timeout) { // queue id and string and callback @@ -368,37 +414,28 @@ cJSON *electrum_submit(char *symbol,struct electrum_info *ep,cJSON **retjsonp,ch ep = electrum_server(symbol,0); while ( ep != 0 ) { + if ( strcmp(ep->symbol,symbol) != 0 ) + { + printf("electrum_submit ep.%p %s %s:%u called for [%s]???\n",ep,ep->symbol,ep->ipaddr,ep->port,symbol); + } if ( ep != 0 && ep->sock >= 0 && retjsonp != 0 ) { *retjsonp = 0; sprintf(stratumreq,"{ \"jsonrpc\":\"2.0\", \"id\": %u, \"method\":\"%s\", \"params\": %s }\n",ep->stratumid,method,params); //printf("%s %s",symbol,stratumreq); memset(ep->buf,0,ep->bufsize); - sitem = (struct stritem *)queueitem(stratumreq); - sitem->expiration = timeout; - sitem->DL.type = ep->stratumid++; - sitem->retptrp = (void **)retjsonp; - portable_mutex_lock(&ep->mutex); - queue_enqueue("sendQ",&ep->sendQ,&sitem->DL); + sitem = electrum_sitem(ep,stratumreq,timeout,retjsonp); + portable_mutex_lock(&ep->mutex); // this helps performance! expiration = (uint32_t)time(NULL) + timeout + 1; while ( *retjsonp == 0 && time(NULL) <= expiration ) - usleep(5000); + usleep(15000); portable_mutex_unlock(&ep->mutex); if ( *retjsonp == 0 || jobj(*retjsonp,"error") != 0 ) { if ( ++ep->numerrors >= LP_ELECTRUM_MAXERRORS ) - { - closesocket(ep->sock), ep->sock = -1; - if ( (ep->sock= LP_socket(0,ep->ipaddr,ep->port)) < 0 ) - printf("error RE-connecting to %s:%u\n",ep->ipaddr,ep->port); - else - { - printf("ep.%p %s numerrors.%d too big -> new %s:%u sock.%d\n",ep,ep->symbol,ep->numerrors,ep->ipaddr,ep->port,ep->sock); - ep->numerrors = 0; - } - } + electrum_kickstart(ep); } else if ( ep->numerrors > 0 ) - ep->numerrors++; + ep->numerrors--; if ( ep->prev == 0 ) { if ( *retjsonp == 0 ) @@ -408,10 +445,10 @@ cJSON *electrum_submit(char *symbol,struct electrum_info *ep,cJSON **retjsonp,ch } return(*retjsonp); } - } else printf("couldnt find electrum server for (%s %s) or no retjsonp.%p\n",method,params,retjsonp); + } //else printf("couldnt find electrum server for (%s %s) or no retjsonp.%p\n",method,params,retjsonp); ep = ep->prev; - if ( ep != 0 ) - printf("using prev ep.%s\n",ep->symbol); + //if ( ep != 0 ) + // printf("using prev ep.%s\n",ep->symbol); } return(0); } @@ -454,7 +491,16 @@ cJSON *electrum_hasharg(char *symbol,struct electrum_info *ep,cJSON **retjsonp,c return(electrum_submit(symbol,ep,retjsonp,method,params,timeout)); } -cJSON *electrum_version(char *symbol,struct electrum_info *ep,cJSON **retjsonp) { return(electrum_noargs(symbol,ep,retjsonp,"server.version",ELECTRUM_TIMEOUT)); } +cJSON *electrum_version(char *symbol,struct electrum_info *ep,cJSON **retjsonp) +{ + char params[128]; cJSON *retjson; + if ( retjsonp == 0 ) + retjsonp = &retjson; + sprintf(params,"[\"barterDEX\", [\"1.1\", \"1.1\"]]"); + return(electrum_submit(symbol,ep,retjsonp,"server.version",params,ELECTRUM_TIMEOUT)); +} + + cJSON *electrum_banner(char *symbol,struct electrum_info *ep,cJSON **retjsonp) { return(electrum_noargs(symbol,ep,retjsonp,"server.banner",ELECTRUM_TIMEOUT)); } cJSON *electrum_donation(char *symbol,struct electrum_info *ep,cJSON **retjsonp) { return(electrum_noargs(symbol,ep,retjsonp,"server.donation_address",ELECTRUM_TIMEOUT)); } cJSON *electrum_peers(char *symbol,struct electrum_info *ep,cJSON **retjsonp) { return(electrum_noargs(symbol,ep,retjsonp,"server.peers.subscribe",ELECTRUM_TIMEOUT)); } @@ -472,12 +518,12 @@ cJSON *electrum_address_subscribe(char *symbol,struct electrum_info *ep,cJSON ** cJSON *retjson; if ( (retjson= electrum_strarg(symbol,ep,retjsonp,"blockchain.address.subscribe",addr,ELECTRUM_TIMEOUT)) != 0 ) { - printf("subscribe.(%s)\n",jprint(retjson,0)); + //printf("subscribe.(%s)\n",jprint(retjson,0)); } return(retjson); } -cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr) +cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr,bits256 reftxid) { char str[65]; struct LP_transaction *tx; cJSON *retjson,*txobj,*item; int32_t i,n,height; bits256 txid; struct iguana_info *coin = LP_coinfind(symbol); retjson = electrum_strarg(symbol,ep,retjsonp,"blockchain.address.get_history",addr,ELECTRUM_TIMEOUT); @@ -489,7 +535,7 @@ cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON * item = jitem(retjson,i); txid = jbits256(item,"tx_hash"); height = jint(item,"height"); - if ( (tx= LP_transactionfind(coin,txid)) == 0 ) + if ( (tx= LP_transactionfind(coin,txid)) == 0 && (bits256_nonz(reftxid) == 0 || bits256_cmp(txid,reftxid) == 0) ) { //char str[65]; printf("history txinit %s ht.%d\n",bits256_str(str,txid),height); txobj = LP_transactioninit(coin,txid,0,0); @@ -503,7 +549,7 @@ cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON * if ( tx->height > 0 && tx->height != height ) printf("update %s height.%d <- %d\n",bits256_str(str,txid),tx->height,height); tx->height = height; - LP_address_utxoadd("electrum history",coin,addr,txid,0,0,height,-1); + LP_address_utxoadd((uint32_t)time(NULL),"electrum history",coin,addr,txid,0,0,height,-1); } } } @@ -512,31 +558,33 @@ cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON * return(retjson); } -int32_t LP_txheight_check(struct iguana_info *coin,char *coinaddr,struct LP_address_utxo *up) +int32_t LP_txheight_check(struct iguana_info *coin,char *coinaddr,bits256 txid) { cJSON *retjson; if ( coin->electrum != 0 ) { - if ( (retjson= electrum_address_gethistory(coin->symbol,coin->electrum,&retjson,coinaddr)) != 0 ) + if ( (retjson= electrum_address_gethistory(coin->symbol,coin->electrum,&retjson,coinaddr,txid)) != 0 ) free_json(retjson); } return(0); } -cJSON *electrum_address_getmempool(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr) +cJSON *electrum_address_getmempool(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr,bits256 reftxid,bits256 reftxid2) { cJSON *retjson; struct iguana_info *coin = LP_coinfind(symbol); retjson = electrum_strarg(symbol,ep,retjsonp,"blockchain.address.get_mempool",addr,ELECTRUM_TIMEOUT); //printf("MEMPOOL.(%s)\n",jprint(retjson,0)); - electrum_process_array(coin,ep,addr,retjson,1); + electrum_process_array(coin,ep,addr,retjson,1,reftxid,reftxid2); return(retjson); } -cJSON *electrum_address_listunspent(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr,int32_t electrumflag) +cJSON *electrum_address_listunspent(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr,int32_t electrumflag,bits256 txid,bits256 txid2) { - cJSON *retjson=0; struct LP_address *ap; struct iguana_info *coin; int32_t height,usecache=1; + cJSON *retjson=0; char *retstr; struct LP_address *ap; struct iguana_info *coin; int32_t updatedflag,height,usecache=1; if ( (coin= LP_coinfind(symbol)) == 0 ) return(0); + if ( strcmp(addr,INSTANTDEX_KMD) == 0 ) + return(cJSON_Parse("[]")); if ( ep == 0 || ep->heightp == 0 ) height = coin->longestchain; else height = *(ep->heightp); @@ -546,24 +594,47 @@ cJSON *electrum_address_listunspent(char *symbol,struct electrum_info *ep,cJSON usecache = 0; else if ( ap->unspentheight < height ) usecache = 0; - else if ( G.LP_pendingswaps != 0 && time(NULL) > ap->unspenttime+20 ) + else if ( G.LP_pendingswaps != 0 && time(NULL) > ap->unspenttime+13 ) usecache = 0; } - //printf("electrum.%s/%s listunspent last.(%s lag %d)\n",ep->symbol,coin->symbol,coin->lastunspent,(int32_t)(time(NULL) - coin->unspenttime)); - if ( usecache == 0 ) + if ( usecache == 0 || electrumflag > 1 ) { if ( (retjson= electrum_strarg(symbol,ep,retjsonp,"blockchain.address.listunspent",addr,ELECTRUM_TIMEOUT)) != 0 ) { - printf("%s.%d u.%u/%d t.%ld %s LISTUNSPENT.(%d)\n",coin->symbol,height,ap->unspenttime,ap->unspentheight,time(NULL),addr,(int32_t)strlen(jprint(retjson,0))); - if ( electrum_process_array(coin,ep,addr,retjson,electrumflag) != 0 ) - LP_postutxos(coin->symbol,addr); - if ( ap != 0 ) + if ( jobj(retjson,"error") == 0 && is_cJSON_Array(retjson) != 0 ) + { + if ( 0 && electrumflag > 1 ) + printf("%s.%d u.%u/%d t.%ld %s LISTUNSPENT.(%d)\n",coin->symbol,height,ap->unspenttime,ap->unspentheight,time(NULL),addr,(int32_t)strlen(jprint(retjson,0))); + updatedflag = 0; + if ( electrum_process_array(coin,ep,addr,retjson,electrumflag,txid,txid2) != 0 ) + { + //LP_postutxos(coin->symbol,addr); + updatedflag = 1; + } + retstr = jprint(retjson,0); + LP_unspents_cache(coin->symbol,addr,retstr,1); + free(retstr); + if ( ap != 0 ) + { + ap->unspenttime = (uint32_t)time(NULL); + ap->unspentheight = height; + } + } + else { - ap->unspenttime = (uint32_t)time(NULL); - ap->unspentheight = height; + free_json(retjson); + retjson = 0; } } - } else retjson = LP_address_utxos(coin,addr,1); + } + if ( retjson == 0 ) + { + if ( (retstr= LP_unspents_filestr(symbol,addr)) != 0 ) + { + retjson = cJSON_Parse(retstr); + free(retstr); + } else retjson = LP_address_utxos(coin,addr,1); + } return(retjson); } @@ -575,7 +646,11 @@ cJSON *electrum_address_getbalance(char *symbol,struct electrum_info *ep,cJSON * cJSON *electrum_addpeer(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *endpoint) { return(electrum_strarg(symbol,ep,retjsonp,"server.add_peer",endpoint,ELECTRUM_TIMEOUT)); } cJSON *electrum_sendrawtransaction(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *rawtx) { return(electrum_strarg(symbol,ep,retjsonp,"blockchain.transaction.broadcast",rawtx,ELECTRUM_TIMEOUT)); } -cJSON *electrum_estimatefee(char *symbol,struct electrum_info *ep,cJSON **retjsonp,int32_t numblocks) { return(electrum_intarg(symbol,ep,retjsonp,"blockchain.estimatefee",numblocks,ELECTRUM_TIMEOUT)); } +cJSON *electrum_estimatefee(char *symbol,struct electrum_info *ep,cJSON **retjsonp,int32_t numblocks) +{ + return(electrum_intarg(symbol,ep,retjsonp,"blockchain.estimatefee",numblocks,ELECTRUM_TIMEOUT)); +} + cJSON *electrum_getchunk(char *symbol,struct electrum_info *ep,cJSON **retjsonp,int32_t n) { return(electrum_intarg(symbol,ep,retjsonp,"blockchain.block.get_chunk",n,ELECTRUM_TIMEOUT)); } cJSON *electrum_getheader(char *symbol,struct electrum_info *ep,cJSON **retjsonp,int32_t n) @@ -583,19 +658,27 @@ cJSON *electrum_getheader(char *symbol,struct electrum_info *ep,cJSON **retjsonp return(electrum_intarg(symbol,ep,retjsonp,"blockchain.block.get_header",n,ELECTRUM_TIMEOUT)); } -cJSON *LP_transaction_fromdata(struct iguana_info *coin,bits256 txid,uint8_t *serialized,int32_t len) +cJSON *LP_cache_transaction(struct iguana_info *coin,bits256 txid,uint8_t *serialized,int32_t len) { - uint8_t *extraspace; cJSON *txobj; char str[65],str2[65]; struct iguana_msgtx msgtx; bits256 checktxid; - extraspace = calloc(1,4000000); - memset(&msgtx,0,sizeof(msgtx)); - txobj = bitcoin_data2json(coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->height,&checktxid,&msgtx,extraspace,4000000,serialized,len,0,0,coin->zcash); - //printf("TX.(%s) match.%d\n",jprint(txobj,0),bits256_cmp(txid,checktxid)); - free(extraspace); - if ( bits256_cmp(txid,checktxid) != 0 ) - { - printf("%s LP_transaction_fromdata mismatched txid %s vs %s\n",coin->symbol,bits256_str(str,txid),bits256_str(str2,checktxid)); - free_json(txobj); - txobj = 0; + cJSON *txobj; struct LP_transaction *tx; + if ( (txobj= LP_transaction_fromdata(coin,txid,serialized,len)) != 0 ) + { + if ( (tx= LP_transactionfind(coin,txid)) == 0 || tx->serialized == 0 ) + { + txobj = LP_transactioninit(coin,txid,0,txobj); + LP_transactioninit(coin,txid,1,txobj); + tx = LP_transactionfind(coin,txid); + } + if ( tx != 0 ) + { + tx->serialized = serialized; + tx->len = len; + } + else + { + char str[65]; printf("unexpected couldnt find tx %s %s\n",coin->symbol,bits256_str(str,txid)); + free(serialized); + } } return(txobj); } @@ -625,11 +708,11 @@ cJSON *_electrum_transaction(char *symbol,struct electrum_info *ep,cJSON **retjs } hexjson = electrum_hasharg(symbol,ep,&hexjson,"blockchain.transaction.get",txid,ELECTRUM_TIMEOUT); hexstr = jprint(hexjson,0); - if ( strlen(hexstr) > 60000 ) + if ( strlen(hexstr) > 100000 ) { static uint32_t counter; if ( counter++ < 3 ) - printf("rawtransaction too big %d\n",(int32_t)strlen(hexstr)); + printf("rawtransaction %s %s too big %d\n",coin->symbol,bits256_str(str,txid),(int32_t)strlen(hexstr)); free(hexstr); free_json(hexjson); *retjsonp = cJSON_Parse("{\"error\":\"transaction too big\"}"); @@ -649,30 +732,11 @@ cJSON *_electrum_transaction(char *symbol,struct electrum_info *ep,cJSON **retjs memcpy(coin->cachedtxiddata,serialized,len); free(hexstr); //printf("DATA.(%s) from (%s)\n",hexstr+1,jprint(hexjson,0)); - if ( (txobj= LP_transaction_fromdata(coin,txid,serialized,len)) != 0 ) - { - if ( (tx= LP_transactionfind(coin,txid)) == 0 || tx->serialized == 0 ) - { - txobj = LP_transactioninit(coin,txid,0,txobj); - LP_transactioninit(coin,txid,1,txobj); - tx = LP_transactionfind(coin,txid); - } - if ( tx != 0 ) - { - tx->serialized = serialized; - tx->len = len; - } - else - { - printf("unexpected couldnt find tx %s %s\n",coin->symbol,bits256_str(str,txid)); - free(serialized); - } - } - *retjsonp = txobj; + *retjsonp = LP_cache_transaction(coin,txid,serialized,len); // eats serialized free_json(hexjson); //printf("return from electrum_transaction\n"); return(*retjsonp); - } else printf("%s %s non-hex tx.(%s)\n",coin->symbol,bits256_str(str,txid),jprint(hexjson,0)); + } //else printf("%s %s non-hex tx.(%s)\n",coin->symbol,bits256_str(str,txid),jprint(hexjson,0)); free(hexstr); free_json(hexjson); } @@ -680,12 +744,34 @@ cJSON *_electrum_transaction(char *symbol,struct electrum_info *ep,cJSON **retjs return(*retjsonp); } -cJSON *electrum_transaction(char *symbol,struct electrum_info *ep,cJSON **retjsonp,bits256 txid) +cJSON *electrum_transaction(int32_t *heightp,char *symbol,struct electrum_info *ep,cJSON **retjsonp,bits256 txid,char *SPVcheck) { - cJSON *retjson; + cJSON *retjson,*array; bits256 zero; struct LP_transaction *tx=0; struct iguana_info *coin; + coin = LP_coinfind(symbol); + *heightp = 0; if ( ep != 0 ) portable_mutex_lock(&ep->txmutex); retjson = _electrum_transaction(symbol,ep,retjsonp,txid); + if ( (tx= LP_transactionfind(coin,txid)) != 0 && ep != 0 && coin != 0 && SPVcheck != 0 && SPVcheck[0] != 0 ) + { + if ( tx->height <= 0 ) + { + memset(zero.bytes,0,sizeof(zero)); + if ( (array= electrum_address_listunspent(symbol,ep,&array,SPVcheck,2,txid,zero)) != 0 ) + { + printf("SPVcheck.%s got %d unspents\n",SPVcheck,cJSON_GetArraySize(array)); + free_json(array); + } + } + if ( tx->height > 0 ) + { + if ( tx->SPV == 0 ) + tx->SPV = LP_merkleproof(coin,SPVcheck,ep,txid,tx->height); + *heightp = tx->height; + } + char str[65]; printf("%s %s %s SPV height %d SPV %d\n",coin->symbol,SPVcheck,bits256_str(str,txid),tx->height,tx->SPV); + } else if ( tx != 0 ) + *heightp = tx->height; if ( ep != 0 ) portable_mutex_unlock(&ep->txmutex); return(retjson); @@ -702,12 +788,13 @@ cJSON *electrum_getmerkle(char *symbol,struct electrum_info *ep,cJSON **retjsonp void electrum_test() { - cJSON *retjson; bits256 hash; struct electrum_info *ep = 0; char *addr,*script,*symbol = "BTC"; + cJSON *retjson; int32_t height; bits256 hash,zero; struct electrum_info *ep = 0; char *addr,*script,*symbol = "BTC"; while ( Num_electrums == 0 ) { sleep(1); printf("Num_electrums %p -> %d\n",&Num_electrums,Num_electrums); } + memset(zero.bytes,0,sizeof(zero)); printf("found electrum server\n"); if ( (retjson= electrum_version(symbol,ep,0)) != 0 ) printf("electrum_version %s\n",jprint(retjson,1)); @@ -727,16 +814,16 @@ void electrum_test() decode_hex(hash.bytes,sizeof(hash),"b967a7d55889fe11e993430921574ec6379bc8ce712a652c3fcb66c6be6e925c"); if ( (retjson= electrum_getmerkle(symbol,ep,0,hash,403000)) != 0 ) printf("electrum_getmerkle %s\n",jprint(retjson,1)); - if ( (retjson= electrum_transaction(symbol,ep,0,hash)) != 0 ) + if ( (retjson= electrum_transaction(&height,symbol,ep,0,hash,0)) != 0 ) printf("electrum_transaction %s\n",jprint(retjson,1)); addr = "14NeevLME8UAANiTCVNgvDrynUPk1VcQKb"; - if ( (retjson= electrum_address_gethistory(symbol,ep,0,addr)) != 0 ) + if ( (retjson= electrum_address_gethistory(symbol,ep,0,addr,zero)) != 0 ) printf("electrum_address_gethistory %s\n",jprint(retjson,1)); - if ( (retjson= electrum_address_getmempool(symbol,ep,0,addr)) != 0 ) + if ( (retjson= electrum_address_getmempool(symbol,ep,0,addr,zero,zero)) != 0 ) printf("electrum_address_getmempool %s\n",jprint(retjson,1)); if ( (retjson= electrum_address_getbalance(symbol,ep,0,addr)) != 0 ) printf("electrum_address_getbalance %s\n",jprint(retjson,1)); - if ( (retjson= electrum_address_listunspent(symbol,ep,0,addr,1)) != 0 ) + if ( (retjson= electrum_address_listunspent(symbol,ep,0,addr,1,zero,zero)) != 0 ) printf("electrum_address_listunspent %s\n",jprint(retjson,1)); if ( (retjson= electrum_addpeer(symbol,ep,0,"electrum.be:50001")) != 0 ) printf("electrum_addpeer %s\n",jprint(retjson,1)); @@ -816,9 +903,12 @@ struct electrum_info *LP_electrum_info(int32_t *alreadyp,char *symbol,char *ipad int32_t LP_recvfunc(struct electrum_info *ep,char *str,int32_t len) { cJSON *strjson,*errjson,*resultjson,*paramsjson; char *method; int32_t i,n,height; uint32_t idnum=0; struct stritem *stritem; struct iguana_info *coin; struct queueitem *tmp,*item = 0; + if ( str == 0 || len == 0 ) + return(-1); ep->lasttime = (uint32_t)time(NULL); if ( (strjson= cJSON_Parse(str)) != 0 ) { + //printf("%s RECV.(%ld) id.%d (%s)\n",ep->symbol,strlen(str),jint(strjson,"id"),jint(strjson,"id")==0?str:""); resultjson = jobj(strjson,"result"); //printf("strjson.(%s)\n",jprint(strjson,0)); if ( (method= jstr(strjson,"method")) != 0 ) @@ -859,10 +949,12 @@ int32_t LP_recvfunc(struct electrum_info *ep,char *str,int32_t len) stritem = (struct stritem *)item; if ( item->type == idnum ) { - //printf("matched idnum.%d result.%p\n",idnum,resultjson); DL_DELETE(ep->pendingQ.list,item); - *((cJSON **)stritem->retptrp) = (resultjson != 0 ? jduplicate(resultjson) : strjson); - resultjson = strjson = 0; + if ( resultjson != 0 ) + *((cJSON **)stritem->retptrp) = jduplicate(resultjson); + else *((cJSON **)stritem->retptrp) = strjson, strjson = 0; + //printf("matched idnum.%d result.(%s)\n",idnum,jprint(*((cJSON **)stritem->retptrp),0)); + //resultjson = strjson = 0; free(item); break; } @@ -890,11 +982,10 @@ int32_t LP_recvfunc(struct electrum_info *ep,char *str,int32_t len) void LP_dedicatedloop(void *arg) { - struct pollfd fds; int32_t i,len,flag,timeout = 10; struct iguana_info *coin; cJSON *retjson; struct stritem *sitem; struct electrum_info *ep = arg; + struct pollfd fds; int32_t i,len,n,flag,timeout = 10; struct iguana_info *coin; struct stritem *sitem; struct electrum_info *ep = arg; if ( (coin= LP_coinfind(ep->symbol)) != 0 ) ep->heightp = &coin->height, ep->heighttimep = &coin->heighttime; - if ( (retjson= electrum_headers_subscribe(ep->symbol,ep,0)) != 0 ) - free_json(retjson); + electrum_initial_requests(ep); printf("LP_dedicatedloop ep.%p sock.%d for %s:%u num.%d %p %s ht.%d\n",ep,ep->sock,ep->ipaddr,ep->port,Num_electrums,&Num_electrums,ep->symbol,*ep->heightp); while ( ep->sock >= 0 ) { @@ -912,6 +1003,7 @@ void LP_dedicatedloop(void *arg) ep->sock = -1; break; } + ep->keepalive = (uint32_t)time(NULL); if ( sitem->expiration != 0 ) sitem->expiration += (uint32_t)time(NULL); else sitem->expiration = (uint32_t)time(NULL) + ELECTRUM_TIMEOUT; @@ -922,7 +1014,34 @@ void LP_dedicatedloop(void *arg) { if ( (fds.revents & POLLIN) != 0 ) { - if ( (len= LP_socketrecv(ep->sock,ep->buf,ep->bufsize)) > 0 ) + len = 0; + while ( len+65536 < ep->bufsize ) + { + if ( (n= LP_socketrecv(ep->sock,&ep->buf[len],ep->bufsize-len)) > 0 ) + { + len += n; + if ( ep->buf[len - 1] == '\n' ) + break; + memset(&fds,0,sizeof(fds)); + fds.fd = ep->sock; + fds.events = POLLIN; + if ( poll(&fds,1,1000) <= 0 ) + { + printf("no more electrum data after a second\n"); + electrum_kickstart(ep); + break; + } + } + else + { +#ifndef _WIN32 + printf("no more electrum data when expected2\n"); + electrum_kickstart(ep); +#endif + break; + } + } + if ( len > 0 ) { ep->pending = 0; LP_recvfunc(ep,(char *)ep->buf,len); @@ -959,10 +1078,38 @@ void LP_dedicatedloop(void *arg) cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port) { - struct electrum_info *ep; int32_t already; cJSON *retjson = cJSON_CreateObject(); + struct electrum_info *ep,*prev; int32_t kickval,already; cJSON *retjson,*array,*item; + if ( ipaddr == 0 || ipaddr[0] == 0 || port == 0 ) + { + ep = coin->electrum; + coin->electrum = 0; + coin->inactive = (uint32_t)time(NULL); + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jaddstr(retjson,"status","electrum mode disabled, now in disabled native coin mode"); + if ( ep != 0 ) + { + array = cJSON_CreateArray(); + while ( ep != 0 ) + { + item = cJSON_CreateObject(); + jaddstr(item,"ipaddr",ep->ipaddr); + jaddnum(item,"port",ep->port); + jaddnum(item,"kickstart",electrum_kickstart(ep)); + jaddi(array,item); + prev = ep->prev; + ep->prev = 0; + ep = prev; + } + jadd(retjson,"electrums",array); + } + //printf("would have disabled %s electrum here\n",coin->symbol); + return(retjson); + } + retjson = cJSON_CreateObject(); jaddstr(retjson,"ipaddr",ipaddr); jaddnum(retjson,"port",port); - if ( (ep= LP_electrum_info(&already,coin->symbol,ipaddr,port,IGUANA_MAXPACKETSIZE * 10)) == 0 ) + if ( (ep= LP_electrum_info(&already,coin->symbol,ipaddr,port,IGUANA_MAXPACKETSIZE)) == 0 ) { jaddstr(retjson,"error","couldnt connect to electrum server"); return(retjson); @@ -976,16 +1123,31 @@ cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port) } else { - printf("launched electrum.(%s:%u)\n",ep->ipaddr,ep->port); + //printf("launched %s electrum.(%s:%u)\n",coin->symbol,ep->ipaddr,ep->port); jaddstr(retjson,"result","success"); ep->prev = coin->electrum; coin->electrum = ep; + if ( coin->loadedcache == 0 ) + { + LP_cacheptrs_init(coin); + coin->loadedcache = (uint32_t)time(NULL); + } } } else { + if ( coin->electrum == 0 ) + { + coin->electrum = ep; + ep->prev = 0; + } jaddstr(retjson,"result","success"); jaddstr(retjson,"status","already there"); + if ( ep->numerrors > 0 ) + { + kickval = electrum_kickstart(ep); + jaddnum(retjson,"restart",kickval); + } } //printf("(%s)\n",jprint(retjson,0)); return(retjson); diff --git a/iguana/exchanges/LP_statemachine.c b/iguana/exchanges/LP_statemachine.c index c14c557ee..be1d7701d 100644 --- a/iguana/exchanges/LP_statemachine.c +++ b/iguana/exchanges/LP_statemachine.c @@ -132,6 +132,548 @@ 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); + }*/ + +void LP_instantdex_txidadd(bits256 txid) +{ + cJSON *array; int32_t i,n; + if ( (array= LP_instantdex_txids()) == 0 ) + array = cJSON_CreateArray(); + if ( (n= cJSON_GetArraySize(array)) >= 0 ) + { + for (i=0; i a_value ) + destsatoshis = a_value; + if ( maxdestsatoshis != 0 && destsatoshis > maxdestsatoshis-desttxfee-1 ) + destsatoshis = maxdestsatoshis-desttxfee-1; + satoshis = (destsatoshis / price + 0.49) - txfee; + *destsatoshisp = destsatoshis; + *satoshisp = satoshis; + if ( satoshis > 0 ) + return((double)destsatoshis / satoshis); + else return(0.); + }*/ + +/*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); + //} + } + }*/ + +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_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 close enough in size\"}")); + return(jprint(LP_utxojson(autxo),1)); +} +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; @@ -277,24 +819,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; @@ -545,7 +1069,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); @@ -785,7 +1309,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 ) { @@ -959,7 +1483,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); @@ -1355,7 +1879,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 @@ -1387,37 +1911,165 @@ int32_t bitcoin_coinptrs(bits256 pubkey,struct iguana_info **bobcoinp,struct igu return(0); } -/*void basilisk_swap_purge(struct basilisk_swap *swap) - { - int32_t i,n; - // while still in orderbook, wait - //return; - portable_mutex_lock(&myinfo->DEX_swapmutex); - n = myinfo->numswaps; - for (i=0; iswaps[i] == swap ) - { - myinfo->swaps[i] = myinfo->swaps[--myinfo->numswaps]; - myinfo->swaps[myinfo->numswaps] = 0; - basilisk_swap_finished(swap); - break; - } - portable_mutex_unlock(&myinfo->DEX_swapmutex); - }*/ +struct LP_utxoinfo *LP_utxopairfind(int32_t iambob,bits256 txid,int32_t vout,bits256 txid2,int32_t vout2) +{ + struct LP_utxoinfo *utxo=0; struct _LP_utxoinfo u; + if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 ) + { + u = (iambob != 0) ? utxo->deposit : utxo->fee; + if (vout2 == u.vout && bits256_cmp(u.txid,txid2) == 0 ) + return(utxo); + } + return(0); +} -/*int32_t LP_priceping(int32_t pubsock,struct LP_utxoinfo *utxo,char *rel,double origprice) - { - double price,bid,ask; uint32_t now; cJSON *retjson; struct LP_quoteinfo Q; char *retstr; - if ( (now= (uint32_t)time(NULL)) > utxo->T.swappending && utxo->S.swap == 0 ) - utxo->T.swappending = 0; - if ( now > utxo->T.published+60 && LP_isavailable(utxo) && (price= LP_myprice(&bid,&ask,utxo->coin,rel)) != 0. ) - { - if ( origprice < price ) - price = origprice; - if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 ) - return(-1); - Q.timestamp = (uint32_t)time(NULL); - retjson = LP_quotejson(&Q); +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); +} + +/*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); + //printf("LP_privkeysloop %u\n",LP_counter); + LP_privkey_updates(ctx,LP_mypubsock,0); + sleep(LP_ORDERBOOK_DURATION * .777); + } + }*/ +/*void basilisk_swap_purge(struct basilisk_swap *swap) + { + int32_t i,n; + // while still in orderbook, wait + //return; + portable_mutex_lock(&myinfo->DEX_swapmutex); + n = myinfo->numswaps; + for (i=0; iswaps[i] == swap ) + { + myinfo->swaps[i] = myinfo->swaps[--myinfo->numswaps]; + myinfo->swaps[myinfo->numswaps] = 0; + basilisk_swap_finished(swap); + break; + } + 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_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); +} +/*int32_t LP_priceping(int32_t pubsock,struct LP_utxoinfo *utxo,char *rel,double origprice) + { + double price,bid,ask; uint32_t now; cJSON *retjson; struct LP_quoteinfo Q; char *retstr; + if ( (now= (uint32_t)time(NULL)) > utxo->T.swappending && utxo->S.swap == 0 ) + utxo->T.swappending = 0; + if ( now > utxo->T.published+60 && LP_isavailable(utxo) && (price= LP_myprice(&bid,&ask,utxo->coin,rel)) != 0. ) + { + if ( origprice < price ) + price = origprice; + if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 ) + return(-1); + Q.timestamp = (uint32_t)time(NULL); + retjson = LP_quotejson(&Q); jaddstr(retjson,"method","quote"); retstr = jprint(retjson,1); //printf("PING.(%s)\n",retstr); @@ -1466,6 +2118,171 @@ int32_t bitcoin_coinptrs(bits256 pubkey,struct iguana_info **bobcoinp,struct igu if ( LP_ismine(utxo) > 0 && strcmp(utxo->coin,base) == 0 ) LP_priceping(LP_mypubsock,utxo,rel,price * LP_profitratio); }*/ + +int32_t LP_ismine(struct LP_utxoinfo *utxo) +{ + if ( utxo != 0 && bits256_cmp(utxo->pubkey,G.LP_mypub25519) == 0 ) + return(1); + else return(0); +} + +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_pubkey_info *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\"}")); +} + +/*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)); + }*/ + +/*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); + }*/ + +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); +} +else if ( strcmp(method,"postutxos") == 0 ) +return(LP_postutxos_recv(argjson)); + +void utxosQ_loop(void *myipaddr) +{ + strcpy(utxosQ_loop_stats.name,"utxosQ_loop"); + utxosQ_loop_stats.threshold = 5000.; + while ( 1 ) + { + LP_millistats_update(&utxosQ_loop_stats); + if ( LP_utxosQ_process() == 0 ) + usleep(50000); + } +} +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); +} + /* bestprice = 0.; if ( (array= LP_tradecandidates(base)) != 0 ) @@ -1613,6 +2430,65 @@ void LP_address_monitor(struct LP_pubkeyinfo *pubp) 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; @@ -1841,6 +2717,27 @@ char *LP_utxos(int32_t iambob,struct LP_peerinfo *mypeer,char *symbol,int32_t la } return(jprint(utxosjson,1)); } +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_utxo_clientpublish(struct LP_utxoinfo *utxo) { bits256 zero; char *msg; @@ -1990,70 +2887,614 @@ else 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); - }*/ +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); +} -if ( aliceutxo->S.swap == 0 ) -LP_availableset(aliceutxo); -return(jprint(bestitem,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); } -if ( 0 && (retstr= issue_LP_listunspent(peer->ipaddr,peer->port,coin->symbol,"")) != 0 ) + +int32_t LP_utxoaddptrs(struct LP_utxoinfo *ptrs[],int32_t n,struct LP_utxoinfo *utxo) { - if ( (array2= cJSON_Parse(retstr)) != 0 ) + int32_t i; + for (i=0; i 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); + if ( (utxo= _LP_utxofind(iambob,refutxo->payment.txid,refutxo->payment.vout)) != 0 && utxo != refutxo ) + n = LP_utxoaddptrs(ptrs,n,utxo); + if ( (utxo= _LP_utxo2find(iambob,refutxo->payment.txid,refutxo->payment.vout)) != 0 && utxo != refutxo ) + n = LP_utxoaddptrs(ptrs,n,utxo); + u = (refutxo->iambob != 0) ? refutxo->deposit : refutxo->fee; + if ( (utxo= _LP_utxofind(iambob,u.txid,u.vout)) != 0 && utxo != refutxo ) + n = LP_utxoaddptrs(ptrs,n,utxo); + if ( (utxo= _LP_utxo2find(iambob,u.txid,u.vout)) != 0 && utxo != refutxo ) + n = LP_utxoaddptrs(ptrs,n,utxo); } - //printf("processed.(%s)\n",retstr); - free(retstr); + portable_mutex_unlock(&LP_utxomutex); + if ( 0 && n > 0 ) + printf("LP_utxocollisions n.%d\n",n); + return(n); } -/*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 ) + +int32_t _LP_availableset(struct LP_utxoinfo *utxo) +{ + int32_t flag = 0; + if ( utxo != 0 ) + { + if ( bits256_nonz(utxo->S.otherpubkey) != 0 ) + flag = 1, memset(&utxo->S.otherpubkey,0,sizeof(utxo->S.otherpubkey)); + if ( utxo->S.swap != 0 ) + flag = 1, utxo->S.swap = 0; + if ( utxo->T.swappending != 0 ) + flag = 1, utxo->T.swappending = 0; + return(flag); + } + return(0); +} + +void _LP_unavailableset(struct LP_utxoinfo *utxo,bits256 otherpubkey) +{ + if ( utxo != 0 ) + { + utxo->T.swappending = (uint32_t)(time(NULL) + LP_RESERVETIME); + utxo->S.otherpubkey = otherpubkey; + } +} + +void LP_unavailableset(struct LP_utxoinfo *utxo,bits256 otherpubkey) +{ + struct LP_utxoinfo *ptrs[8]; int32_t i,n; struct _LP_utxoinfo u; + memset(ptrs,0,sizeof(ptrs)); + if ( (n= LP_utxocollisions(ptrs,utxo)) > 0 ) + { + for (i=0; iiambob != 0) ? utxo->deposit : utxo->fee; + char str[65],str2[65]; printf("UTXO.[%d] RESERVED %s/v%d %s/v%d collisions.%d\n",utxo->iambob,bits256_str(str,utxo->payment.txid),utxo->payment.vout,bits256_str(str2,u.txid),u.vout,n); + _LP_unavailableset(utxo,otherpubkey); +} + +void LP_availableset(struct LP_utxoinfo *utxo) +{ + struct LP_utxoinfo *ptrs[8]; int32_t i,n,count = 0; struct _LP_utxoinfo u; + if ( utxo != 0 ) + { + memset(ptrs,0,sizeof(ptrs)); + if ( (n= LP_utxocollisions(ptrs,utxo)) > 0 ) + { + for (i=0; i 0 ) + { + u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; + char str[65],str2[65]; printf("UTXO.[%d] AVAIL %s/v%d %s/v%d collisions.%d\n",utxo->iambob,bits256_str(str,utxo->payment.txid),utxo->payment.vout,bits256_str(str2,u.txid),u.vout,n); + } + } +} + + +cJSON *LP_inventoryjson(cJSON *item,struct LP_utxoinfo *utxo) +{ + struct _LP_utxoinfo u; + //jaddstr(item,"method","oldutxo"); + if ( utxo == 0 ) + return(item); + if ( utxo->gui[0] != 0 ) + jaddstr(item,"gui",utxo->gui); + jaddstr(item,"coin",utxo->coin); + //jaddnum(item,"now",time(NULL)); + jaddnum(item,"iambob",utxo->iambob); + jaddstr(item,"address",utxo->coinaddr); + jaddbits256(item,"txid",utxo->payment.txid); + jaddnum(item,"vout",utxo->payment.vout); + jadd64bits(item,"value",utxo->payment.value); + jadd64bits(item,"satoshis",utxo->S.satoshis); + u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; + if ( bits256_nonz(u.txid) != 0 ) + { + jaddbits256(item,"txid2",u.txid); + jaddnum(item,"vout2",u.vout); + jadd64bits(item,"value2",u.value); + } + if ( utxo->T.swappending != 0 ) + jaddnum(item,"pending",utxo->T.swappending); + if ( utxo->iambob != 0 ) + { + jaddbits256(item,"srchash",utxo->pubkey);//LP_mypub25519); + if ( bits256_nonz(utxo->S.otherpubkey) != 0 ) + jaddbits256(item,"desthash",utxo->S.otherpubkey); + } + else + { + jaddbits256(item,"desthash",utxo->pubkey);//LP_mypub25519); + if ( bits256_nonz(utxo->S.otherpubkey) != 0 ) + jaddbits256(item,"srchash",utxo->S.otherpubkey); + } + //if ( utxo->S.swap != 0 ) + // jaddstr(item,"swap","in progress"); + if ( utxo->T.spentflag != 0 ) + jaddnum(item,"spent",utxo->T.spentflag); + jaddnum(item,"session",utxo->T.sessionid); + return(item); +} + +cJSON *LP_utxojson(struct LP_utxoinfo *utxo) +{ + cJSON *item = cJSON_CreateObject(); + item = LP_inventoryjson(item,utxo); + jaddbits256(item,"pubkey",utxo->pubkey); + //jaddnum(item,"profit",utxo->S.profitmargin); + jaddstr(item,"base",utxo->coin); + //jaddstr(item,"script",utxo->spendscript); + return(item); +} + +struct LP_utxoinfo *LP_utxo_bestfit(char *symbol,uint64_t destsatoshis) +{ + uint64_t srcvalue,srcvalue2; struct LP_utxoinfo *utxo,*tmp,*bestutxo = 0; int32_t 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,G.LP_utxoinfos[iambob],utxo,tmp) + { + if ( strcmp(symbol,utxo->coin) != 0 ) + continue; + if ( LP_isavailable(utxo) > 0 && LP_ismine(utxo) > 0 ) + { + //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 ) + // utxo->T.spentflag = (uint32_t)time(NULL); + continue; + } + bestutxo = utxo; + } //else printf("skip alice utxo %.8f vs dest %.8f, bestsize.%d %p\n",dstr(utxo->S.satoshis),dstr(destsatoshis),bestsize,bestutxo); + } + } + return(bestutxo); +} + +void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector) +{ + if ( utxo == 0 ) + return; + utxo->T.spentflag = (uint32_t)time(NULL); +} + +struct LP_utxoinfo *LP_utxofinds(int32_t iambob,bits256 txid,int32_t vout,bits256 txid2,int32_t vout2) +{ + struct LP_utxoinfo *utxo; + if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 || (utxo= LP_utxofind(iambob,txid2,vout2)) != 0 || (utxo= LP_utxo2find(iambob,txid,vout)) != 0 || (utxo= LP_utxo2find(iambob,txid2,vout2)) != 0 ) + return(utxo); + else return(0); +} + +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,txfee; int32_t spendvini,numconfirms,selector; bits256 spendtxid; struct iguana_info *coin; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo = 0; + if ( symbol == 0 || symbol[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 || vout < 0 || vout2 < 0 || value <= 0 || value2 <= 0 )//|| sessionid == 0 ) + { + char str[65],str2[65]; printf("REJECT (%s) iambob.%d %s utxoadd.(%.8f %.8f) %s/v%d %s/v%d\n",coinaddr,iambob,symbol,dstr(value),dstr(value2),bits256_str(str,txid),vout,bits256_str(str2,txid2),vout2); + printf("session.%u addutxo %d %d %d %d %d %d %d %d\n",sessionid,symbol == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(txid2) == 0,vout < 0,vout2 < 0,value <= 0,value2 <= 0); + return(0); + } + if ( (coin= LP_coinfind(symbol)) == 0 || (IAMLP == 0 && coin->inactive != 0) ) + { + //printf("LP_utxoadd reject inactive %s\n",symbol); + return(0); + } + txfee = LP_txfeecalc(coin,0,0); + char str[65],str2[65],dispflag = 0;//(iambob == 0); + if ( iambob == 0 && bits256_cmp(pubkey,G.LP_mypub25519) != 0 ) + { + printf("trying to add Alice utxo when not mine? %s/v%d\n",bits256_str(str,txid),vout); + return(0); + } + if ( coin->inactive == 0 ) + { + if ( LP_iseligible(&val,&val2,iambob,symbol,txid,vout,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); + } + } + else + { + val = value; + val2 = value2; + } + dispflag = 0; + if ( dispflag != 0 ) + printf("%.8f %.8f %s iambob.%d %s utxoadd.(%.8f %.8f) %s %s\n",dstr(val),dstr(val2),coinaddr,iambob,symbol,dstr(value),dstr(value2),bits256_str(str,txid),bits256_str(str2,txid2)); + dispflag = 1; + if ( (utxo= LP_utxofinds(iambob,txid,vout,txid2,vout2)) != 0 ) + { + if ( 0 && LP_ismine(utxo) == 0 ) + { + char str2[65],str3[65]; printf("iambob.%d %s %s utxoadd.(%.8f %.8f) %s %s\n",iambob,bits256_str(str3,pubkey),symbol,dstr(value),dstr(value2),bits256_str(str,txid),bits256_str(str2,txid2)); + printf("duplicate %.8f %.8f %.8f vs utxo.(%.8f %.8f %.8f)\n",dstr(value),dstr(value2),dstr(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 || 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); + printf("original utxo pair not valid\n"); + if ( dispflag != 0 ) + printf("error on subsequent utxo iambob.%d %.8f %.8f add.(%s %s) when.(%s %s) %d %d %d %d %d %d %d %d %d %d pubkeys.(%s vs %s)\n",iambob,dstr(val),dstr(val2),bits256_str(str,txid),bits256_str(str2,txid2),bits256_str(str3,utxo->payment.txid),bits256_str(str4,utxo->deposit.txid),bits256_cmp(txid,utxo->payment.txid) != 0,bits256_cmp(txid2,u.txid) != 0,vout != utxo->payment.vout,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; + } + } + if ( utxo != 0 ) + { + if ( utxo->T.sessionid == 0 ) + utxo->T.sessionid = sessionid; + //else if ( profitmargin > SMALLVAL ) + // utxo->S.profitmargin = profitmargin; + utxo->T.lasttime = (uint32_t)time(NULL); + //printf("return existing utxo[%d] %s %s\n",iambob,bits256_str(str,utxo->payment.txid),bits256_str(str2,iambob != 0 ? utxo->deposit.txid : utxo->fee.txid)); + return(utxo); + } + } + utxo = calloc(1,sizeof(*utxo)); + //utxo->S.profitmargin = profitmargin; + utxo->pubkey = pubkey; + safecopy(utxo->gui,gui,sizeof(utxo->gui)); + safecopy(utxo->coin,symbol,sizeof(utxo->coin)); + safecopy(utxo->coinaddr,coinaddr,sizeof(utxo->coinaddr)); + //safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript)); + utxo->payment.txid = txid; + utxo->payment.vout = vout; + utxo->payment.value = value; + utxo->S.satoshis = satoshis; + if ( (utxo->iambob= iambob) != 0 ) + { + utxo->deposit.txid = txid2; + utxo->deposit.vout = vout2; + utxo->deposit.value = value2; + } + else + { + utxo->fee.txid = txid2; + utxo->fee.vout = vout2; + utxo->fee.value = value2; + } + LP_utxosetkey(utxo->key,txid,vout); + LP_utxosetkey(utxo->key2,txid2,vout2); + if ( LP_ismine(utxo) > 0 ) + utxo->T.sessionid = G.LP_sessionid; + else utxo->T.sessionid = sessionid; + if ( coin->inactive == 0 && (selector= LP_mempool_vinscan(&spendtxid,&spendvini,symbol,coinaddr,txid,vout,txid2,vout2)) >= 0 ) + { + printf("utxoadd selector.%d spent in mempool %s vini.%d",selector,bits256_str(str,spendtxid),spendvini); + utxo->T.spentflag = (uint32_t)time(NULL); + } + //printf(" %s %.8f %.8f %p addutxo.%d (%s %s) session.%u iambob.%d <<<<<<<<<<<<<<< %.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,G.LP_utxoinfos[iambob],utxo->key,sizeof(utxo->key),utxo); + if ( _LP_utxo2find(iambob,txid2,vout2) == 0 ) + HASH_ADD_KEYPTR(hh2,G.LP_utxoinfos2[iambob],utxo->key2,sizeof(utxo->key2),utxo); + portable_mutex_unlock(&LP_utxomutex); + if ( iambob != 0 ) + { + if ( LP_ismine(utxo) > 0 ) + { + //LP_utxo_clientpublish(utxo); + if ( LP_mypeer != 0 ) + utxo->T.lasttime = (uint32_t)time(NULL); + } + } + return(utxo); +} + +int32_t _LP_utxos_remove(bits256 txid,int32_t vout) +{ + struct LP_utxoinfo *utxo,*utxo2; int32_t retval = 0,iambob = 1; + utxo = utxo2 = 0; + if ( (utxo= _LP_utxofind(iambob,txid,vout)) != 0 ) + { + if ( LP_isavailable(utxo) == 0 ) + retval = -1; + else + { + if ( (utxo2= _LP_utxo2find(iambob,txid,vout)) != 0 ) + { + if ( LP_isavailable(utxo) == 0 ) + retval = -1; + else + { + _LP_utxo_delete(iambob,utxo); + _LP_utxo2_delete(iambob,utxo2); + } + } + } + } + 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_utxos_remove(bits256 txid,int32_t vout) +{ + 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) +{ + struct LP_utxoinfo *utxo,*tmp; struct _LP_utxoinfo u; char *myipaddr; cJSON *array; uint64_t val,val2; int32_t iambob = 0; struct iguana_info *coin; + array = cJSON_CreateArray(); + if ( LP_mypeer != 0 ) + myipaddr = LP_mypeer->ipaddr; + else myipaddr = "127.0.0.1"; + if ( (coin= LP_coinfind(symbol)) != 0 ) + LP_listunspent_both(symbol,coin->smartaddr,0); + HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,tmp) + { + char str[65]; + //printf("iambob.%d iterate %s\n",iambob,bits256_str(str,LP_mypub25519)); + if ( LP_isunspent(utxo) != 0 && strcmp(symbol,utxo->coin) == 0 && utxo->iambob == iambob && LP_ismine(utxo) > 0 ) + { + u = (iambob != 0) ? utxo->deposit : utxo->fee; + if ( LP_iseligible(&val,&val2,iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,u.txid,u.vout) == 0 ) + { + //if ( utxo->T.spentflag == 0 ) + // utxo->T.spentflag = (uint32_t)time(NULL); + //printf("%s %s ineligible %.8f %.8f\n",utxo->coin,bits256_str(str,u.txid),dstr(val),dstr(val2)); + continue; + } + //if ( iambob != 0 ) + // LP_utxo_clientpublish(utxo); + jaddi(array,LP_inventoryjson(cJSON_CreateObject(),utxo)); + } + else if ( 0 && LP_ismine(utxo) > 0 && strcmp(symbol,utxo->coin) == 0 ) + printf("skip %s %s %d %d %d %d\n",utxo->coin,bits256_str(str,utxo->payment.txid),LP_isunspent(utxo) != 0,strcmp(symbol,utxo->coin) == 0,utxo->iambob == iambob,LP_ismine(utxo) > 0); + } + return(array); +} + +/*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); + }*/ +//struct LP_pubkey_info *pubp,*ptmp; //cJSON *retjson; struct iguana_info *coin,*tmp; +/*HASH_ITER(hh,LP_coins,coin,tmp) // firstrefht,firstscanht,lastscanht + { + if ( coin->electrum != 0 && time(NULL) > coin->lastunspent+30 ) + { + //printf("call electrum listunspent.%s\n",coin->symbol); + if ( (retjson= electrum_address_listunspent(coin->symbol,coin->electrum,&retjson,coin->smartaddr,2)) != 0 ) + free_json(retjson); + coin->lastunspent = (uint32_t)time(NULL); + } + }*/ +/*HASH_ITER(hh,LP_pubkeyinfos,pubp,ptmp) + { + pubp->dynamictrust = LP_dynamictrust(pubp->pubkey,0); + }*/ +/*void LP_prices_parse(struct LP_peerinfo *peer,cJSON *obj) + { + struct LP_pubkey_info *pubp; struct LP_priceinfo *basepp,*relpp; uint32_t timestamp; bits256 pubkey; cJSON *asks,*item; uint8_t rmd160[20]; int32_t i,n,relid,mismatch; char *base,*rel,*hexstr; double askprice; uint32_t now; + now = (uint32_t)time(NULL); + pubkey = jbits256(obj,"pubkey"); + if ( bits256_nonz(pubkey) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 ) + { + if ( (hexstr= jstr(obj,"rmd160")) != 0 && strlen(hexstr) == 2*sizeof(rmd160) ) + decode_hex(rmd160,sizeof(rmd160),hexstr); + if ( memcmp(pubp->rmd160,rmd160,sizeof(rmd160)) != 0 ) + mismatch = 1; + else mismatch = 0; + if ( bits256_cmp(pubkey,G.LP_mypub25519) == 0 && mismatch == 0 ) + peer->needping = 0; + LP_pubkey_sigcheck(pubp,obj); + timestamp = juint(obj,"timestamp"); + if ( timestamp > now ) + timestamp = now; + if ( timestamp >= pubp->timestamp && (asks= jarray(&n,obj,"asks")) != 0 ) + { + for (i=0; i 0 ) + { + if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 ) + { + //char str[65]; printf("gotprice %s %s/%s (%d/%d) %.8f\n",bits256_str(str,pubkey),base,rel,basepp->ind,relid,askprice); + pubp->matrix[basepp->ind][relid] = askprice; + //pubp->timestamps[basepp->ind][relid] = timestamp; + if ( (relpp= LP_priceinfofind(rel)) != 0 ) + { + dxblend(&basepp->relvals[relpp->ind],askprice,0.9); + dxblend(&relpp->relvals[basepp->ind],1. / askprice,0.9); + } + } + } + } + } + } + } + + void LP_peer_pricesquery(struct LP_peerinfo *peer) + { + char *retstr; cJSON *array; int32_t i,n; + if ( strcmp(peer->ipaddr,LP_myipaddr) == 0 ) + return; + peer->needping = (uint32_t)time(NULL); + if ( (retstr= issue_LP_getprices(peer->ipaddr,peer->port)) != 0 ) + { + 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); + } + }*/ + +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; } } @@ -2245,6 +3686,80 @@ void LP_price_broadcastloop(void *ctx) sleep(LP_ORDERBOOK_DURATION * .9); } } +/*if ( expiration != 0 ) + { + redeemlen = LP_deposit_addr(vinaddr,redeemscript,coin->taddr,coin->p2shtype,expiration,G.LP_pubsecp); + if ( strcmp(depositaddr,vinaddr) == 0 ) + { + claimtime = (uint32_t)time(NULL)-777; + if ( claimtime <= expiration ) + { + printf("claimtime.%u vs locktime.%u, need to wait %d seconds\n",claimtime,timestamp,(int32_t)timestamp-claimtime); + return(clonestr("{\"error\":\"need to wait to claim\"}")); + } + sum += LP_claimtx(ctx,coin,txids,utxotxid,utxovout,satoshis,vinaddr,claimtime,redeemscript,redeemlen); + + }*/ +/*timestamp = (now / LP_WEEKMULT) * LP_WEEKMULT + LP_WEEKMULT; + while ( timestamp > LP_FIRSTWEEKTIME ) + { + if ( expiration != 0 ) + timestamp = expiration; + else timestamp -= LP_WEEKMULT; + redeemlen = LP_deposit_addr(vinaddr,redeemscript,coin->taddr,coin->p2shtype,timestamp,G.LP_pubsecp); + if ( strcmp(depositaddr,vinaddr) == 0 ) + { + claimtime = (uint32_t)time(NULL)-777; + if ( claimtime <= timestamp ) + { + printf("claimtime.%u vs locktime.%u, need to wait %d seconds\n",claimtime,timestamp,(int32_t)timestamp-claimtime); + } + else + { + printf("found %s at timestamp.%u\n",vinaddr,timestamp); + memset(zero.bytes,0,sizeof(zero)); + if ( (array= LP_listunspent(coin->symbol,vinaddr,zero,zero)) != 0 ) + { + //printf("unspents.(%s)\n",jprint(array,0)); + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; i 0 ) + { + for (i=0; itotalrelvolume * .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 = (rand() % maxind) + 1; +peerind = (LP_rand() % maxind) + 1; else peerind = 1; sock = LP_peerindsock(&peerind); if ( sock >= 0 ) @@ -2320,11 +3862,11 @@ void _LP_queuesend(uint32_t crc32,int32_t sock0,int32_t sock1,uint8_t *msg,int32 else { if ( (maxind= LP_numpeers()) > 0 ) - peerind = (rand() % maxind) + 1; + peerind = (LP_rand() % maxind) + 1; else peerind = 1; sock0 = LP_peerindsock(&peerind); if ( (maxind= LP_numpeers()) > 0 ) - peerind = (rand() % maxind) + 1; + peerind = (LP_rand() % maxind) + 1; else peerind = 1; sock1 = LP_peerindsock(&peerind); } @@ -2508,6 +4050,36 @@ if ( (0) ) #undef aptr #undef bptr }*/ +/*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); + }*/ + +/*if ( (sobj= jobj(v,"scriptPubKey")) != 0 ) + { + if ( (scriptstr= jstr(sobj,"hex")) != 0 ) + { + printf("amount64 %.8f vout.%d (%s) weeki.%d %.8f (%s)\n",dstr(amount64),vout,jprint(v,0),weeki,dstr(satoshis),scriptstr); + len = (int32_t)strlen(scriptstr) >> 1; + if ( len <= sizeof(spendscript)/sizeof(*spendscript) ) + { + decode_hex(spendscript,len,scriptstr); + if ( spendscript[11] == 33 ) + { + pub33 = &spendscript[12]; + redeemlen = LP_deposit_addr(p2shaddr,redeemscript,coin->taddr,coin->p2shtype,timestamp,pub33); + if ( len == redeemlen && (timestamp % LP_WEEKMULT) == 0 ) + { + bitcoin_address(coinaddr,coin->taddr,coin->pubtype,pub33,33); + printf("%s -> matched %s script t.%u weeki.%d deposit %.8f\n",coinaddr,p2shaddr,timestamp,(timestamp-LP_FIRSTWEEKTIME)/LP_WEEKMULT,dstr(satoshis)); + // add to pubp->credits; + } + } + } + } + }*/ /*portable_mutex_lock(&ep->pendingQ.mutex); if ( ep->pendingQ.list != 0 ) @@ -2528,6 +4100,184 @@ if ( (0) ) portable_mutex_unlock(&ep->pendingQ.mutex);*/ //printf("%p SENT.(%s) to %s:%u\n",sitem,sitem->str,ep->ipaddr,ep->port); +#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) +{ + bits256 pubkey; char *obookstr,coinaddr[64]; cJSON *orderbook,*asks,*rawasks,*item; int32_t maxiters,i,j,numasks,max; struct LP_address_utxo **utxos; double price; struct LP_pubkey_info *pubp; uint64_t asatoshis; struct iguana_info *basecoin; struct LP_utxoinfo *bestutxo = 0; + maxiters = 100; + *ordermatchpricep = 0.; + *bestsatoshisp = *bestdestsatoshisp = 0; + basecoin = LP_coinfind(base); + if ( duration <= 0 ) + duration = LP_ORDERBOOK_DURATION; + 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 ( (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 ) + { + if ( bits256_nonz(destpubkey) == 0 ) + { + for (j=0; jtaddr,basecoin->pubtype,pubp->rmd160,sizeof(pubp->rmd160)); + asatoshis = autxo->S.satoshis; + //LP_listunspent_query(base,coinaddr); + for (j=0; jpubkey,gui)) != 0 ) + { + //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; + } + if ( j < maxiters ) + break; + } else printf("self trading or blacklisted peer\n"); + } + else + { + if ( i == 0 ) + printf("too expensive maxprice %.8f vs %.8f\n",maxprice,price); + break; + } + } + if ( asks != 0 && asks != rawasks ) + free_json(asks); + } + free_json(orderbook); + } + free(obookstr); + } + free(utxos); + if ( *ordermatchpricep == 0. || *bestdestsatoshisp == 0 ) + return(0); + int32_t changed; + LP_mypriceset(&changed,autxo->coin,base,1. / *ordermatchpricep); + return(bestutxo); +} +#endif +#ifdef oldway +//LP_RTmetrics_update(base,rel); +while ( 1 ) +{ + if ( (bestutxo= LP_buyutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,gui,pubkeys,numpubs,destpubkey)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) + { + 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)); +} +return(clonestr("{\"error\":\"cant get here\"}")); +#endif + +if ( 0 ) +{ + char *p2sh = "bJVtQF2o8B6sdNjeXupzNw5rnidJUNwPJD",p2shaddr[64]; uint8_t script[512],pub33[33]; uint32_t timestamp; + decode_hex(pub33,33,"03fe754763c176e1339a3f62ee6b9484720e17ee4646b65a119e9f6370c7004abc"); + for (timestamp=1510934803-3600*24; timestamp<1510934803+3600*24; timestamp++) + { + LP_deposit_addr(p2shaddr,script,0,85,timestamp,pub33); + if ( strcmp(p2shaddr,p2sh) == 0 ) + { + printf("matched timestamp.%u\n",timestamp); + break; + } else printf("%s ",p2shaddr); + } +} + +/*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++; + } + }*/ + 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; diff --git a/iguana/exchanges/LP_stats.c b/iguana/exchanges/LP_stats.c index 1fcea0355..a434cf936 100644 --- a/iguana/exchanges/LP_stats.c +++ b/iguana/exchanges/LP_stats.c @@ -20,22 +20,82 @@ #define LP_STATSLOG_FNAME "stats.log" -struct LP_swapstats -{ - UT_hash_handle hh; - struct LP_quoteinfo Q; - bits256 bobdeposit,alicepayment,bobpayment,paymentspent,Apaymentspent,depositspent; - double qprice; - uint64_t aliceid; - uint32_t ind,methodind,finished,expired; - char alicegui[32],bobgui[32]; -} *LP_swapstats; +struct LP_swapstats *LP_swapstats,*LP_RTstats; int32_t LP_statslog_parsequote(char *method,cJSON *lineobj); char *LP_stats_methods[] = { "unknown", "request", "reserved", "connect", "connected", "tradestatus" }; +#define LP_TRADESTATUS_METHODIND 5 static uint32_t LP_requests,LP_reserveds,LP_connects,LP_connecteds,LP_tradestatuses,LP_parse_errors,LP_unknowns,LP_duplicates,LP_aliceids; +void LP_dPoW_request(struct iguana_info *coin) +{ + bits256 zero; cJSON *reqjson; + reqjson = cJSON_CreateObject(); + jaddstr(reqjson,"method","getdPoW"); + jaddstr(reqjson,"coin",coin->symbol); + memset(zero.bytes,0,sizeof(zero)); + //printf("request %s\n",jprint(reqjson,0)); + LP_reserved_msg(0,coin->symbol,coin->symbol,zero,jprint(reqjson,1)); +} + +void LP_dPoW_broadcast(struct iguana_info *coin) +{ + bits256 zero; cJSON *reqjson; + if ( time(NULL) > coin->dPoWtime+60 && (coin->isassetchain != 0 || strcmp(coin->symbol,"KMD") == 0) ) + { + reqjson = cJSON_CreateObject(); + jaddstr(reqjson,"method","dPoW"); + jaddstr(reqjson,"coin",coin->symbol); + jaddnum(reqjson,"notarized",coin->notarized); + jaddbits256(reqjson,"notarizedhash",coin->notarizedhash); + jaddbits256(reqjson,"notarizationtxid",coin->notarizationtxid); + memset(zero.bytes,0,sizeof(zero)); + //printf("broadcast %s\n",jprint(reqjson,0)); + LP_reserved_msg(0,coin->symbol,coin->symbol,zero,jprint(reqjson,1)); + coin->dPoWtime = (uint32_t)time(NULL); + } +} + +char *LP_dPoW_recv(cJSON *argjson) +{ + int32_t notarized; bits256 notarizedhash,notarizationtxid; char *symbol; struct iguana_info *coin; + if ( (symbol= jstr(argjson,"coin")) != 0 && (coin= LP_coinfind(symbol)) != 0 && coin->electrum != 0 ) + { + notarized = jint(argjson,"notarized"); + notarizedhash = jbits256(argjson,"notarizedhash"); + notarizationtxid = jbits256(argjson,"notarizationtxid"); + //printf("dPoW %s\n",jprint(argjson,0)); + if ( notarized > coin->notarized && LP_notarization_validate(symbol,notarized,notarizedhash,notarizationtxid) == 0 ) + { + coin->notarized = notarized; + coin->notarizedhash = notarizedhash; + coin->notarizationtxid = notarizationtxid; + printf("VALIDATED dPoW %s\n",jprint(argjson,0)); + } + } + return(clonestr("{\"result\":\"success\"}")); +} + +/*int32_t LP_dPoWheight(struct iguana_info *coin) // get dPoW protected height +{ + int32_t notarized,oldnotarized; + if ( coin->electrum == 0 ) + { + coin->heighttime = (uint32_t)(time(NULL) - 61); + oldnotarized = coin->notarized; + LP_getheight(¬arized,coin); + if ( notarized != 0 && notarized != oldnotarized ) + { + printf("dPoWheight.%s %d <- %d\n",coin->symbol,oldnotarized,notarized); + coin->notarized = notarized; + } + } + else if ( coin->notarized == 0 ) + LP_dPoW_request(coin); + return(coin->notarized); +}*/ + void LP_tradecommand_log(cJSON *argjson) { static FILE *logfp; char *jsonstr; @@ -90,13 +150,14 @@ void LP_statslog_parseline(cJSON *lineobj) int32_t LP_statslog_parse() { - static long lastpos; FILE *fp; char line[8192]; cJSON *lineobj; int32_t n = 0; + static long lastpos; + FILE *fp; long fpos; char line[8192]; cJSON *lineobj; int32_t c,n = 0; if ( (fp= fopen(LP_STATSLOG_FNAME,"rb")) != 0 ) { if ( lastpos > 0 ) { fseek(fp,0,SEEK_END); - if ( ftell(fp) > lastpos ) + if ( ftell(fp) >= lastpos ) fseek(fp,lastpos,SEEK_SET); else { @@ -104,6 +165,20 @@ int32_t LP_statslog_parse() return(0); } } + else if ( 1 ) + { + if ( IAMLP == 0 ) + { + fseek(fp,0,SEEK_END); + if ( (fpos= ftell(fp)) > LP_CLIENT_STATSPARSE ) + { + fseek(fp,fpos-LP_CLIENT_STATSPARSE,SEEK_SET); + while ( (c= fgetc(fp)) >= 0 && c != '\n' ) + ; + printf("start scanning %s from %ld, found boundary %ld\n",LP_STATSLOG_FNAME,fpos-LP_CLIENT_STATSPARSE,ftell(fp)); + } else rewind(fp); + } + } while ( fgets(line,sizeof(line),fp) > 0 ) { lastpos = ftell(fp); @@ -123,18 +198,22 @@ int32_t LP_statslog_parse() struct LP_swapstats *LP_swapstats_find(uint64_t aliceid) { struct LP_swapstats *sp; - HASH_FIND(hh,LP_swapstats,&aliceid,sizeof(aliceid),sp); + HASH_FIND(hh,LP_RTstats,&aliceid,sizeof(aliceid),sp); + if ( sp == 0 ) + HASH_FIND(hh,LP_swapstats,&aliceid,sizeof(aliceid),sp); return(sp); } -struct LP_swapstats *LP_swapstats_add(uint64_t aliceid) +struct LP_swapstats *LP_swapstats_add(uint64_t aliceid,int32_t RTflag) { struct LP_swapstats *sp; if ( (sp= LP_swapstats_find(aliceid)) == 0 ) { sp = calloc(1,sizeof(*sp)); sp->aliceid = aliceid; - HASH_ADD(hh,LP_swapstats,aliceid,sizeof(aliceid),sp); + if ( RTflag != 0 ) + HASH_ADD(hh,LP_RTstats,aliceid,sizeof(aliceid),sp); + else HASH_ADD(hh,LP_swapstats,aliceid,sizeof(aliceid),sp); } return(LP_swapstats_find(aliceid)); } @@ -173,6 +252,7 @@ bits256 LP_swapstats_txid(cJSON *argjson,char *name,bits256 oldtxid) int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSON *lineobj) { char *statusstr,*base,*rel,gui[64]; uint32_t requestid,quoteid; uint64_t satoshis,destsatoshis; + sp->lasttime = (uint32_t)time(NULL); safecopy(gui,sp->Q.gui,sizeof(gui)); if ( strcmp(LP_stats_methods[sp->methodind],"tradestatus") == 0 ) { @@ -182,7 +262,7 @@ int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSO quoteid = juint(lineobj,"quoteid"); satoshis = jdouble(lineobj,"srcamount") * SATOSHIDEN; destsatoshis = jdouble(lineobj,"destamount") * SATOSHIDEN; - if ( base != 0 && strcmp(base,sp->Q.srccoin) == 0 && rel != 0 && strcmp(rel,sp->Q.destcoin) == 0 && requestid == sp->Q.R.requestid && quoteid == sp->Q.R.quoteid && ((satoshis+2*sp->Q.txfee)|1) == (sp->Q.satoshis|1) && ((destsatoshis+2*sp->Q.desttxfee)|1) == (sp->Q.destsatoshis|1) ) + if ( base != 0 && strcmp(base,sp->Q.srccoin) == 0 && rel != 0 && strcmp(rel,sp->Q.destcoin) == 0 && requestid == sp->Q.R.requestid && quoteid == sp->Q.R.quoteid && llabs((int64_t)(satoshis+2*sp->Q.txfee) - (int64_t)sp->Q.satoshis) <= sp->Q.txfee && llabs((int64_t)(destsatoshis+2*sp->Q.desttxfee) - (int64_t)sp->Q.destsatoshis) <= sp->Q.desttxfee ) { sp->bobdeposit = LP_swapstats_txid(lineobj,"bobdeposit",sp->bobdeposit); sp->alicepayment = LP_swapstats_txid(lineobj,"alicepayment",sp->alicepayment); @@ -195,14 +275,14 @@ int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSO if ( (sp->finished= juint(lineobj,"timestamp")) == 0 ) sp->finished = (uint32_t)time(NULL); } - if ( sp->finished == 0 && time(NULL) > sp->Q.timestamp+INSTANTDEX_LOCKTIME*2 ) + if ( sp->finished == 0 && time(NULL) > sp->Q.timestamp+LP_atomic_locktime(base,rel)*2 ) sp->expired = (uint32_t)time(NULL); return(0); } else { - if ( requestid == sp->Q.R.requestid && quoteid == sp->Q.R.quoteid ) - printf("mismatched tradestatus aliceid.%016llx b%s/%s r%s/%s r%u/%u q%u/%u %.8f/%.8f -> %.8f/%.8f\n",(long long)sp->aliceid,base,sp->Q.srccoin,rel,sp->Q.destcoin,requestid,sp->Q.R.requestid,quoteid,sp->Q.R.quoteid,dstr(satoshis+2*sp->Q.txfee),dstr(sp->Q.satoshis),dstr(destsatoshis+2*sp->Q.desttxfee),dstr(sp->Q.destsatoshis)); + if ( 0 && requestid == sp->Q.R.requestid && quoteid == sp->Q.R.quoteid ) + printf("mismatched tradestatus aliceid.%22llu b%s/%s r%s/%s r%u/%u q%u/%u %.8f/%.8f -> %.8f/%.8f\n",(long long)sp->aliceid,base,sp->Q.srccoin,rel,sp->Q.destcoin,requestid,sp->Q.R.requestid,quoteid,sp->Q.R.quoteid,dstr(satoshis+2*sp->Q.txfee),dstr(sp->Q.satoshis),dstr(destsatoshis+2*sp->Q.desttxfee),dstr(sp->Q.destsatoshis)); return(-1); } @@ -212,10 +292,140 @@ int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSO return(0); } +int32_t LP_finished_lastheight(struct LP_swapstats *sp) +{ + int32_t height = 1; struct iguana_info *bob,*alice; //char str[65]; + if ( (bob= LP_coinfind(sp->Q.srccoin)) != 0 && (alice= LP_coinfind(sp->Q.destcoin)) != 0 ) + { + if ( strcmp(bob->symbol,"BTC") == 0 ) + sp->bobneeds_dPoW = 0; + if ( strcmp(alice->symbol,"BTC") == 0 ) + sp->aliceneeds_dPoW = 0; + if ( sp->bobneeds_dPoW != 0 ) + { + if ( bits256_nonz(sp->bobdeposit) != 0 && sp->bobdeposit_ht == 0 ) + { + if ( (sp->bobdeposit_ht= LP_txheight(bob,sp->bobdeposit)) > sp->bobneeds_dPoW ) + sp->bobneeds_dPoW = sp->bobdeposit_ht; + //printf("%s bobdeposit.%d height.%d\n",bits256_str(str,sp->bobdeposit),ht,sp->bobneeds_dPoW); + } + if ( bits256_nonz(sp->bobpayment) != 0 && sp->bobpayment_ht == 0 ) + { + if ( (sp->bobpayment_ht= LP_txheight(bob,sp->bobpayment)) > sp->bobneeds_dPoW ) + sp->bobneeds_dPoW = sp->bobpayment_ht; + //printf("%s bobpayment.%d height.%d\n",bits256_str(str,sp->bobpayment),ht,sp->bobneeds_dPoW); + } + if ( bits256_nonz(sp->paymentspent) != 0 && sp->paymentspent_ht == 0 ) + { + if ( (sp->paymentspent_ht= LP_txheight(bob,sp->paymentspent)) > sp->bobneeds_dPoW ) + sp->bobneeds_dPoW = sp->paymentspent_ht; + //printf("%s paymentspent.%d height.%d\n",bits256_str(str,sp->paymentspent),ht,sp->bobneeds_dPoW); + } + if ( bits256_nonz(sp->depositspent) != 0 && sp->depositspent_ht == 0 ) + { + if ( (sp->depositspent_ht= LP_txheight(bob,sp->depositspent)) > sp->bobneeds_dPoW ) + sp->bobneeds_dPoW = sp->depositspent_ht; + //printf("%s depositspent.%d height.%d\n",bits256_str(str,sp->depositspent),ht,sp->bobneeds_dPoW); + } + } + if ( sp->aliceneeds_dPoW != 0 ) + { + if ( bits256_nonz(sp->alicepayment) != 0 && sp->alicepayment_ht == 0 ) + { + if ( (sp->alicepayment_ht= LP_txheight(alice,sp->alicepayment)) > sp->aliceneeds_dPoW ) + sp->aliceneeds_dPoW = sp->alicepayment_ht; + //printf("%s alicepayment.%d height.%d\n",bits256_str(str,sp->alicepayment),ht,sp->aliceneeds_dPoW); + } + if ( bits256_nonz(sp->Apaymentspent) != 0 && sp->Apaymentspent_ht == 0 ) + { + if ( (sp->Apaymentspent_ht= LP_txheight(alice,sp->Apaymentspent)) > sp->aliceneeds_dPoW ) + sp->aliceneeds_dPoW = sp->Apaymentspent_ht; + //printf("%s Apaymentspent.%d height.%d\n",bits256_str(str,sp->Apaymentspent),ht,sp->aliceneeds_dPoW); + } + } + } + return(height); +} + +int32_t LP_swap_finished(struct LP_swapstats *sp,int32_t dPoWflag) +{ + struct iguana_info *bob,*alice; + if ( sp->dPoWfinished != 0 || sp->expired != 0 ) + return(1); + else if ( dPoWflag == 0 && sp->finished != 0 ) + return(1); + if ( (bob= LP_coinfind(sp->Q.srccoin)) == 0 ) + { + //printf("no bobcoin.%s\n",sp->Q.srccoin); + return(0); + } + if ( (alice= LP_coinfind(sp->Q.destcoin)) == 0 ) + { + //printf("no alicecoin.%s\n",sp->Q.destcoin); + return(0); + } + if ( dPoWflag != 0 ) + { + if ( sp->finished != 0 ) + { + LP_finished_lastheight(sp); + if ( 0 && IAMLP == 0 ) + printf("bob needs %d @ %d, alice needs %d @ %d\n",sp->bobneeds_dPoW,bob->notarized,sp->aliceneeds_dPoW,alice->notarized); + } + if ( (sp->bobneeds_dPoW == 0 || (sp->bobneeds_dPoW > 1 && bob->notarized >= sp->bobneeds_dPoW)) && (sp->aliceneeds_dPoW == 0 || (sp->aliceneeds_dPoW > 1 && alice->notarized >= sp->aliceneeds_dPoW)) ) + { + sp->dPoWfinished = (uint32_t)time(NULL); + return(1); + } + } + return(0); +} + +struct LP_swapstats *LP_swapstats_create(uint64_t aliceid,int32_t RTflag,struct LP_quoteinfo *qp,double qprice,int32_t methodind) +{ + struct LP_pubswap *ptr; struct iguana_info *alice,*bob; struct LP_pubkey_info *pubp; char *base,*rel; struct LP_swapstats *sp = 0; + base = qp->srccoin, rel = qp->destcoin; + if ( (sp= LP_swapstats_add(aliceid,RTflag)) != 0 ) + { + sp->Q = *qp; + sp->qprice = qprice; + sp->methodind = methodind; + sp->ind = LP_aliceids++; + sp->lasttime = (uint32_t)time(NULL); + if ( sp->lasttime > sp->Q.timestamp+LP_atomic_locktime(base,rel)*2 ) + sp->expired = sp->lasttime; + else + { + if ( (alice= LP_coinfind(rel)) != 0 && (alice->isassetchain != 0 || strcmp("KMD",alice->symbol) == 0) ) + sp->aliceneeds_dPoW = 1; + if ( (bob= LP_coinfind(rel)) != 0 && (bob->isassetchain != 0 || strcmp(bob->symbol,"KMD") == 0) ) + sp->bobneeds_dPoW = 1; + } + strcpy(sp->bobgui,"nogui"); + strcpy(sp->alicegui,"nogui"); + if ( LP_swap_finished(sp,1) == 0 ) //sp->finished == 0 && sp->expired == 0 ) + { + if ( (pubp= LP_pubkeyadd(qp->srchash)) != 0 ) + { + ptr = calloc(1,sizeof(*ptr)); + ptr->swap = sp; + DL_APPEND(pubp->bobswaps,ptr); + } + if ( (pubp= LP_pubkeyadd(qp->desthash)) != 0 ) + { + ptr = calloc(1,sizeof(*ptr)); + ptr->swap = sp; + DL_APPEND(pubp->aliceswaps,ptr); + } + } + } else printf("unexpected LP_swapstats_add failure\n"); + return(sp); +} + int32_t LP_statslog_parsequote(char *method,cJSON *lineobj) { static uint32_t unexpected; - struct LP_swapstats *sp,*tmp; double qprice; uint32_t requestid,quoteid,timestamp; int32_t i,flag,numtrades[LP_MAXPRICEINFOS],methodind,destvout,feevout,duplicate=0; char *gui,*base,*rel; uint64_t aliceid,txfee,satoshis,destsatoshis; bits256 desttxid,feetxid; struct LP_quoteinfo Q; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS]; + struct LP_swapstats *sp,*tmp; double qprice; uint32_t requestid,quoteid,timestamp; int32_t i,RTflag,flag,numtrades[LP_MAXPRICEINFOS],methodind,destvout,feevout,duplicate=0; char *statusstr,*gui,*base,*rel; uint64_t aliceid,txfee,satoshis,destsatoshis; bits256 desttxid,feetxid; struct LP_quoteinfo Q; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS]; memset(numtrades,0,sizeof(numtrades)); memset(basevols,0,sizeof(basevols)); memset(relvols,0,sizeof(relvols)); @@ -235,8 +445,11 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj) if ( (sp= LP_swapstats_find(aliceid)) != 0 ) { sp->methodind = methodind; + sp->Q.R.requestid = requestid; + sp->Q.R.quoteid = quoteid; if ( LP_swapstats_update(sp,&Q,lineobj) == 0 ) flag = 1; + //else printf("LP_swapstats_update error\n"); } if ( flag == 0 ) { @@ -246,14 +459,20 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj) { sp->methodind = methodind; if ( LP_swapstats_update(sp,&Q,lineobj) == 0 ) + { flag = 1; - else printf("error after delayed match\n"); - break; + break; + } + printf("error after delayed match\n"); } } } if ( flag == 0 ) - printf("unexpected.%d tradestatus.(%s)\n",unexpected++,jprint(lineobj,0)); + { + static uint32_t counter; + if ( counter++ < 3 ) + printf("unexpected.%d tradestatus aliceid.%llu requestid.%u quoteid.%u\n",unexpected++,(long long)aliceid,requestid,quoteid);//,jprint(lineobj,0)); + } return(0); } if ( LP_quoteparse(&Q,lineobj) < 0 ) @@ -283,6 +502,9 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj) destvout = jint(lineobj,"destvout"); feetxid = jbits256(lineobj,"feetxid"); feevout = jint(lineobj,"feevout"); + if ( (statusstr= jstr(lineobj,"status")) != 0 && strcmp(statusstr,"finished") == 0 ) + RTflag = 0; + else RTflag = 1; qprice = ((double)destsatoshis / (satoshis - txfee)); //printf("%s/v%d %s/v%d\n",bits256_str(str,desttxid),destvout,bits256_str(str2,feetxid),feevout); aliceid = LP_aliceid_calc(desttxid,destvout,feetxid,feevout); @@ -298,17 +520,8 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj) } else { - if ( (sp= LP_swapstats_add(aliceid)) != 0 ) - { - sp->Q = Q; - sp->qprice = qprice; - sp->methodind = methodind; - sp->ind = LP_aliceids++; - strcpy(sp->bobgui,"nogui"); - strcpy(sp->alicegui,"nogui"); - //LP_swapstats_line(numtrades,basevols,relvols,line,sp); - //printf("%s\n",line); - } else printf("unexpected LP_swapstats_add failure\n"); + sp = LP_swapstats_create(aliceid,RTflag,&Q,qprice,methodind); + //printf("create aliceid.%llu\n",(long long)aliceid); } if ( sp != 0 ) { @@ -323,11 +536,194 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj) return(duplicate == 0); } -char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey) +cJSON *LP_swapstats_json(struct LP_swapstats *sp) +{ + cJSON *item = cJSON_CreateObject(); + jaddnum(item,"timestamp",sp->Q.timestamp); + jadd64bits(item,"aliceid",sp->aliceid); + jaddbits256(item,"src",sp->Q.srchash); + jaddstr(item,"base",sp->Q.srccoin); + jaddnum(item,"basevol",dstr(sp->Q.satoshis)); + jaddbits256(item,"dest",sp->Q.desthash); + jaddstr(item,"rel",sp->Q.destcoin); + jaddnum(item,"relvol",dstr(sp->Q.destsatoshis)); + jaddnum(item,"price",sp->qprice); + jaddnum(item,"requestid",sp->Q.R.requestid); + jaddnum(item,"quoteid",sp->Q.R.quoteid); + jaddnum(item,"finished",sp->finished); + jaddnum(item,"expired",sp->expired); + if ( bits256_nonz(sp->bobdeposit) != 0 ) + jaddbits256(item,"bobdeposit",sp->bobdeposit); + if ( bits256_nonz(sp->alicepayment) != 0 ) + jaddbits256(item,"alicepayment",sp->alicepayment); + if ( bits256_nonz(sp->bobpayment) != 0 ) + jaddbits256(item,"bobpayment",sp->bobpayment); + if ( bits256_nonz(sp->paymentspent) != 0 ) + jaddbits256(item,"paymentspent",sp->paymentspent); + if ( bits256_nonz(sp->Apaymentspent) != 0 ) + jaddbits256(item,"Apaymentspent",sp->Apaymentspent); + if ( bits256_nonz(sp->depositspent) != 0 ) + jaddbits256(item,"depositspent",sp->depositspent); + if ( sp->finished == 0 && sp->expired == 0 ) + jaddnum(item,"expires",sp->Q.timestamp + LP_atomic_locktime(sp->Q.srccoin,sp->Q.destcoin)*2 - time(NULL)); + jaddnum(item,"ind",sp->methodind); + //jaddstr(item,"line",line); + return(item); +} + +char *LP_swapstatus_recv(cJSON *argjson) { - cJSON *retjson,*array,*item; struct LP_swapstats *sp,*tmp; int32_t i,dispflag,numtrades[LP_MAXPRICEINFOS]; char line[1024]; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS]; + struct LP_swapstats *sp; char *statusstr; uint64_t aliceid; double qprice; struct LP_quoteinfo Q; int32_t methodind,RTflag; bits256 txid; //char str[65]; + if ( (aliceid= j64bits(argjson,"aliceid")) == 0 ) + return(clonestr("{\"error\":\"LP_swapstatus_recv null aliceid\"}")); + if ( (sp= LP_swapstats_find(aliceid)) == 0 ) + { + LP_quoteparse(&Q,argjson); + if ( Q.satoshis > Q.txfee ) + return(clonestr("{\"error\":\"LP_swapstatus_recv null satoshis\"}")); + qprice = (double)Q.destsatoshis / (Q.satoshis - Q.txfee); + if ( (statusstr= jstr(argjson,"status")) != 0 && strcmp(statusstr,"finished") == 0 ) + RTflag = 0; + else RTflag = 1; + sp = LP_swapstats_create(aliceid,RTflag,&Q,qprice,LP_TRADESTATUS_METHODIND); + //printf("create swapstatus from recv\n"); + } + if ( sp != 0 ) + { + if ( 0 && IAMLP == 0 ) + printf("swapstatus.(%s)\n",jprint(argjson,0)); + sp->lasttime = (uint32_t)time(NULL); + if ( (methodind= jint(argjson,"ind")) > sp->methodind && methodind < sizeof(LP_stats_methods)/sizeof(*LP_stats_methods) ) + { + if ( 0 && sp->finished == 0 && sp->expired == 0 ) + printf("SWAPSTATUS updated %llu %s %u %u\n",(long long)sp->aliceid,LP_stats_methods[sp->methodind],juint(argjson,"finished"),juint(argjson,"expired")); + sp->methodind = methodind; + sp->finished = juint(argjson,"finished"); + sp->expired = juint(argjson,"expired"); + txid = jbits256(argjson,"bobdeposit"); + if ( bits256_nonz(txid) != 0 && bits256_nonz(sp->bobdeposit) == 0 ) + { + sp->bobdeposit = txid; + //printf("set aliceid.%llu bobdeposit %s\n",(long long)sp->aliceid,bits256_str(str,txid)); + } + txid = jbits256(argjson,"alicepayment"); + if ( bits256_nonz(txid) != 0 && bits256_nonz(sp->alicepayment) == 0 ) + { + sp->alicepayment = txid; + //printf("set aliceid.%llu alicepayment %s\n",(long long)sp->aliceid,bits256_str(str,txid)); + } + txid = jbits256(argjson,"bobpayment"); + if ( bits256_nonz(txid) != 0 && bits256_nonz(sp->bobpayment) == 0 ) + { + sp->bobpayment = txid; + //printf("set aliceid.%llu bobpayment %s\n",(long long)sp->aliceid,bits256_str(str,txid)); + } + txid = jbits256(argjson,"paymentspent"); + if ( bits256_nonz(txid) != 0 && bits256_nonz(sp->paymentspent) == 0 ) + { + sp->paymentspent = txid; + //printf("set aliceid.%llu paymentspent %s\n",(long long)sp->aliceid,bits256_str(str,txid)); + } + txid = jbits256(argjson,"Apaymentspent"); + if ( bits256_nonz(txid) != 0 && bits256_nonz(sp->Apaymentspent) == 0 ) + { + sp->Apaymentspent = txid; + //printf("set aliceid.%llu Apaymentspent %s\n",(long long)sp->aliceid,bits256_str(str,txid)); + } + txid = jbits256(argjson,"depositspent"); + if ( bits256_nonz(txid) != 0 && bits256_nonz(sp->depositspent) == 0 ) + { + sp->depositspent = txid; + //printf("set aliceid.%llu depositspent %s\n",(long long)sp->aliceid,bits256_str(str,txid)); + } + } + } + return(clonestr("{\"result\":\"success\"}")); +} + +char *LP_gettradestatus(uint64_t aliceid,uint32_t requestid,uint32_t quoteid) +{ + struct LP_swapstats *sp; struct iguana_info *bob,*alice; char *swapstr,*statusstr; cJSON *reqjson,*swapjson; bits256 zero; + //printf("gettradestatus.(%llu)\n",(long long)aliceid); + if ( IAMLP != 0 ) + { + if ( (sp= LP_swapstats_find(aliceid)) != 0 && sp->Q.satoshis != 0 && sp->Q.destsatoshis != 0 && bits256_nonz(sp->bobdeposit) != 0 ) + { + if ( time(NULL) > sp->lasttime+60 ) + { + if ( (reqjson= LP_swapstats_json(sp)) != 0 ) + { + jaddstr(reqjson,"method","swapstatus"); + memset(zero.bytes,0,sizeof(zero)); + LP_reserved_msg(0,"","",zero,jprint(reqjson,1)); + } + if ( (bob= LP_coinfind(sp->Q.srccoin)) != 0 ) + LP_dPoW_broadcast(bob); + if ( (alice= LP_coinfind(sp->Q.destcoin)) != 0 ) + LP_dPoW_broadcast(alice); + } + return(clonestr("{\"result\":\"success\"}")); + } + } + if ( (swapstr= basilisk_swapentry(requestid,quoteid,0)) != 0 ) + { + if ( (swapjson= cJSON_Parse(swapstr)) != 0 ) + { + if ( (statusstr= jstr(swapjson,"status")) != 0 && strcmp(statusstr,"finished") == 0 ) + { + jaddstr(swapjson,"method","swapstatus"); + memset(zero.bytes,0,sizeof(zero)); + printf("send local swapstatus\n"); + LP_reserved_msg(0,"","",zero,jprint(swapjson,0)); + } + free_json(swapjson); + } + free(swapstr); + } + return(clonestr("{\"result\":\"success\"}")); +} + +int32_t LP_stats_dispiter(cJSON *array,struct LP_swapstats *sp,uint32_t starttime,uint32_t endtime,char *refbase,char *refrel,char *refgui,bits256 refpubkey) +{ + int32_t dispflag,retval = 0; + if ( sp->finished == 0 && sp->expired == 0 && time(NULL) > sp->Q.timestamp+LP_atomic_locktime(sp->Q.srccoin,sp->Q.destcoin)*2 ) + sp->expired = (uint32_t)time(NULL); + if ( LP_swap_finished(sp,1) > 0 ) + retval = 1; + dispflag = 0; + if ( starttime == 0 && endtime == 0 ) + dispflag = 1; + else if ( starttime > time(NULL) && endtime == starttime && sp->finished == 0 && sp->expired == 0 ) + dispflag = 1; + else if ( sp->Q.timestamp >= starttime && sp->Q.timestamp <= endtime ) + dispflag = 1; + if ( refbase != 0 && strcmp(refbase,sp->Q.srccoin) != 0 && strcmp(refbase,sp->Q.destcoin) != 0 ) + dispflag = 0; + if ( refrel != 0 && strcmp(refrel,sp->Q.srccoin) != 0 && strcmp(refrel,sp->Q.destcoin) != 0 ) + dispflag = 0; + if ( dispflag != 0 ) + { + dispflag = 0; + if ( refgui == 0 || refgui[0] == 0 || strcmp(refgui,sp->bobgui) == 0 || strcmp(refgui,sp->alicegui) == 0 ) + { + if ( bits256_nonz(refpubkey) == 0 || bits256_cmp(refpubkey,sp->Q.srchash) == 0 || bits256_cmp(refpubkey,sp->Q.desthash) == 0 ) + dispflag = 1; + } + } + if ( dispflag != 0 ) + jaddi(array,LP_swapstats_json(sp)); + return(retval); +} + +cJSON *LP_statslog_disp(uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey,char *refbase,char *refrel) +{ + static int32_t rval; + cJSON *retjson,*array,*item,*reqjson; struct LP_pubkey_info *pubp,*ptmp; bits256 zero; uint32_t now; struct LP_swapstats *sp,*tmp; int32_t i,n,numtrades[LP_MAXPRICEINFOS]; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS]; + if ( rval == 0 ) + rval = (LP_rand() % 300) + 60; if ( starttime > endtime ) starttime = endtime; + n = LP_statslog_parse(); memset(basevols,0,sizeof(basevols)); memset(relvols,0,sizeof(relvols)); memset(numtrades,0,sizeof(numtrades)); @@ -335,45 +731,41 @@ char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgu jaddstr(retjson,"result","success"); jaddnum(retjson,"newlines",n); array = cJSON_CreateArray(); - HASH_ITER(hh,LP_swapstats,sp,tmp) + LP_RTcount = LP_swapscount = 0; + now = (uint32_t)time(NULL); + HASH_ITER(hh,LP_RTstats,sp,tmp) { - if ( sp->finished == 0 && time(NULL) > sp->Q.timestamp+INSTANTDEX_LOCKTIME*2 ) - sp->expired = (uint32_t)time(NULL); - dispflag = 0; - if ( starttime == 0 && endtime == 0 ) - dispflag = 1; - else if ( starttime > time(NULL) && endtime == starttime && sp->finished == 0 && sp->expired == 0 ) - dispflag = 1; - else if ( sp->Q.timestamp >= starttime && sp->Q.timestamp <= endtime ) - dispflag = 1; - if ( dispflag != 0 ) - { - dispflag = 0; - if ( refgui == 0 || refgui[0] == 0 || strcmp(refgui,sp->bobgui) == 0 || strcmp(refgui,sp->alicegui) == 0 ) - { - if ( bits256_nonz(refpubkey) == 0 || bits256_cmp(refpubkey,sp->Q.srchash) == 0 || bits256_cmp(refpubkey,sp->Q.desthash) == 0 ) - dispflag = 1; - } + if ( LP_stats_dispiter(array,sp,starttime,endtime,refbase,refrel,refgui,refpubkey) > 0 ) + { + HASH_DELETE(hh,LP_RTstats,sp); + HASH_ADD(hh,LP_swapstats,aliceid,sizeof(sp->aliceid),sp); } - if ( dispflag != 0 ) + else { - LP_swapstats_line(numtrades,basevols,relvols,line,sp); - item = cJSON_CreateObject(); - jadd64bits(item,"aliceid",sp->aliceid); - jaddbits256(item,"src",sp->Q.srchash); - jaddstr(item,"base",sp->Q.srccoin); - jaddnum(item,"basevol",dstr(sp->Q.satoshis)); - jaddbits256(item,"dest",sp->Q.desthash); - jaddstr(item,"rel",sp->Q.destcoin); - jaddnum(item,"relvol",dstr(sp->Q.destsatoshis)); - jaddnum(item,"price",sp->qprice); - jaddnum(item,"requestid",sp->Q.R.requestid); - jaddnum(item,"quoteid",sp->Q.R.quoteid); - jaddstr(item,"line",line); - jaddi(array,item); + LP_RTcount++; + if ( now > sp->lasttime+rval ) + { + reqjson = cJSON_CreateObject(); + jaddstr(reqjson,"method","gettradestatus"); + jadd64bits(reqjson,"aliceid",sp->aliceid); + memset(zero.bytes,0,sizeof(zero)); + LP_reserved_msg(0,"","",zero,jprint(reqjson,1)); + } } } + HASH_ITER(hh,LP_swapstats,sp,tmp) + { + LP_stats_dispiter(array,sp,starttime,endtime,refbase,refrel,refgui,refpubkey); + LP_swapscount++; + } + HASH_ITER(hh,LP_pubkeyinfos,pubp,ptmp) + { + pubp->dynamictrust = LP_dynamictrust(0,pubp->pubkey,0); + } + //printf("RT.%d completed.%d\n",LP_RTcount,LP_swapscount); jadd(retjson,"swaps",array); + jaddnum(retjson,"RTcount",LP_RTcount); + jaddnum(retjson,"swapscount",LP_swapscount); array = cJSON_CreateArray(); for (i=0; i-timescale*1024, endtime=, timescale=60) -> [timestamp, high, low, open, close, relvolume, basevolume, aveprice, numtrades] + +struct LP_ohlc +{ + uint32_t timestamp,firsttime,lasttime,numtrades; + double high,low,open,close,relsum,basesum; +}; + +cJSON *LP_ohlc_json(struct LP_ohlc *bar,struct LP_ohlc *prevbar) +{ + cJSON *item; struct LP_ohlc tmp; + memset(&tmp,0,sizeof(tmp)); + if ( bar->numtrades == 0 ) + { + memset(&tmp,0,sizeof(tmp)); + tmp.timestamp = bar->timestamp; + tmp.open = tmp.high = tmp.low = tmp.close = prevbar->close; + tmp.numtrades = 0; + tmp.relsum = tmp.basesum = 0.; + } else tmp = *bar; + bar = &tmp; + item = cJSON_CreateArray(); + jaddinum(item,bar->timestamp); + jaddinum(item,bar->high); + jaddinum(item,bar->low); + jaddinum(item,bar->open); + jaddinum(item,bar->close); + jaddinum(item,bar->relsum); + jaddinum(item,bar->basesum); + if ( bar->basesum != 0 ) + jaddinum(item,bar->relsum / bar->basesum); + else jaddinum(item,0); + jaddinum(item,bar->numtrades); + return(item); +} + +void LP_ohlc_update(struct LP_ohlc *bar,uint32_t timestamp,double basevol,double relvol) +{ + double price; + if ( basevol > SMALLVAL && relvol > SMALLVAL ) + { + price = relvol / basevol; + if ( bar->firsttime == 0 || timestamp < bar->firsttime ) + { + bar->firsttime = timestamp; + bar->open = price; + } + if ( bar->lasttime == 0 || timestamp > bar->lasttime ) + { + bar->lasttime = timestamp; + bar->close = price; + } + if ( bar->low == 0. || price < bar->low ) + bar->low = price; + if ( bar->high == 0. || price > bar->high ) + bar->high = price; + bar->basesum += basevol; + bar->relsum += relvol; + bar->numtrades++; + //printf("%d %.8f/%.8f -> %.8f\n",bar->numtrades,basevol,relvol,price); + } +} + +cJSON *LP_tradesarray(char *refbase,char *refrel,uint32_t starttime,uint32_t endtime,int32_t timescale) +{ + struct LP_ohlc *bars,nonz; cJSON *array,*item,*statsjson,*swaps; uint32_t timestamp; bits256 zero; char *base,*rel; int32_t i,n,numbars,bari; + if ( timescale < 60 ) + return(cJSON_Parse("{\"error\":\"one minute is shortest timescale\"}")); + memset(zero.bytes,0,sizeof(zero)); + if ( endtime == 0 ) + endtime = (((uint32_t)time(NULL) / timescale) * timescale); + if ( starttime == 0 || starttime >= endtime ) + starttime = (endtime - LP_SCREENWIDTH*timescale); + numbars = ((endtime - starttime) / timescale) + 1; + bars = calloc(numbars,sizeof(*bars)); + for (bari=0; bari= starttime && timestamp <= endtime ) + { + bari = (timestamp - starttime) / timescale; + base = jstr(item,"base"); + rel = jstr(item,"rel"); + if ( strcmp(base,refbase) == 0 && strcmp(rel,refrel) == 0 ) + LP_ohlc_update(&bars[bari],timestamp,jdouble(item,"basevol"),jdouble(item,"relvol")); + else if ( strcmp(rel,refbase) == 0 && strcmp(base,refrel) == 0 ) + LP_ohlc_update(&bars[bari],timestamp,jdouble(item,"relvol"),jdouble(item,"basevol")); + } else printf("skip.(%s)\n",jprint(item,0)); + } + } + free_json(statsjson); + } + array = cJSON_CreateArray(); + memset(&nonz,0,sizeof(nonz)); + for (bari=0; bari 0 ) + nonz = bars[bari]; + } + } + free(bars); + return(array); +} diff --git a/iguana/exchanges/LP_swap.c b/iguana/exchanges/LP_swap.c index 0238e398b..da7597e47 100644 --- a/iguana/exchanges/LP_swap.c +++ b/iguana/exchanges/LP_swap.c @@ -109,24 +109,44 @@ */ +uint32_t LP_atomic_locktime(char *base,char *rel) +{ + if ( strcmp(base,"BTC") != 0 && strcmp(rel,"BTC") != 0 ) + return(INSTANTDEX_LOCKTIME); + else return(INSTANTDEX_LOCKTIME * 10); +} + void basilisk_rawtx_purge(struct basilisk_rawtx *rawtx) { if ( rawtx->vins != 0 ) - free_json(rawtx->vins); + free_json(rawtx->vins), rawtx->vins = 0; //if ( rawtx->txbytes != 0 ) // free(rawtx->txbytes), rawtx->txbytes = 0; } void basilisk_swap_finished(struct basilisk_swap *swap) { - int32_t i; + /*int32_t i; if ( swap->utxo != 0 && swap->sentflag == 0 ) { LP_availableset(swap->utxo); swap->utxo = 0; //LP_butxo_swapfields_set(swap->utxo); } - swap->I.finished = (uint32_t)time(NULL); + swap->I.finished = (uint32_t)time(NULL);*/ + if ( swap->I.finished == 0 ) + { + if ( swap->I.iambob != 0 ) + { + LP_availableset(swap->bobdeposit.utxotxid,swap->bobdeposit.utxovout); + LP_availableset(swap->bobpayment.utxotxid,swap->bobpayment.utxovout); + } + else + { + LP_availableset(swap->alicepayment.utxotxid,swap->alicepayment.utxovout); + LP_availableset(swap->myfee.utxotxid,swap->myfee.utxovout); + } + } // save to permanent storage basilisk_rawtx_purge(&swap->bobdeposit); basilisk_rawtx_purge(&swap->bobpayment); @@ -139,11 +159,11 @@ void basilisk_swap_finished(struct basilisk_swap *swap) basilisk_rawtx_purge(&swap->bobspend); basilisk_rawtx_purge(&swap->bobrefund); basilisk_rawtx_purge(&swap->alicereclaim); - for (i=0; inummessages; i++) + /*for (i=0; inummessages; i++) if ( swap->messages[i].data != 0 ) free(swap->messages[i].data), swap->messages[i].data = 0; free(swap->messages), swap->messages = 0; - swap->nummessages = 0; + swap->nummessages = 0;*/ if ( swap->N.pair >= 0 ) nn_close(swap->N.pair), swap->N.pair = -1; } @@ -177,6 +197,8 @@ uint32_t basilisk_requestid(struct basilisk_request *rp) int32_t LP_pubkeys_data(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) { int32_t i,datalen = 0; + datalen += iguana_rwnum(1,&data[datalen],sizeof(swap->I.req.requestid),&swap->I.req.requestid); + datalen += iguana_rwnum(1,&data[datalen],sizeof(swap->I.req.quoteid),&swap->I.req.quoteid); data[datalen++] = swap->I.aliceconfirms; data[datalen++] = swap->I.bobconfirms; data[datalen++] = swap->I.alicemaxconfirms; @@ -186,14 +208,22 @@ int32_t LP_pubkeys_data(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) data[datalen++] = swap->persistent_pubkey33[i]; for (i=0; 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,nonz=0,alicemaxconfirms,bobmaxconfirms,aliceconfirms,bobconfirms,len = 0; uint8_t other33[33]; - if ( datalen == sizeof(swap->otherdeck)+38 ) + uint32_t requestid,quoteid; int32_t i,nonz=0,alicemaxconfirms,bobmaxconfirms,aliceconfirms,bobconfirms,len = 0; uint8_t other33[33]; + if ( datalen == sizeof(swap->otherdeck)+38+sizeof(uint32_t)*2 ) { + len += iguana_rwnum(0,&data[len],sizeof(requestid),&requestid); + len += iguana_rwnum(0,&data[len],sizeof(quoteid),"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++]; @@ -220,7 +250,7 @@ int32_t LP_pubkeys_verify(struct basilisk_swap *swap,uint8_t *data,int32_t datal if ( swap->I.otheristrusted != 0 ) { swap->I.aliceconfirms = swap->I.bobconfirms = 0; - printf("Otherside trusts us, adjust required confirms to: alice.%d bob.%d\n",swap->I.aliceconfirms,swap->I.bobconfirms); + printf("mutually trusted swap, adjust required confirms to: alice.%d bob.%d\n",swap->I.aliceconfirms,swap->I.bobconfirms); } } printf("NUMCONFIRMS for SWAP alice.%d bob.%d, otheristrusted.%d othertrusts.%d\n",swap->I.aliceconfirms,swap->I.bobconfirms,swap->I.otheristrusted,swap->I.otherstrust); @@ -233,7 +263,7 @@ int32_t LP_pubkeys_verify(struct basilisk_swap *swap,uint8_t *data,int32_t datal len += iguana_rwnum(0,&data[len],sizeof(swap->otherdeck[i>>1][i&1]),&swap->otherdeck[i>>1][i&1]); return(0); } - printf("pubkeys verify size mismatch %d != %d\n",datalen,(int32_t)sizeof(swap->otherdeck)+36); + printf("pubkeys verify size mismatch %d != %d\n",datalen,(int32_t)(sizeof(swap->otherdeck)+38+sizeof(uint32_t)*2)); return(-1); } @@ -262,7 +292,7 @@ int32_t LP_choosei_data(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) int32_t LP_choosei_verify(struct basilisk_swap *swap,uint8_t *data,int32_t datalen) { - int32_t otherchoosei=-1,i,len = 0; uint8_t pubkey33[33]; char str[65],str2[65]; + int32_t otherchoosei=-1,i,len = 0; uint8_t pubkey33[33]; if ( datalen == sizeof(otherchoosei)+sizeof(bits256)*2 ) { len += iguana_rwnum(0,data,sizeof(otherchoosei),&otherchoosei); @@ -275,13 +305,13 @@ int32_t LP_choosei_verify(struct basilisk_swap *swap,uint8_t *data,int32_t datal swap->I.pubA0.bytes[i] = data[len++]; for (i=0; i<32; i++) swap->I.pubA1.bytes[i] = data[len++]; - printf("GOT pubA0/1 %s\n",bits256_str(str,swap->I.pubA0)); + //printf("GOT pubA0/1 %s\n",bits256_str(str,swap->I.pubA0)); swap->I.privBn = swap->privkeys[swap->I.otherchoosei]; memset(&swap->privkeys[swap->I.otherchoosei],0,sizeof(swap->privkeys[swap->I.otherchoosei])); revcalc_rmd160_sha256(swap->I.secretBn,swap->I.privBn);//.bytes,sizeof(swap->privBn)); vcalc_sha256(0,swap->I.secretBn256,swap->I.privBn.bytes,sizeof(swap->I.privBn)); swap->I.pubBn = bitcoin_pubkey33(swap->ctx,pubkey33,swap->I.privBn); - printf("set privBn.%s %s\n",bits256_str(str,swap->I.privBn),bits256_str(str2,*(bits256 *)swap->I.secretBn256)); + //printf("set privBn.%s %s\n",bits256_str(str,swap->I.privBn),bits256_str(str2,*(bits256 *)swap->I.secretBn256)); //basilisk_bobscripts_set(swap,1,1); } else @@ -290,18 +320,18 @@ int32_t LP_choosei_verify(struct basilisk_swap *swap,uint8_t *data,int32_t datal swap->I.pubB0.bytes[i] = data[len++]; for (i=0; i<32; i++) swap->I.pubB1.bytes[i] = data[len++]; - printf("GOT pubB0/1 %s\n",bits256_str(str,swap->I.pubB0)); + //printf("GOT pubB0/1 %s\n",bits256_str(str,swap->I.pubB0)); swap->I.privAm = swap->privkeys[swap->I.otherchoosei]; memset(&swap->privkeys[swap->I.otherchoosei],0,sizeof(swap->privkeys[swap->I.otherchoosei])); revcalc_rmd160_sha256(swap->I.secretAm,swap->I.privAm);//.bytes,sizeof(swap->privAm)); vcalc_sha256(0,swap->I.secretAm256,swap->I.privAm.bytes,sizeof(swap->I.privAm)); swap->I.pubAm = bitcoin_pubkey33(swap->ctx,pubkey33,swap->I.privAm); - printf("set privAm.%s %s\n",bits256_str(str,swap->I.privAm),bits256_str(str2,*(bits256 *)swap->I.secretAm256)); + //printf("set privAm.%s %s\n",bits256_str(str,swap->I.privAm),bits256_str(str2,*(bits256 *)swap->I.secretAm256)); swap->bobdeposit.I.pubkey33[0] = 2; swap->bobpayment.I.pubkey33[0] = 2; for (i=0; i<32; i++) swap->bobpayment.I.pubkey33[i+1] = swap->bobdeposit.I.pubkey33[i+1] = swap->I.pubA0.bytes[i]; - printf("SET bobdeposit pubkey33.(02%s)\n",bits256_str(str,swap->I.pubA0)); + //printf("SET bobdeposit pubkey33.(02%s)\n",bits256_str(str,swap->I.pubA0)); //basilisk_bobscripts_set(swap,0); } return(0); @@ -556,7 +586,12 @@ struct basilisk_rawtx *LP_swapdata_rawtx(struct basilisk_swap *swap,uint8_t *dat int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys) { - bits256 otherhash,myhash,txid; int64_t txfee; int32_t i,offset=0,datalen=0,retval=-1,hexlen,n; uint8_t *data; cJSON *txobj,*skey,*vouts,*vout; char *hexstr,redeemaddr[64],checkaddr[64]; uint32_t quoteid,msgbits; + bits256 otherhash,myhash,txid; int64_t txfee,val; int32_t i,offset=0,datalen=0,retval=-1,hexlen,n; uint8_t *data; cJSON *txobj,*skey,*vouts,*vout; char *hexstr,redeemaddr[64],checkaddr[64]; uint32_t quoteid,msgbits; struct iguana_info *coin; + if ( (coin= LP_coinfind(rawtx->symbol)) == 0 ) + { + printf("LP_rawtx_spendscript couldnt find coin.(%s)\n",rawtx->symbol); + return(-1); + } for (i=0; i<32; i++) otherhash.bytes[i] = recvbuf[offset++]; for (i=0; i<32; i++) @@ -577,9 +612,9 @@ int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct ba memcpy(rawtx->redeemscript,&data[datalen],rawtx->I.redeemlen); //for (i=0; 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(rawtx->coin,checkaddr,0,data,datalen,0); + bitcoin_address(redeemaddr,coin->taddr,coin->p2shtype,rawtx->redeemscript,rawtx->I.redeemlen); + //printf(" received redeemscript.(%s) %s taddr.%d\n",redeemaddr,coin->symbol,coin->taddr); + LP_swap_coinaddr(coin,checkaddr,0,data,datalen,0); if ( strcmp(redeemaddr,checkaddr) != 0 ) { printf("REDEEMADDR MISMATCH??? %s != %s\n",redeemaddr,checkaddr); @@ -609,24 +644,27 @@ int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct ba char str[65]; printf("rawtx.%s txid %s\n",rawtx->name,bits256_str(str,txid)); if ( bits256_cmp(txid,rawtx->I.actualtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 ) rawtx->I.actualtxid = txid; - if ( (txobj= bitcoin_data2json(rawtx->coin->taddr,rawtx->coin->pubtype,rawtx->coin->p2shtype,rawtx->coin->isPoS,height,&rawtx->I.signedtxid,&rawtx->msgtx,rawtx->extraspace,sizeof(rawtx->extraspace),data,datalen,0,suppress_pubkeys,rawtx->coin->zcash)) != 0 ) + if ( (txobj= bitcoin_data2json(coin->symbol,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,height,&rawtx->I.signedtxid,&rawtx->msgtx,rawtx->extraspace,sizeof(rawtx->extraspace),data,datalen,0,suppress_pubkeys,coin->zcash)) != 0 ) { rawtx->I.actualtxid = rawtx->I.signedtxid; rawtx->I.locktime = rawtx->msgtx.lock_time; if ( (vouts= jarray(&n,txobj,"vout")) != 0 && v < n ) { vout = jitem(vouts,v); - if ( strcmp("BTC",rawtx->coin->symbol) == 0 && rawtx == &swap->otherfee ) + if ( strcmp("BTC",coin->symbol) == 0 && rawtx == &swap->otherfee ) txfee = LP_MIN_TXFEE; else { - if ( strcmp(rawtx->coin->symbol,swap->bobcoin.symbol) == 0 ) + if ( strcmp(coin->symbol,swap->I.bobstr) == 0 ) txfee = swap->I.Btxfee; - else if ( strcmp(rawtx->coin->symbol,swap->alicecoin.symbol) == 0 ) + else if ( strcmp(coin->symbol,swap->I.alicestr) == 0 ) txfee = swap->I.Atxfee; else txfee = LP_MIN_TXFEE; } - if ( j64bits(vout,"satoshis") >= rawtx->I.amount && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 ) + if ( rawtx->I.amount > 2*txfee) + val = rawtx->I.amount-2*txfee; + else val = 1; + if ( j64bits(vout,"satoshis") >= val && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 ) { if ( (hexlen= (int32_t)strlen(hexstr) >> 1) < sizeof(rawtx->spendscript) ) { @@ -638,9 +676,9 @@ int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct ba if ( rawtx == &swap->otherfee ) { char str[65]; - LP_swap_coinaddr(rawtx->coin,rawtx->p2shaddr,0,data,datalen,0); + LP_swap_coinaddr(coin,rawtx->p2shaddr,0,data,datalen,0); printf("got %s txid.%s (%s) -> %s\n",rawtx->name,bits256_str(str,rawtx->I.signedtxid),jprint(txobj,0),rawtx->p2shaddr); - } else bitcoin_address(rawtx->p2shaddr,rawtx->coin->taddr,rawtx->coin->p2shtype,rawtx->spendscript,hexlen); + } else bitcoin_address(rawtx->p2shaddr,coin->taddr,coin->p2shtype,rawtx->spendscript,hexlen); } } else printf("%s satoshis %.8f ERROR.(%s) txfees.[%.8f %.8f: %.8f] amount.%.8f -> %.8f\n",rawtx->name,dstr(j64bits(vout,"satoshis")),jprint(txobj,0),dstr(swap->I.Atxfee),dstr(swap->I.Btxfee),dstr(txfee),dstr(rawtx->I.amount),dstr(rawtx->I.amount)-dstr(txfee)); } @@ -656,7 +694,7 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3 { if ( bits256_nonz(rawtx->I.signedtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 ) { - rawtx->I.actualtxid = LP_broadcast_tx(rawtx->name,rawtx->coin->symbol,rawtx->txbytes,rawtx->I.datalen); + rawtx->I.actualtxid = LP_broadcast_tx(rawtx->name,rawtx->symbol,rawtx->txbytes,rawtx->I.datalen); if ( bits256_cmp(rawtx->I.actualtxid,rawtx->I.signedtxid) != 0 ) { char str[65],str2[65]; @@ -684,7 +722,7 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3 if ( suppress_swapsend == 0 ) { retval = LP_swapsend(pairsock,swap,msgbits,sendbuf,sendlen,nextbits,rawtx->I.crcs); - if ( LP_waitmempool(rawtx->coin->symbol,rawtx->I.destaddr,rawtx->I.signedtxid,0,LP_SWAPSTEP_TIMEOUT*10) < 0 ) + if ( LP_waitmempool(rawtx->symbol,rawtx->I.destaddr,rawtx->I.signedtxid,0,LP_SWAPSTEP_TIMEOUT*10) < 0 ) { char str[65]; printf("failed to find %s %s %s in the mempool?\n",rawtx->name,rawtx->I.destaddr,bits256_str(str,rawtx->I.actualtxid)); retval = -1; @@ -704,22 +742,25 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3 return(0); } -int32_t LP_swapwait(uint32_t requestid,uint32_t quoteid,int32_t duration,int32_t sleeptime) +int32_t LP_swapwait(struct basilisk_swap *swap,uint32_t requestid,uint32_t quoteid,int32_t duration,int32_t sleeptime) { char *retstr; cJSON *retjson=0; uint32_t expiration = (uint32_t)(time(NULL) + duration); printf("wait %d:%d for SWAP.(r%u/q%u) to complete\n",duration,sleeptime,requestid,quoteid); - sleep(10); + sleep(sleeptime/3); //if ( sleeptime < divisor*60 ) // sleeptime = divisor * 60; while ( time(NULL) < expiration ) { - if ( (retstr= basilisk_swapentry(requestid,quoteid)) != 0 ) + if ( (retstr= basilisk_swapentry(requestid,quoteid,1)) != 0 ) { if ( (retjson= cJSON_Parse(retstr)) != 0 ) { if ( jstr(retjson,"status") != 0 && strcmp(jstr(retjson,"status"),"finished") == 0 ) + { + swap->I.finished = (uint32_t)time(NULL); break; - else printf("NOT FINISHED.(%s)\n",jprint(retjson,0)); + } + //else printf("NOT FINISHED.(%s)\n",jprint(retjson,0)); free_json(retjson); retjson = 0; } @@ -734,7 +775,7 @@ int32_t LP_swapwait(uint32_t requestid,uint32_t quoteid,int32_t duration,int32_t { printf("\n>>>>>>>>>>>>>>>>>>>>>>>>>\nSWAP completed! %u-%u %s\n",requestid,quoteid,jprint(retjson,0)); free_json(retjson); - if ( (retstr= basilisk_swapentry(requestid,quoteid)) != 0 ) + if ( 0 && (retstr= basilisk_swapentry(requestid,quoteid,1)) != 0 ) { printf("second call.(%s)\n",retstr); free(retstr); @@ -753,7 +794,7 @@ void LP_bobloop(void *_swap) expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT; if ( swap != 0 ) { - if ( LP_waitsend("pubkeys",60,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) + if ( LP_waitsend("pubkeys",120,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) printf("error waitsend pubkeys\n"); else if ( LP_waitsend("choosei",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 ) printf("error waitsend choosei\n"); @@ -768,6 +809,7 @@ void LP_bobloop(void *_swap) basilisk_bobdeposit_refund(swap,swap->I.putduration); //printf("depositlen.%d\n",swap->bobdeposit.I.datalen); LP_swapsfp_update(&swap->I.req); + LP_swap_critical = (uint32_t)time(NULL); if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT*10,LP_verify_otherfee) < 0 ) printf("error waiting for alicefee\n"); else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x200,data,maxlen,&swap->bobdeposit,0x100,0) == 0 ) @@ -776,36 +818,41 @@ void LP_bobloop(void *_swap) printf("error waiting for alicepayment\n"); else { + LP_swap_critical = (uint32_t)time(NULL); if ( basilisk_bobscripts_set(swap,0,1) < 0 ) printf("error bobscripts payment\n"); else { - if ( strcmp(swap->alicecoin.symbol,"BTC") == 0 ) + if ( strcmp(swap->I.alicestr,"BTC") == 0 ) m = 0; else m = swap->I.aliceconfirms; - while ( (n= LP_numconfirms(swap->alicecoin.symbol,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,1)) < m ) // sync with alice + while ( (n= LP_numconfirms(swap->I.alicestr,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,1)) < m ) // sync with alice { - char str[65];printf("%d waiting for alicepayment %s to be confirmed.%d %s %s\n",n,swap->alicepayment.I.destaddr,m,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid)); + LP_swap_critical = (uint32_t)time(NULL); + char str[65];printf("%d wait for alicepayment %s numconfs.%d %s %s\n",n,swap->alicepayment.I.destaddr,m,swap->I.alicestr,bits256_str(str,swap->alicepayment.I.signedtxid)); sleep(10); } + LP_swap_critical = (uint32_t)time(NULL); if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x8000,data,maxlen,&swap->bobpayment,0x4000,0) == 0 ) printf("error sending bobpayment\n"); //if ( LP_waitfor(swap->N.pair,swap,10,LP_verify_alicespend) < 0 ) // printf("error waiting for alicespend\n"); - swap->sentflag = 1; + //swap->sentflag = 1; swap->bobreclaim.utxovout = 0; swap->bobreclaim.utxotxid = swap->bobpayment.I.signedtxid; basilisk_bobpayment_reclaim(swap,swap->I.callduration); if ( swap->N.pair >= 0 ) nn_close(swap->N.pair), swap->N.pair = -1; - LP_swapwait(swap->I.req.requestid,swap->I.req.quoteid,4*3600,30); + LP_swap_endcritical = (uint32_t)time(NULL); + LP_swapwait(swap,swap->I.req.requestid,swap->I.req.quoteid,LP_atomic_locktime(swap->I.bobstr,swap->I.alicestr)*2,swap->I.aliceconfirms == 0 ? 3 : 30); } } } - basilisk_swap_finished(swap); - //free(swap); } else printf("swap timed out\n"); G.LP_pendingswaps--; + basilisk_swap_finished(swap); + free(swap); + free(data); } void LP_aliceloop(void *_swap) @@ -818,7 +865,7 @@ void LP_aliceloop(void *_swap) if ( swap != 0 ) { printf("start swap iamalice pair.%d\n",swap->N.pair); - if ( LP_sendwait("pubkeys",60,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) + if ( LP_sendwait("pubkeys",120,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) printf("error LP_sendwait pubkeys\n"); else if ( LP_sendwait("choosei",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 ) printf("error LP_sendwait choosei\n"); @@ -829,55 +876,66 @@ void LP_aliceloop(void *_swap) else { LP_swapsfp_update(&swap->I.req); + LP_swap_critical = (uint32_t)time(NULL); if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x80,data,maxlen,&swap->myfee,0x40,0) == 0 ) printf("error sending alicefee\n"); else if ( LP_waitfor(swap->N.pair,swap,1800,LP_verify_bobdeposit) < 0 ) printf("error waiting for bobdeposit\n"); - else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0) == 0 ) - printf("error sending alicepayment\n"); else { - if ( strcmp(swap->alicecoin.symbol,"BTC") == 0 ) + if ( strcmp(swap->I.bobstr,"BTC") == 0 ) m = 0; - else m = swap->I.aliceconfirms; - while ( (n= LP_numconfirms(swap->alicecoin.symbol,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,1)) < m ) + else m = swap->I.bobconfirms; + while ( (n= LP_numconfirms(swap->I.bobstr,swap->bobdeposit.I.destaddr,swap->bobdeposit.I.signedtxid,0,1)) < m ) { - char str[65];printf("%d waiting for alicepayment %s to be confirmed.%d %s %s\n",n,swap->alicepayment.I.destaddr,m,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid)); + LP_swap_critical = (uint32_t)time(NULL); + char str[65];printf("%d wait for bobdeposit %s numconfs.%d %s %s\n",n,swap->bobdeposit.I.destaddr,m,swap->I.bobstr,bits256_str(str,swap->bobdeposit.I.signedtxid)); sleep(10); } - swap->sentflag = 1; - if ( LP_waitfor(swap->N.pair,swap,1800,LP_verify_bobpayment) < 0 ) - printf("error waiting for bobpayment\n"); + if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0) == 0 ) + printf("error sending alicepayment\n"); else { - while ( (n= LP_numconfirms(swap->bobcoin.symbol,swap->bobpayment.I.destaddr,swap->bobpayment.I.signedtxid,0,1)) < swap->I.bobconfirms ) + if ( strcmp(swap->I.alicestr,"BTC") == 0 ) + m = 0; + else m = swap->I.aliceconfirms; + while ( (n= LP_numconfirms(swap->I.alicestr,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,1)) < m ) { - char str[65];printf("%d waiting for bobpayment %s to be confirmed.%d %s %s\n",n,swap->bobpayment.I.destaddr,swap->I.bobconfirms,swap->bobcoin.symbol,bits256_str(str,swap->bobpayment.I.signedtxid)); + LP_swap_critical = (uint32_t)time(NULL); + char str[65];printf("%d wait for alicepayment %s numconfs.%d %s %s\n",n,swap->alicepayment.I.destaddr,m,swap->I.alicestr,bits256_str(str,swap->alicepayment.I.signedtxid)); sleep(10); } - /*if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x20000,data,maxlen,&swap->alicespend,0x40000,0) == 0 ) - printf("error sending alicespend\n"); - while ( (n= LP_numconfirms(swap->alicecoin.symbol,swap->alicespend.I.destaddr,swap->alicespend.I.signedtxid,0,1)) < swap->I.aliceconfirms ) + //swap->sentflag = 1; + LP_swap_critical = (uint32_t)time(NULL); + if ( LP_waitfor(swap->N.pair,swap,1800,LP_verify_bobpayment) < 0 ) + printf("error waiting for bobpayment\n"); + else { - char str[65];printf("%d waiting for alicespend %s to be confirmed.%d %s %s\n",n,swap->alicespend.I.destaddr,swap->I.aliceconfirms,swap->bobcoin.symbol,bits256_str(str,swap->alicespend.I.signedtxid)); - sleep(LP_SWAPSTEP_TIMEOUT); - }*/ - if ( swap->N.pair >= 0 ) - nn_close(swap->N.pair), swap->N.pair = -1; - LP_swapwait(swap->I.req.requestid,swap->I.req.quoteid,4*3600,30); + LP_swap_endcritical = (uint32_t)time(NULL); + while ( (n= LP_numconfirms(swap->I.bobstr,swap->bobpayment.I.destaddr,swap->bobpayment.I.signedtxid,0,1)) < swap->I.bobconfirms ) + { + char str[65];printf("%d wait for bobpayment %s numconfs.%d %s %s\n",n,swap->bobpayment.I.destaddr,swap->I.bobconfirms,swap->I.bobstr,bits256_str(str,swap->bobpayment.I.signedtxid)); + sleep(10); + } + /*if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x20000,data,maxlen,&swap->alicespend,0x40000,0) == 0 ) + printf("error sending alicespend\n"); + while ( (n= LP_numconfirms(swap->I.alicestr,swap->alicespend.I.destaddr,swap->alicespend.I.signedtxid,0,1)) < swap->I.aliceconfirms ) + { + char str[65];printf("%d wait for alicespend %s numconfs.%d %s %s\n",n,swap->alicespend.I.destaddr,swap->I.aliceconfirms,swap->I.bobstr,bits256_str(str,swap->alicespend.I.signedtxid)); + sleep(LP_SWAPSTEP_TIMEOUT); + }*/ + if ( swap->N.pair >= 0 ) + nn_close(swap->N.pair), swap->N.pair = -1; + LP_swap_endcritical = (uint32_t)time(NULL); + LP_swapwait(swap,swap->I.req.requestid,swap->I.req.quoteid,LP_atomic_locktime(swap->I.bobstr,swap->I.alicestr)*2,swap->I.aliceconfirms == 0 ? 3 : 30); + } } } } } free(data); - if ( swap->N.pair >= 0 ) - { - nn_close(swap->N.pair); - swap->N.pair = -1; - } basilisk_swap_finished(swap); - printf("finish swap.%p\n",swap); - //free(swap); + free(swap); G.LP_pendingswaps--; } @@ -965,8 +1023,8 @@ void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx * numconfirms = 0; #endif strcpy(rawtx->name,name); - rawtx->coin = coin; - strcpy(rawtx->I.coinstr,coin->symbol); + printf("set coin.%s %s -> %s\n",coin->symbol,coin->smartaddr,name); + strcpy(rawtx->symbol,coin->symbol); rawtx->I.numconfirms = numconfirms; if ( (rawtx->I.amount= satoshis) < LP_MIN_TXFEE ) rawtx->I.amount = LP_MIN_TXFEE; @@ -977,13 +1035,13 @@ void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx * if ( strcmp(coin->symbol,"BTC") == 0 && (quoteid % 10) == 0 ) decode_hex(rawtx->I.rmd160,20,TIERNOLAN_RMD160); else decode_hex(rawtx->I.rmd160,20,INSTANTDEX_RMD160); - bitcoin_address(rawtx->I.destaddr,rawtx->coin->taddr,rawtx->coin->pubtype,rawtx->I.rmd160,20); + bitcoin_address(rawtx->I.destaddr,coin->taddr,coin->pubtype,rawtx->I.rmd160,20); } if ( pubkey33 != 0 ) { memcpy(rawtx->I.pubkey33,pubkey33,33); - bitcoin_address(rawtx->I.destaddr,rawtx->coin->taddr,rawtx->coin->pubtype,rawtx->I.pubkey33,33); - bitcoin_addr2rmd160(rawtx->coin->taddr,&rawtx->I.addrtype,rawtx->I.rmd160,rawtx->I.destaddr); + bitcoin_address(rawtx->I.destaddr,coin->taddr,coin->pubtype,rawtx->I.pubkey33,33); + bitcoin_addr2rmd160(coin->taddr,&rawtx->I.addrtype,rawtx->I.rmd160,rawtx->I.destaddr); } if ( rawtx->I.vouttype <= 1 && rawtx->I.destaddr[0] != 0 ) { @@ -992,26 +1050,54 @@ void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx * } else printf("%s vouttype.%d destaddr.(%s)\n",name,rawtx->I.vouttype,rawtx->I.destaddr); } -struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 pubkey25519,struct basilisk_swap *swap,int32_t optionduration,uint32_t statebits,struct LP_quoteinfo *qp) +struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 pubkey25519,struct basilisk_swap *swap,int32_t optionduration,uint32_t statebits,struct LP_quoteinfo *qp,int32_t dynamictrust) { //FILE *fp; char fname[512]; - uint8_t *alicepub33=0,*bobpub33=0; int32_t jumblrflag=-2,x = -1; struct iguana_info *coin; - swap->I.Atxfee = qp->desttxfee; - swap->I.Btxfee = qp->txfee; - swap->I.putduration = swap->I.callduration = INSTANTDEX_LOCKTIME; + uint8_t *alicepub33=0,*bobpub33=0; int32_t jumblrflag=-2,x = -1; struct iguana_info *bobcoin,*alicecoin; + strcpy(swap->I.bobstr,swap->I.req.src); + strcpy(swap->I.alicestr,swap->I.req.dest); + if ( (alicecoin= LP_coinfind(swap->I.alicestr)) == 0 ) + { + printf("missing alicecoin src.%p dest.%p\n",LP_coinfind(swap->I.req.src),LP_coinfind(swap->I.req.dest)); + free(swap); + return(0); + } + if ( (bobcoin= LP_coinfind(swap->I.bobstr)) == 0 ) + { + printf("missing bobcoin src.%p dest.%p\n",LP_coinfind(swap->I.req.src),LP_coinfind(swap->I.req.dest)); + free(swap); + return(0); + } + if ( (swap->I.Atxfee= qp->desttxfee) < 0 ) + { + printf("bitcoin_swapinit %s Atxfee %.8f rejected\n",swap->I.req.dest,dstr(swap->I.Atxfee)); + return(0); + } + if ( (swap->I.Btxfee= qp->txfee) < 0 ) + { + printf("bitcoin_swapinit %s Btxfee %.8f rejected\n",swap->I.req.src,dstr(swap->I.Btxfee)); + return(0); + } + swap->I.putduration = swap->I.callduration = LP_atomic_locktime(swap->I.bobstr,swap->I.alicestr); if ( optionduration < 0 ) swap->I.putduration -= optionduration; else if ( optionduration > 0 ) swap->I.callduration += optionduration; - swap->I.bobsatoshis = swap->I.req.srcamount; - swap->I.alicesatoshis = swap->I.req.destamount; + if ( (swap->I.bobsatoshis= swap->I.req.srcamount) <= 0 ) + { + printf("bitcoin_swapinit %s bobsatoshis %.8f rejected\n",swap->I.req.src,dstr(swap->I.bobsatoshis)); + return(0); + } + if ( (swap->I.alicesatoshis= swap->I.req.destamount) <= 0 ) + { + printf("bitcoin_swapinit %s alicesatoshis %.8f rejected\n",swap->I.req.dest,dstr(swap->I.alicesatoshis)); + return(0); + } if ( (swap->I.bobinsurance= (swap->I.bobsatoshis / INSTANTDEX_INSURANCEDIV)) < LP_MIN_TXFEE ) swap->I.bobinsurance = LP_MIN_TXFEE; if ( (swap->I.aliceinsurance= (swap->I.alicesatoshis / INSTANTDEX_INSURANCEDIV)) < LP_MIN_TXFEE ) swap->I.aliceinsurance = LP_MIN_TXFEE; - strcpy(swap->I.bobstr,swap->I.req.src); - strcpy(swap->I.alicestr,swap->I.req.dest); - swap->I.started = (uint32_t)time(NULL); + swap->I.started = qp->timestamp;//(uint32_t)time(NULL); swap->I.expiration = swap->I.req.timestamp + swap->I.putduration + swap->I.callduration; OS_randombytes((uint8_t *)&swap->I.choosei,sizeof(swap->I.choosei)); if ( swap->I.choosei < 0 ) @@ -1024,42 +1110,30 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 swap->I.iambob = 0; swap->I.otherhash = swap->I.req.desthash; swap->I.aliceistrusted = 1; - swap->I.otheristrusted = swap->I.bobistrusted = LP_pubkey_istrusted(swap->I.req.srchash); + if ( dynamictrust == 0 && LP_pubkey_istrusted(swap->I.req.srchash) != 0 ) + dynamictrust = 1; + swap->I.otheristrusted = swap->I.bobistrusted = dynamictrust; } else { swap->I.iambob = 1; swap->I.otherhash = swap->I.req.srchash; swap->I.bobistrusted = 1; - swap->I.otheristrusted = swap->I.aliceistrusted = LP_pubkey_istrusted(swap->I.req.desthash); + if ( dynamictrust == 0 && LP_pubkey_istrusted(swap->I.req.desthash) != 0 ) + dynamictrust = 1; + swap->I.otheristrusted = swap->I.aliceistrusted = dynamictrust; } if ( bits256_nonz(privkey) == 0 || (x= instantdex_pubkeyargs(swap,2 + INSTANTDEX_DECKSIZE,privkey,swap->I.orderhash,0x02+swap->I.iambob)) != 2 + INSTANTDEX_DECKSIZE ) { char str[65]; printf("couldnt generate privkeys %d %s\n",x,bits256_str(str,privkey)); return(0); } - if ( (coin= LP_coinfind(swap->I.alicestr)) != 0 ) - swap->alicecoin = *coin; - else - { - printf("missing bobcoin.%p or missing alicecoin.%p src.%p dest.%p\n",&swap->bobcoin,&swap->alicecoin,LP_coinfind(swap->I.req.src),LP_coinfind(swap->I.req.dest)); - free(swap); - return(0); - } - if ( (coin= LP_coinfind(swap->I.bobstr)) != 0 ) - swap->bobcoin = *coin; - else - { - printf("missing bobcoin.%p or missing alicecoin.%p src.%p dest.%p\n",&swap->bobcoin,&swap->alicecoin,LP_coinfind(swap->I.req.src),LP_coinfind(swap->I.req.dest)); - free(swap); - return(0); - } - if ( strcmp("BTC",swap->bobcoin.symbol) == 0 ) + if ( strcmp("BTC",swap->I.bobstr) == 0 ) { swap->I.bobconfirms = (1 + sqrt(dstr(swap->I.bobsatoshis) * .1)); swap->I.aliceconfirms = BASILISK_DEFAULT_NUMCONFIRMS; } - else if ( strcmp("BTC",swap->alicecoin.symbol) == 0 ) + else if ( strcmp("BTC",swap->I.alicestr) == 0 ) { swap->I.aliceconfirms = (1 + sqrt(dstr(swap->I.alicesatoshis) * .1)); swap->I.bobconfirms = BASILISK_DEFAULT_NUMCONFIRMS; @@ -1069,17 +1143,17 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 swap->I.bobconfirms = BASILISK_DEFAULT_NUMCONFIRMS; swap->I.aliceconfirms = BASILISK_DEFAULT_NUMCONFIRMS; } - if ( swap->bobcoin.isassetchain != 0 ) + if ( bobcoin->isassetchain != 0 ) swap->I.bobconfirms = 1; - if ( swap->alicecoin.isassetchain != 0 ) + if ( alicecoin->isassetchain != 0 ) swap->I.aliceconfirms = 1; - if ( swap->bobcoin.userconfirms > 0 ) - swap->I.bobconfirms = swap->bobcoin.userconfirms; - if ( swap->alicecoin.userconfirms > 0 ) - swap->I.aliceconfirms = swap->alicecoin.userconfirms; - if ( (swap->I.bobmaxconfirms= swap->bobcoin.maxconfirms) == 0 ) + if ( bobcoin->userconfirms > 0 ) + swap->I.bobconfirms = bobcoin->userconfirms; + if ( alicecoin->userconfirms > 0 ) + swap->I.aliceconfirms = alicecoin->userconfirms; + if ( (swap->I.bobmaxconfirms= bobcoin->maxconfirms) == 0 ) swap->I.bobmaxconfirms = BASILISK_DEFAULT_MAXCONFIRMS; - if ( (swap->I.alicemaxconfirms= swap->alicecoin.maxconfirms) == 0 ) + if ( (swap->I.alicemaxconfirms= alicecoin->maxconfirms) == 0 ) swap->I.alicemaxconfirms = BASILISK_DEFAULT_MAXCONFIRMS; if ( swap->I.bobconfirms > swap->I.bobmaxconfirms ) swap->I.bobconfirms = swap->I.bobmaxconfirms; @@ -1087,57 +1161,57 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 swap->I.aliceconfirms = swap->I.alicemaxconfirms; swap->I.bobconfirms *= !swap->I.bobistrusted; swap->I.aliceconfirms *= !swap->I.aliceistrusted; - printf(">>>>>>>>>> jumblrflag.%d <<<<<<<<< use smart address, %.8f bobconfs.%d, %.8f aliceconfs.%d taddr.%d %d\n",jumblrflag,dstr(swap->I.bobsatoshis),swap->I.bobconfirms,dstr(swap->I.alicesatoshis),swap->I.aliceconfirms,swap->bobcoin.taddr,swap->alicecoin.taddr); + printf(">>>>>>>>>> jumblrflag.%d <<<<<<<<< r.%u q.%u, %.8f bobconfs.%d, %.8f aliceconfs.%d taddr.%d %d\n",jumblrflag,swap->I.req.requestid,swap->I.req.quoteid,dstr(swap->I.bobsatoshis),swap->I.bobconfirms,dstr(swap->I.alicesatoshis),swap->I.aliceconfirms,bobcoin->taddr,alicecoin->taddr); if ( swap->I.iambob != 0 ) { - basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,&swap->bobcoin,0,0,LP_DEXFEE(swap->I.bobsatoshis) + swap->bobcoin.txfee,0,0,jumblrflag); - basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,&swap->alicecoin,0,0,LP_DEXFEE(swap->I.alicesatoshis) + swap->alicecoin.txfee,0,0,jumblrflag); + basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,bobcoin,0,0,LP_DEXFEE(swap->I.bobsatoshis) + 0*bobcoin->txfee,0,0,jumblrflag); + basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,alicecoin,0,0,LP_DEXFEE(swap->I.alicesatoshis) + 0*alicecoin->txfee,0,0,jumblrflag); bobpub33 = pubkey33; } else { - basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,&swap->bobcoin,0,0,LP_DEXFEE(swap->I.bobsatoshis) + swap->bobcoin.txfee,0,0,jumblrflag); - basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,&swap->alicecoin,0,0,LP_DEXFEE(swap->I.alicesatoshis) + swap->alicecoin.txfee,0,0,jumblrflag); + basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,bobcoin,0,0,LP_DEXFEE(swap->I.bobsatoshis) + 0*bobcoin->txfee,0,0,jumblrflag); + basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,alicecoin,0,0,LP_DEXFEE(swap->I.alicesatoshis) + 0*alicecoin->txfee,0,0,jumblrflag); alicepub33 = pubkey33; } swap->myfee.I.locktime = swap->I.started + 1; swap->otherfee.I.locktime = swap->I.started + 1; - basilisk_rawtx_setparms("bobdeposit",swap->I.req.quoteid,&swap->bobdeposit,&swap->bobcoin,swap->I.bobconfirms,0,LP_DEPOSITSATOSHIS(swap->I.bobsatoshis) + swap->bobcoin.txfee,4,0,jumblrflag); - basilisk_rawtx_setparms("bobrefund",swap->I.req.quoteid,&swap->bobrefund,&swap->bobcoin,1,4,LP_DEPOSITSATOSHIS(swap->I.bobsatoshis),1,bobpub33,jumblrflag); + basilisk_rawtx_setparms("bobdeposit",swap->I.req.quoteid,&swap->bobdeposit,bobcoin,swap->I.bobconfirms,0,LP_DEPOSITSATOSHIS(swap->I.bobsatoshis) + 2*bobcoin->txfee,4,0,jumblrflag); + basilisk_rawtx_setparms("bobrefund",swap->I.req.quoteid,&swap->bobrefund,bobcoin,1,4,LP_DEPOSITSATOSHIS(swap->I.bobsatoshis),1,bobpub33,jumblrflag); swap->bobrefund.I.suppress_pubkeys = 1; - basilisk_rawtx_setparms("aliceclaim",swap->I.req.quoteid,&swap->aliceclaim,&swap->bobcoin,1,4,LP_DEPOSITSATOSHIS(swap->I.bobsatoshis),1,alicepub33,jumblrflag); + basilisk_rawtx_setparms("aliceclaim",swap->I.req.quoteid,&swap->aliceclaim,bobcoin,1,4,LP_DEPOSITSATOSHIS(swap->I.bobsatoshis),1,alicepub33,jumblrflag); swap->aliceclaim.I.suppress_pubkeys = 1; swap->aliceclaim.I.locktime = swap->I.started + swap->I.putduration+swap->I.callduration + 1; - basilisk_rawtx_setparms("bobpayment",swap->I.req.quoteid,&swap->bobpayment,&swap->bobcoin,swap->I.bobconfirms,0,swap->I.bobsatoshis + swap->bobcoin.txfee,3,0,jumblrflag); - basilisk_rawtx_setparms("alicespend",swap->I.req.quoteid,&swap->alicespend,&swap->bobcoin,swap->I.bobconfirms,3,swap->I.bobsatoshis,1,alicepub33,jumblrflag); + basilisk_rawtx_setparms("bobpayment",swap->I.req.quoteid,&swap->bobpayment,bobcoin,swap->I.bobconfirms,0,swap->I.bobsatoshis + 2*bobcoin->txfee,3,0,jumblrflag); + basilisk_rawtx_setparms("alicespend",swap->I.req.quoteid,&swap->alicespend,bobcoin,swap->I.bobconfirms,3,swap->I.bobsatoshis,1,alicepub33,jumblrflag); swap->alicespend.I.suppress_pubkeys = 1; - basilisk_rawtx_setparms("bobreclaim",swap->I.req.quoteid,&swap->bobreclaim,&swap->bobcoin,swap->I.bobconfirms,3,swap->I.bobsatoshis,1,bobpub33,jumblrflag); + basilisk_rawtx_setparms("bobreclaim",swap->I.req.quoteid,&swap->bobreclaim,bobcoin,swap->I.bobconfirms,3,swap->I.bobsatoshis,1,bobpub33,jumblrflag); swap->bobreclaim.I.suppress_pubkeys = 1; swap->bobreclaim.I.locktime = swap->I.started + swap->I.putduration + 1; - basilisk_rawtx_setparms("alicepayment",swap->I.req.quoteid,&swap->alicepayment,&swap->alicecoin,swap->I.aliceconfirms,0,swap->I.alicesatoshis+swap->alicecoin.txfee,2,0,jumblrflag); - basilisk_rawtx_setparms("bobspend",swap->I.req.quoteid,&swap->bobspend,&swap->alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,bobpub33,jumblrflag); + basilisk_rawtx_setparms("alicepayment",swap->I.req.quoteid,&swap->alicepayment,alicecoin,swap->I.aliceconfirms,0,swap->I.alicesatoshis + 2*alicecoin->txfee,2,0,jumblrflag); + basilisk_rawtx_setparms("bobspend",swap->I.req.quoteid,&swap->bobspend,alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,bobpub33,jumblrflag); swap->bobspend.I.suppress_pubkeys = 1; - basilisk_rawtx_setparms("alicereclaim",swap->I.req.quoteid,&swap->alicereclaim,&swap->alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,alicepub33,jumblrflag); + basilisk_rawtx_setparms("alicereclaim",swap->I.req.quoteid,&swap->alicereclaim,alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,alicepub33,jumblrflag); swap->alicereclaim.I.suppress_pubkeys = 1; swap->bobpayment.utxotxid = qp->txid, swap->bobpayment.utxovout = qp->vout; swap->bobdeposit.utxotxid = qp->txid2, swap->bobdeposit.utxovout = qp->vout2; swap->alicepayment.utxotxid = qp->desttxid, swap->alicepayment.utxovout = qp->destvout; - LP_mark_spent(swap->bobcoin.symbol,qp->txid,qp->vout); - LP_mark_spent(swap->bobcoin.symbol,qp->txid2,qp->vout2); - LP_mark_spent(swap->alicecoin.symbol,qp->desttxid,qp->destvout); + LP_mark_spent(swap->I.bobstr,qp->txid,qp->vout); + LP_mark_spent(swap->I.bobstr,qp->txid2,qp->vout2); + LP_mark_spent(swap->I.alicestr,qp->desttxid,qp->destvout); if ( swap->I.iambob != 0 ) swap->otherfee.utxotxid = qp->feetxid, swap->otherfee.utxovout = qp->feevout; else { swap->myfee.utxotxid = qp->feetxid, swap->myfee.utxovout = qp->feevout; - LP_mark_spent(swap->alicecoin.symbol,qp->feetxid,qp->feevout); + LP_mark_spent(swap->I.alicestr,qp->feetxid,qp->feevout); } - char str[65],str2[65],str3[65]; printf("IAMBOB.%d %s %s %s\n",swap->I.iambob,bits256_str(str,qp->txid),bits256_str(str2,qp->txid2),bits256_str(str3,qp->feetxid)); + char str[65],str2[65],str3[65]; printf("IAMBOB.%d %s %s %s [%s %s]\n",swap->I.iambob,bits256_str(str,qp->txid),bits256_str(str2,qp->txid2),bits256_str(str3,qp->feetxid),swap->I.bobstr,swap->I.alicestr); return(swap); } -struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp) +struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp,int32_t dynamictrust) { struct basilisk_swap *swap; bits256 pubkey25519; uint8_t pubkey33[33]; swap = calloc(1,sizeof(*swap)); @@ -1149,14 +1223,14 @@ struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 G.LP_skipstatus[G.LP_numskips] = ((uint64_t)rp->requestid << 32) | rp->quoteid; if ( G.LP_numskips < sizeof(G.LP_skipstatus)/sizeof(*G.LP_skipstatus) ) G.LP_numskips++; - printf("basilisk_thread_start request.%u iambob.%d (%s/%s) quoteid.%u\n",rp->requestid,iambob,rp->src,rp->dest,rp->quoteid); + printf("LP_swapinit request.%u iambob.%d (%s/%s) quoteid.%u\n",rp->requestid,iambob,rp->src,rp->dest,rp->quoteid); bitcoin_pubkey33(swap->ctx,pubkey33,privkey); pubkey25519 = curve25519(privkey,curve25519_basepoint9()); swap->persistent_pubkey = pubkey25519; swap->persistent_privkey = privkey; memcpy(swap->persistent_pubkey33,pubkey33,33); calc_rmd160_sha256(swap->changermd160,pubkey33,33); - if ( bitcoin_swapinit(privkey,pubkey33,pubkey25519,swap,optionduration,!iambob,qp) == 0 ) + if ( bitcoin_swapinit(privkey,pubkey33,pubkey25519,swap,optionduration,!iambob,qp,dynamictrust) == 0 ) { printf("error doing swapinit\n"); free(swap); diff --git a/iguana/exchanges/LP_tradebots.c b/iguana/exchanges/LP_tradebots.c new file mode 100644 index 000000000..39526c2be --- /dev/null +++ b/iguana/exchanges/LP_tradebots.c @@ -0,0 +1,694 @@ + +/****************************************************************************** + * Copyright © 2014-2017 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ +// +// LP_tradebots.c +// marketmaker +// + +#define TRADEBOTS_GAPTIME 120 +#define LP_TRADEBOTS_MAXTRADES 10 + +struct LP_tradebot_trade +{ + double maxprice,totalrelvolume,basevol,relvol; + uint64_t aliceid; + int32_t dispdir; + uint32_t started,finished,requestid,quoteid,tradeid,expired; + char base[65],rel[65],event[32]; +}; + +struct LP_tradebot +{ + struct LP_tradebot *next,*prev; + char name[128],base[65],rel[65]; + int32_t numtrades,numpending,completed,dispdir; + double maxprice,totalrelvolume,totalbasevolume,basesum,relsum,pendbasesum,pendrelsum; + uint32_t lasttime,dead,pause,userpause,started,id; + struct LP_tradebot_trade *trades[LP_TRADEBOTS_MAXTRADES]; +} *LP_tradebots; + +void LP_tradebot_pauseall() +{ + struct LP_tradebot *bot,*tmp; + DL_FOREACH_SAFE(LP_tradebots,bot,tmp) + { + bot->userpause = bot->pause = (uint32_t)time(NULL); + } +} + +void LP_tradebot_updatestats(struct LP_tradebot *bot,struct LP_tradebot_trade *tp) +{ + char *swapstr,*status; int32_t flag; cJSON *swapjson; + if ( (swapstr= basilisk_swapentry(tp->requestid,tp->quoteid,1)) != 0 ) + { + flag = 0; + if ( (swapjson= cJSON_Parse(swapstr)) != 0 ) + { + tp->basevol = dstr(j64bits(swapjson,"satoshis")); + tp->relvol = dstr(j64bits(swapjson,"destsatoshis")); + tp->aliceid = j64bits(swapjson,"aliceid"); + if ( (status= jstr(swapjson,"status")) != 0 ) + { + if ( strcmp(status,"finished") == 0 ) + { + if ( tp->finished == 0 ) + tp->finished = (uint32_t)time(NULL); + } + } + free_json(swapjson); + } + free(swapstr); + } +} + +void LP_tradebot_calcstats(struct LP_tradebot *bot) +{ + int32_t i; struct LP_tradebot_trade *tp; + bot->basesum = bot->relsum = bot->pendbasesum = bot->pendrelsum = 0.; + bot->numpending = bot->completed = 0; + for (i=0; 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 ) + { + jadd(json,"complete",bot->completed!=0?jtrue():jfalse()); + jaddnum(json,"percentage",100. * (bot->relsum / bot->totalrelvolume)); + if ( bot->dispdir > 0 ) + { + jaddnum(json,"aveprice",bot->relsum / bot->basesum); + jaddnum(json,"volume",bot->relsum); + } + else + { + jaddnum(json,"aveprice",bot->basesum / bot->relsum); + jaddnum(json,"volume",bot->basesum); + } + } + if ( bot->pendbasesum > SMALLVAL && bot->pendrelsum > SMALLVAL && bot->numpending > 0 ) + { + jaddnum(json,"pending",bot->numpending); + if ( bot->dispdir > 0 ) + { + jaddnum(json,"pendingprice",bot->pendrelsum / bot->pendbasesum); + jaddnum(json,"pendingvolume",bot->pendrelsum); + } + else + { + jaddnum(json,"pendingprice",bot->pendbasesum / bot->pendrelsum); + jaddnum(json,"pendingvolume",bot->pendbasesum); + } + } + return(json); +} + +struct LP_tradebot *_LP_tradebotfind(uint32_t botid) +{ + struct LP_tradebot *tmp,*bot,*retbot = 0; + DL_FOREACH_SAFE(LP_tradebots,bot,tmp) + { + if ( botid == bot->id ) + { + retbot = bot; + break; + } + } + return(retbot); +} + +struct LP_tradebot *LP_tradebotfind(uint32_t botid) +{ + struct LP_tradebot *retbot = 0; + portable_mutex_lock(&LP_tradebotsmutex); + retbot = _LP_tradebotfind(botid); + portable_mutex_unlock(&LP_tradebotsmutex); + return(retbot); +} + +void LP_tradebotadd(struct LP_tradebot *bot) +{ + portable_mutex_lock(&LP_tradebotsmutex); + while ( _LP_tradebotfind(bot->id) != 0 ) + { + printf("BOT collision at %u, ok if rare\n",bot->id); + bot->id++; + } + DL_APPEND(LP_tradebots,bot); + portable_mutex_unlock(&LP_tradebotsmutex); +} + +struct LP_tradebot_trade *LP_tradebot_pending(struct LP_tradebot *bot,cJSON *pending,uint32_t tradeid) +{ + struct LP_tradebot_trade *tp; + tp = calloc(1,sizeof(*tp)); + tp->tradeid = tradeid; + tp->maxprice = bot->maxprice; + tp->totalrelvolume = bot->totalrelvolume; + tp->started = (uint32_t)time(NULL); + tp->dispdir = bot->dispdir; + strcpy(tp->base,bot->base); + strcpy(tp->rel,bot->rel); + tp->aliceid = j64bits(pending,"aliceid"); + tp->basevol = jdouble(pending,"basevalue"); + tp->relvol = jdouble(pending,"relvalue"); + printf("tradebot pending basevol %.8f relvol %.8f\n",tp->basevol,tp->relvol); + return(tp); +} + +double LP_orderbook_maxrel(char *base,char *rel,double maxprice) +{ + char *retstr; int32_t i,numasks; cJSON *retjson,*asks,*item; double maxvol,maxrel = 0.; + if ( (retstr= LP_orderbook(base,rel,0)) != 0 ) + { + //printf("maxprice %.8f %s/%s\n",maxprice,base,rel); + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( (asks= jarray(&numasks,retjson,"asks")) != 0 ) + { + for (i=0; i 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; bits256 zero; struct LP_tradebot *bot,*tmp; + DL_FOREACH_SAFE(LP_tradebots,bot,tmp) + { + memset(zero.bytes,0,sizeof(zero)); + if ( (relcoin= LP_coinfind(bot->rel)) != 0 ) + LP_listunspent_issue(bot->rel,relcoin->smartaddr,1,zero,zero); + if ( bot->relsum >= 0.99*bot->totalrelvolume-SMALLVAL || bot->basesum >= 0.99*bot->totalbasevolume-SMALLVAL ) + bot->dead = (uint32_t)time(NULL); + else if ( (bot->pendrelsum+bot->relsum) >= 0.99*bot->totalrelvolume-SMALLVAL || (bot->basesum+bot->pendbasesum) >= 0.99*bot->totalbasevolume-SMALLVAL ) + bot->pause = (uint32_t)time(NULL); + else if ( bot->userpause == 0 ) + bot->pause = 0; + if ( bot->numpending == 0 && time(NULL) > bot->lasttime+TRADEBOTS_GAPTIME ) + { + LP_tradebot_timeslice(ctx,bot); + bot->lasttime = (uint32_t)time(NULL); + } + } + lastnumfinished = LP_numfinished; +} + +char *LP_tradebot_list(void *ctx,int32_t pubsock,cJSON *argjson) +{ + struct LP_tradebot *bot,*tmp; cJSON *array = cJSON_CreateArray(); + DL_FOREACH_SAFE(LP_tradebots,bot,tmp) + { + jaddinum(array,bot->id); + } + return(jprint(array,1)); +} + +char *LP_tradebot_statuslist(void *ctx,int32_t pubsock,cJSON *argjson) +{ + struct LP_tradebot *bot,*tmp; cJSON *array = cJSON_CreateArray(); + DL_FOREACH_SAFE(LP_tradebots,bot,tmp) + { + jaddi(array,LP_tradebot_json(bot)); + } + return(jprint(array,1)); +} + +char *LP_tradebot_buy(int32_t dispdir,char *base,char *rel,double maxprice,double relvolume) +{ + struct LP_tradebot *bot; char *retstr; double shortfall; cJSON *retjson; uint64_t sum,txfee,txfees,balance=0,abalance=0; struct iguana_info *basecoin,*relcoin; + basecoin = LP_coinfind(base); + relcoin = LP_coinfind(rel); + if ( basecoin == 0 || relcoin == 0 || basecoin->inactive != 0 || relcoin->inactive != 0 ) + return(clonestr("{\"error\":\"one or more coins inactive\"}")); + /*if ( (array= LP_inventory(rel)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 && is_cJSON_Array(array) != 0 ) + { + for (i=0; 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 ( 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 7d0f963a3..4f458beff 100644 --- a/iguana/exchanges/LP_transaction.c +++ b/iguana/exchanges/LP_transaction.c @@ -63,7 +63,7 @@ bits256 LP_pubkey(bits256 privkey) int32_t LP_gettx_presence(char *symbol,bits256 expectedtxid) { cJSON *txobj; bits256 txid; int32_t flag = 0; - if ( (txobj= LP_gettx(symbol,expectedtxid)) != 0 ) + if ( (txobj= LP_gettx(symbol,expectedtxid,0)) != 0 ) { txid = jbits256(txobj,"txid"); if ( jobj(txobj,"error") == 0 && bits256_cmp(txid,expectedtxid) == 0 ) @@ -78,7 +78,8 @@ int32_t LP_gettx_presence(char *symbol,bits256 expectedtxid) bits256 LP_broadcast(char *txname,char *symbol,char *txbytes,bits256 expectedtxid) { - char *retstr; bits256 txid; uint8_t *ptr; cJSON *retjson,*errorobj; int32_t i,len,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)); if ( txbytes == 0 || txbytes[0] == 0 ) return(txid); @@ -115,6 +116,15 @@ 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); @@ -247,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_in,numvouts); for (vini=0; vinitx_in; vini++) { if ( V->p2shscript[0] != 0 && V->p2shlen != 0 ) { script = V->p2shscript; scriptlen = V->p2shlen; - //for (j=0; jp2shlen.%d\n",V->p2shlen); } else { script = msgtx->vins[vini].spendscript; scriptlen = msgtx->vins[vini].spendlen; } - 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); + //for (j=0; jvins[vini].prev_hash,msgtx->vins[vini].prev_vout); + sigtxid = bitcoin_sigtxid(symbol,taddr,pubtype,p2shtype,isPoS,height,serialized,maxlen,msgtx,vini,script,scriptlen,V[vini].amount,sighash,vpnstr,suppress_pubkeys,zcash); + //printf("bitcoin_verifyvins scriptlen.%d siglen.%d\n",scriptlen,V[vini].signers[0].siglen); if ( bits256_nonz(sigtxid) != 0 ) { vp = &V[vini]; @@ -431,6 +449,7 @@ int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype, if ( sig == 0 || siglen == 0 ) { memset(vp->signers[j].pubkey,0,sizeof(vp->signers[j].pubkey)); + printf("no sig.%p or siglen.%d zero\n",sig,siglen); continue; } if ( bitcoin_verify(ctx,sig,siglen-1,sigtxid,vp->signers[j].pubkey,bitcoin_pubkeylen(vp->signers[j].pubkey)) < 0 ) @@ -449,7 +468,7 @@ int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype, printf(" <- sig[%d]\n",j); for (z=0; z<33; z++) printf("%02x",vp->signers[j].pubkey[z]); - bitcoin_address(tmpaddr,60,vp->signers[j].pubkey,33); + bitcoin_address(tmpaddr,0,0,vp->signers[j].pubkey,33); printf(" <- pub, SIG.%d.%d VERIFIED numsigs.%d vs M.%d %s\n",vini,j,numsigs,vp->M,tmpaddr);*/ } } @@ -458,8 +477,8 @@ 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,zcash); + cJSON *txobj = 0;//cJSON_CreateObject(); + *signedtx = iguana_rawtxbytes(symbol,taddr,pubtype,p2shtype,isPoS,height,txobj,msgtx,suppress_pubkeys,zcash); //printf("SIGNEDTX.(%s)\n",jprint(txobj,1)); *signedtxidp = msgtx->txid; return(complete); @@ -475,7 +494,7 @@ int64_t iguana_lockval(int32_t finalized,int64_t locktime) 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 = 100000; 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; uint32_t sighash; 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 ) @@ -487,7 +506,7 @@ 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); - if ( (txobj= bitcoin_hex2json(taddr,pubtype,p2shtype,isPoS,height,&txid,msgtx,rawtx,extraspace,extralen,serialized4,vins,V->suppress_pubkeys,zcash)) != 0 ) + if ( (txobj= bitcoin_hex2json(symbol,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 printf("no txobj from bitcoin_hex2json\n"); @@ -496,7 +515,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_ { //printf("numinputs.%d (%s) msgtx.%d\n",numinputs,jprint(vins,0),msgtx->tx_in); memset(msgtx,0,sizeof(*msgtx)); - if ( iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,0,0,serialized,maxsize,msgtx,&txid,"",extraspace,extralen,vins,V->suppress_pubkeys,zcash) > 0 && numinputs == msgtx->tx_in ) + if ( iguana_rwmsgtx(symbol,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)); @@ -519,12 +538,12 @@ 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; flag = (msgtx->vins[i].vinscript[0] == 0); - type = bitcoin_scriptget(taddr,pubtype,p2shtype,&hashtype,&sigsize,&pubkeysize,&userdata,&userdatalen,&mainvin,msgtx->vins[i].vinscript+flag,msgtx->vins[i].scriptlen-flag,0); + type = bitcoin_scriptget(symbol,taddr,pubtype,p2shtype,&hashtype,&sigsize,&pubkeysize,&userdata,&userdatalen,&mainvin,msgtx->vins[i].vinscript+flag,msgtx->vins[i].scriptlen-flag,0,zcash); //printf("i.%d flag.%d type.%d scriptlen.%d\n",i,flag,type,msgtx->vins[i].scriptlen); if ( msgtx->vins[i].redeemscript != 0 ) { @@ -583,7 +602,8 @@ 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,zcash)) > 0 && signedtx != 0 ) + sighash = LP_sighash(symbol,zcash); + if ( (complete= bitcoin_verifyvins(ctx,symbol,taddr,pubtype,p2shtype,isPoS,height,signedtxidp,&signedtx,msgtx,serialized3,maxsize,V,sighash,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 ) @@ -603,9 +623,142 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_ return(complete); } +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; cJSON *item,*vins,*vouts,*txobj,*retjson,*sobj; char *scriptsig,*signedtx; uint32_t sighash; int32_t sigsize,slen,height,finalized = 1,i,len,maxsize,numinputs,numoutputs,complete; struct vin_info *V; uint8_t *serialized,*serialized2,scriptbuf[256]; 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(symbol,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); + if ( (vouts= jarray(&numoutputs,txobj,"vout")) > 0 ) + { + for (i=0; i 0 ) + outputsum += vout.value; + } + } + if ( (vins= jarray(&numinputs,txobj,"vin")) > 0 ) + { + V = calloc(numinputs,sizeof(*V)); + len = 0; + for (i=0; ivins[i].spendscript = V[i].spendscript; + msgtx->vins[i].spendlen = V[i].spendlen; + if ( (sobj= jobj(item,"scriptSig")) != 0 ) + { + if ( (scriptsig= jstr(sobj,"hex")) != 0 ) + { + slen = (int32_t)strlen(scriptsig) >> 1; + if ( slen <= sizeof(scriptbuf) ) + { + msgtx->vins[i].scriptlen = slen; + msgtx->vins[i].vinscript = scriptbuf; + decode_hex(scriptbuf,slen,scriptsig); + if ( (sigsize= scriptbuf[0]) >= 70 && sigsize < 76 ) + { + memcpy(V[i].signers[0].sig,scriptbuf+1,sigsize-1); + V[i].signers[0].siglen = sigsize - 1; + V[i].hashtype = scriptbuf[1 + sigsize-1]; + if ( scriptbuf[sigsize+1] == 33 ) + { + memcpy(V[i].signers[0].pubkey,&scriptbuf[sigsize+2],33); + uint8_t rmd160[20]; char rmdstr[42]; + calc_rmd160(rmdstr,rmd160,V[i].signers[0].pubkey,33); + printf("RMD160.%s\n",rmdstr); + } + } else printf("sigsize.%d unexpected\n",sigsize); + } + } + } + inputsum += V[i].amount; + if ( msgtx->vins[i].sequence < IGUANA_SEQUENCEID_FINAL ) + finalized = 0; + //for (j=0; jvins[i].spendlen; j++) + // printf("%02x",msgtx->vins[i].spendscript[j]); + //printf(" spendscript, vin.%d (%s) scriptlen.%d spendlen.%d:%d finalize.%d\n",i,jprint(item,0),msgtx->vins[i].scriptlen,V[i].spendlen,msgtx->vins[i].spendlen,finalized); + } + sighash = LP_sighash(symbol,zcash); + complete = bitcoin_verifyvins(ctx,symbol,taddr,pubtype,p2shtype,isPoS,height,&signedtxid,&signedtx,msgtx,serialized2,maxsize,V,sighash,0,V[0].suppress_pubkeys,zcash); + msgtx->txid = signedtxid; + cJSON *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); + jadd(retjson,"complete",complete!=0?jtrue():jfalse()); + if ( signedtx != 0 ) + free(signedtx); + free(V); + } + free(serialized), free(serialized2); + } + //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 *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,LP_IS_BITCOINCASH); + 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[2]; uint32_t timestamp,locktime = 0,sequenceid = 0xffffffff * finalseqid; bits256 txid; uint64_t value=0,change = 0; struct iguana_msgtx msgtx; struct iguana_info *coin; + 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; @@ -617,10 +770,10 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch if ( redeemlen < 0 ) return(0); value = 0; -#ifndef BASILISK_DISABLESENDTX if ( (coin= LP_coinfind(symbol)) != 0 ) { - if ( (txobj= LP_gettx(symbol,utxotxid)) != 0 ) +#ifndef BASILISK_DISABLESENDTX + if ( (txobj= LP_gettx(symbol,utxotxid,0)) != 0 ) { if ( (vouts= jarray(&n,txobj,"vout")) != 0 && utxovout < n ) { @@ -629,24 +782,27 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch //printf("value in vout.%d %.8f (%s)\n",vout,dstr(value),jprint(txobj,0)); } free_json(txobj); - //if ( value != 0 ) - // gettxout } else printf("cant gettx\n"); if ( value == 0 ) { printf("basilisk_swap_bobtxspend.%s %s utxo.(%s).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 { @@ -795,19 +951,33 @@ int32_t LP_vin_select(int32_t *aboveip,int64_t *abovep,int32_t *belowip,int64_t above = gap; abovei = i; } - } else gap = (value - atx_value); - if ( below == 0 || gap < below ) + } + else { - below = gap; - belowi = i; + gap = (value - atx_value); + if ( below == 0 || gap < below ) + { + below = gap; + belowi = i; + } } + //printf("value %.8f gap %.8f abovei.%d %.8f belowi.%d %.8f\n",dstr(value),dstr(gap),abovei,dstr(above),belowi,dstr(below)); } *aboveip = abovei; *abovep = above; *belowip = belowi; *belowp = below; //printf("above.%d below.%d\n",abovei,belowi); - return(abovei >= 0 && above < (below>>1) ? abovei : belowi); + if ( abovei >= 0 && belowi >= 0 ) + { + if ( above < (below >> 1) ) + return(abovei); + else return(belowi); + } + else if ( abovei >= 0 ) + return(abovei); + else return(belowi); + //return(abovei >= 0 && above < (below>>1) ? abovei : belowi); } cJSON *LP_inputjson(bits256 txid,int32_t vout,char *spendscriptstr) @@ -825,8 +995,10 @@ cJSON *LP_inputjson(bits256 txid,int32_t vout,char *spendscriptstr) uint64_t _komodo_interestnew(uint64_t nValue,uint32_t nLockTime,uint32_t tiptime) { int32_t minutes; uint64_t interest = 0; - if ( (minutes= (tiptime - nLockTime) / 60) >= 60 ) + if ( tiptime > nLockTime && (minutes= (tiptime - nLockTime) / 60) >= 60 ) { + //minutes.71582779 tiptime.1511292969 locktime.1511293505 + printf("minutes.%d tiptime.%u locktime.%u\n",minutes,tiptime,nLockTime); if ( minutes > 365 * 24 * 60 ) minutes = 365 * 24 * 60; minutes -= 59; @@ -849,36 +1021,132 @@ int64_t LP_komodo_interest(bits256 txid,int64_t value) return(interest); } -int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_t amount,struct vin_info *V,struct LP_address_utxo **utxos,int32_t numunspents,int32_t suppress_pubkeys,int32_t ignore_cltverr,bits256 privkey,cJSON *privkeys,cJSON *vins,uint8_t *script,int32_t scriptlen) +int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_t amount,struct vin_info *V,struct LP_address_utxo **utxos,int32_t numunspents,int32_t suppress_pubkeys,int32_t ignore_cltverr,bits256 privkey,cJSON *privkeys,cJSON *vins,uint8_t *script,int32_t scriptlen,bits256 utxotxid,int32_t utxovout,int32_t dustcombine) { - char wifstr[128],spendscriptstr[128]; int32_t i,n,ind,abovei,belowi,maxmode=0; struct vin_info *vp; struct LP_address_utxo *up; int64_t interest,interestsum,above,below,remains = amount,total = 0; + char wifstr[128],spendscriptstr[128],str[65]; int32_t i,j,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); - for (i=n=0; iU.vout && bits256_cmp(utxotxid,up->U.txid) == 0 ) { - printf("error finding unspent i.%d of %d, %.8f vs %.8f\n",i,numunspents,dstr(remains),dstr(amount)); - return(0); + preselected[numpre++] = up; + printf("found utxotxid in slot.%d\n",j); + utxos[j] = 0; + continue; + } + if ( up->spendheight <= 0 && up->U.height > 0 && up->U.value != 0 ) + { + if ( (txobj= LP_gettxout(coin->symbol,coin->smartaddr,up->U.txid,up->U.vout)) == 0 ) + { + up->spendheight = 1; + utxos[j] = 0; + } + else + { + if ( LP_inventory_prevent(1,coin->symbol,up->U.txid,up->U.vout) == 0 ) + { + if ( min1 == 0 || up->U.value < min1->U.value ) + { + if ( min0 == 0 || up->U.value < min0->U.value ) + { + min1 = min0; + min0 = up; + } else min1 = up; + } + } else utxos[j] = 0; + if ( 0 && utxos[j] != 0 ) + printf("gettxout j.%d %s/v%d (%s)\n",j,bits256_str(str,up->U.txid),up->U.vout,jprint(txobj,0)); + free_json(txobj); + } + } else utxos[j] = 0; + } + if ( bits256_nonz(utxotxid) != 0 && numpre == 0 ) + { + up = LP_address_utxofind(coin,coin->smartaddr,utxotxid,utxovout); + //printf("have utxotxid but wasnt found up.%p\n",up); + if ( up == 0 ) + { + value = LP_txvalue(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 ( belowi < 0 || abovei >= 0 ) - ind = abovei; - else ind = belowi; - if ( ind < 0 ) + if ( (up= LP_address_utxofind(coin,coin->smartaddr,utxotxid,utxovout)) != 0 ) + preselected[numpre++] = up; + else { - printf("error finding unspent i.%d of %d, %.8f vs %.8f, abovei.%d belowi.%d ind.%d\n",i,numunspents,dstr(remains),dstr(amount),abovei,belowi,ind); + printf("couldnt add address_utxo after not finding\n"); return(0); } - up = utxos[ind]; - utxos[ind] = utxos[--numunspents]; - utxos[numunspents] = 0; + } + if ( dustcombine >= 1 && min0 != 0 && min0->U.value < LP_DUSTCOMBINE_THRESHOLD && (coin->electrum == 0 || min0->SPV > 0) ) + { + 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; + } + if ( bits256_cmp(utxotxid,up->U.txid) != 0 && LP_allocated(up->U.txid,up->U.vout) != 0 ) + continue; + up->spendheight = 1; total += up->U.value; remains -= up->U.value; + interest = 0; if ( up->U.height < 7777777 && strcmp(coin->symbol,"KMD") == 0 ) { if ( (interest= LP_komodo_interest(up->U.txid,up->U.value)) > 0 ) @@ -887,6 +1155,7 @@ int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_ 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; @@ -895,11 +1164,10 @@ int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_ vp->suppress_pubkeys = suppress_pubkeys; vp->ignore_cltverr = ignore_cltverr; jaddi(vins,LP_inputjson(up->U.txid,up->U.vout,spendscriptstr)); - //printf("wif.%s i.%d privkeys.%s vins.%s %p %p\n",wifstr,i,jprint(privkeys,0),jprint(vins,0),privkeys,vins); - //printf("%s value %.8f -> remains %.8f\n",coinaddr,dstr(value),dstr(remains)); - if ( remains <= 0 ) + LP_unavailableset(up->U.txid,up->U.vout,(uint32_t)time(NULL)+LP_RESERVETIME,G.LP_mypub25519); + if ( remains <= 0 && i >= numpre-1 ) break; - if ( numunspents == 0 ) + if ( numunspents < 0 || n >= LP_MAXVINS ) { printf("total %.8f not enough for amount %.8f\n",dstr(total),dstr(amount)); return(0); @@ -909,24 +1177,29 @@ int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_ return(n); } -char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_info *coin,struct vin_info *V,int32_t max,bits256 privkey,cJSON *outputs,cJSON *vins,cJSON *privkeys,int64_t txfee) +char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_info *coin,struct vin_info *V,int32_t max,bits256 privkey,cJSON *outputs,cJSON *vins,cJSON *privkeys,int64_t txfee,bits256 utxotxid,int32_t utxovout,uint32_t locktime) { static void *ctx; - cJSON *txobj,*item; uint8_t addrtype,rmd160[20],script[64],spendscript[64]; char *coinaddr,*rawtxbytes; bits256 txid; uint32_t timestamp,locktime; int64_t change=0,adjust=0,total,value,amount = 0; int32_t i,scriptlen,spendlen,suppress_pubkeys,ignore_cltverr,numvouts=0,numvins=0,numutxos=0; struct LP_address_utxo *utxos[256]; struct LP_address *ap; + cJSON *txobj,*item; uint8_t addrtype,rmd160[20],script[64],spendscript[256]; char *coinaddr,*rawtxbytes; bits256 txid; uint32_t timestamp; int64_t change=0,adjust=0,total,value,amount = 0; int32_t i,dustcombine,scriptlen,spendlen,suppress_pubkeys,ignore_cltverr,numvouts=0,numvins=0,numutxos=0; struct LP_address_utxo *utxos[LP_MAXVINS*256]; struct LP_address *ap; if ( ctx == 0 ) ctx = bitcoin_ctx(); *numvinsp = 0; *txobjp = 0; - if ( sizeof(utxos)/sizeof(*utxos) != max ) + /*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); + printf("%s LP_createrawtransaction %s i.%d of %d is invalid\n",coin->symbol,coinaddr,i,numvouts); return(0); } if ( (value= SATOSHIDEN * jdouble(item,coinaddr)) <= 0 ) @@ -944,6 +1217,7 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf return(0); } amount += value; + printf("vout.%d %.8f -> total %.8f\n",i,dstr(value),dstr(amount)); } else { @@ -951,41 +1225,41 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf return(0); } } - LP_listunspent_issue(coin->symbol,coin->smartaddr,1); - if ( (ap= LP_addressfind(coin,coin->smartaddr)) == 0 ) + if ( (ap= LP_address(coin,coin->smartaddr)) == 0 ) { - printf("LP_createrawtransaction: cant find address data\n"); + printf("LP_createrawtransaction LP_address null?\n"); return(0); } memset(utxos,0,sizeof(utxos)); - if ( (numutxos= LP_address_utxo_ptrs(coin,0,utxos,max,ap,coin->smartaddr)) <= 0 ) + if ( (numutxos= LP_address_utxo_ptrs(coin,0,utxos,(int32_t)(sizeof(utxos)/sizeof(*utxos)),ap,coin->smartaddr)) <= 0 ) { - printf("LP_createrawtransaction: address_utxo_ptrs %d, error\n",numutxos); - return(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); - if ( total < amount ) + 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 for amount %.8f < %.8f txfee %.8f\n",dstr(total),dstr(amount),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 ( strcmp("KMD",coin->symbol) == 0 ) + if ( locktime == 0 && strcmp("KMD",coin->symbol) == 0 ) locktime = timestamp - 777; - else locktime = 0; txobj = bitcoin_txcreate(coin->symbol,coin->isPoS,locktime,1,timestamp); jdelete(txobj,"vin"); jadd(txobj,"vin",jduplicate(vins)); - 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); - spendlen = bitcoin_standardspend(spendscript,0,rmd160); + if ( addrtype == coin->pubtype ) + spendlen = bitcoin_standardspend(spendscript,0,rmd160); + else spendlen = bitcoin_p2shspend(spendscript,0,rmd160); + if ( i == numvouts-1 && strcmp(coinaddr,coin->smartaddr) == 0 && change != 0 ) + { + printf("combine last vout %.8f with change %.8f\n",dstr(value+adjust),dstr(change)); + value += change; + change = 0; + } txobj = bitcoin_txoutput(txobj,spendscript,spendlen,value + adjust); } else { printf("cant get fieldname.%d of %d %s\n",i,numvouts,jprint(outputs,0)); + free_json(txobj); return(0); } } + if ( change < 6000 ) + { + //adjust = change / numvouts; adjust messes up vout encoding! + change = 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; + *numvinsp = numvins; return(rawtxbytes); } char *LP_withdraw(struct iguana_info *coin,cJSON *argjson) { static void *ctx; - int32_t iter,completed=0,maxV,numvins,numvouts,datalen,suppress_pubkeys; bits256 privkey; char changeaddr[64],vinaddr[64],str[65],*signedtx=0,*rawtx=0; struct vin_info *V; cJSON *retjson,*outputs,*vins=0,*txobj=0,*privkeys=0; struct iguana_msgtx msgtx; bits256 signedtxid; uint64_t txfee,newtxfee=10000; + int32_t iter,i,utxovout,autofee,completed=0,maxV,numvins,numvouts,datalen,suppress_pubkeys; bits256 privkey; struct LP_address *ap; char changeaddr[64],vinaddr[64],str[65],*signedtx=0,*rawtx=0; struct vin_info *V; uint32_t locktime; cJSON *retjson,*item,*outputs,*vins=0,*txobj=0,*privkeys=0; struct iguana_msgtx msgtx; bits256 utxotxid,signedtxid; uint64_t txfee,newtxfee=10000; + if ( ctx == 0 ) + ctx = bitcoin_ctx(); if ( (outputs= jarray(&numvouts,argjson,"outputs")) == 0 ) { printf("no outputs in argjson (%s)\n",jprint(argjson,0)); return(clonestr("{\"error\":\"no outputs specified\"}")); } - txfee = coin->txfee; - if ( ctx == 0 ) - ctx = bitcoin_ctx(); - if ( txfee > 0 && txfee < 10000 ) - txfee = 10000; + utxotxid = jbits256(argjson,"utxotxid"); + utxovout = jint(argjson,"utxovout"); + locktime = juint(argjson,"locktime"); + txfee = juint(argjson,"txfee"); + autofee = (strcmp(coin->symbol,"BTC") == 0); + if ( txfee == 0 ) + { + autofee = 1; + txfee = coin->txfee; + if ( txfee > 0 && txfee < 10000 ) + txfee = 10000; + } else autofee = 0; suppress_pubkeys = 0; memset(signedtxid.bytes,0,sizeof(signedtxid)); safecopy(changeaddr,coin->smartaddr,sizeof(changeaddr)); safecopy(vinaddr,coin->smartaddr,sizeof(vinaddr)); privkey = LP_privkey(vinaddr,coin->taddr); - maxV = 256; + maxV = LP_MAXVINS; V = malloc(maxV * sizeof(*V)); for (iter=0; iter<2; iter++) { + if ( (ap= LP_address_utxo_reset(coin)) == 0 ) + { + printf("LP_withdraw error utxo reset %s\n",coin->symbol); + free(V); + return(0); + } privkeys = cJSON_CreateArray(); vins = cJSON_CreateArray(); memset(V,0,sizeof(*V) * maxV); - if ( (rawtx= LP_createrawtransaction(&txobj,&numvins,coin,V,maxV,privkey,outputs,vins,privkeys,iter == 0 ? txfee : newtxfee)) != 0 ) + numvins = 0; + if ( (rawtx= LP_createrawtransaction(&txobj,&numvins,coin,V,maxV,privkey,outputs,vins,privkeys,iter == 0 ? txfee : newtxfee,utxotxid,utxovout,locktime)) != 0 ) { completed = 0; memset(&msgtx,0,sizeof(msgtx)); @@ -1058,21 +1364,40 @@ char *LP_withdraw(struct iguana_info *coin,cJSON *argjson) if ( signedtx == 0 ) break; datalen = (int32_t)strlen(signedtx) / 2; - if ( strcmp(coin->symbol,"BTC") == 0 ) + if ( iter == 0 && strcmp(coin->symbol,"BTC") == 0 ) { newtxfee = LP_txfeecalc(coin,0,datalen); - printf("txfee %.8f -> newtxfee %.8f\n",dstr(txfee),dstr(newtxfee)); + printf("txfee %.8f -> newtxfee %.8f, numvins.%d\n",dstr(txfee),dstr(newtxfee),numvins); + for (i=0; i 0 ) + { + + for (i=0; isymbol)) == 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); + //printf("call LP_withdraw.(%s)\n",jprint(argjson,0)); + 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; + } else printf("rawtx withdraw error? (%s)\n",retstr); + 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 ) @@ -1123,6 +1486,7 @@ int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pub break; } return(retval); +#endif } int32_t basilisk_rawtx_sign(char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,struct basilisk_swap *swap,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr,uint8_t *changermd160,char *vinaddr,int32_t zcash) @@ -1190,19 +1554,11 @@ char *basilisk_swap_Aspend(char *name,char *symbol,uint64_t Atxfee,uint8_t wifta //printf("pubAm.(%s)\n",bits256_str(str,pubAm)); //printf("pubBn.(%s)\n",bits256_str(str,pubBn)); spendlen = basilisk_alicescript(redeemscript,&redeemlen,spendscript,0,msigaddr,taddr,p2shtype,pubAm,pubBn); - //char str[65]; printf("%s utxo.(%s) redeemlen.%d spendlen.%d\n",msigaddr,bits256_str(str,utxotxid),redeemlen,spendlen); - /*rev = privAm; - for (i=0; i<32; i++) - privAm.bytes[i] = rev.bytes[31 - i]; - rev = privBn; - for (i=0; i<32; i++) - privBn.bytes[i] = rev.bytes[31 - i];*/ if ( (txfee= Atxfee) == 0 ) { if ( (txfee= LP_getestimatedrate(LP_coinfind(symbol)) * LP_AVETXSIZE) < LP_MIN_TXFEE ) txfee = LP_MIN_TXFEE; } - //txfee = LP_txfee(symbol); signedtx = basilisk_swap_bobtxspend(&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); } @@ -1213,7 +1569,7 @@ int32_t LP_swap_getcoinaddr(char *symbol,char *coinaddr,bits256 txid,int32_t vou { cJSON *retjson; coinaddr[0] = 0; - if ( (retjson= LP_gettx(symbol,txid)) != 0 ) + if ( (retjson= LP_gettx(symbol,txid,0)) != 0 ) { LP_txdestaddr(coinaddr,txid,vout,retjson); free_json(retjson); @@ -1224,7 +1580,7 @@ int32_t LP_swap_getcoinaddr(char *symbol,char *coinaddr,bits256 txid,int32_t vou int32_t basilisk_swap_getsigscript(char *symbol,uint8_t *script,int32_t maxlen,bits256 txid,int32_t vini) { cJSON *retjson,*vins,*item,*skey; int32_t n,scriptlen = 0; char *hexstr; - if ( (retjson= LP_gettx(symbol,txid)) != 0 ) + if ( (retjson= LP_gettx(symbol,txid,0)) != 0 ) { if ( (vins= jarray(&n,retjson,"vin")) != 0 && vini < n ) { @@ -1296,25 +1652,56 @@ bits256 _LP_swap_spendtxid(char *symbol,char *destaddr,char *coinaddr,bits256 ut } #endif -bits256 LP_swap_spendtxid(char *symbol,char *destaddr,bits256 utxotxid,int32_t vout) +bits256 LP_swap_spendtxid(char *symbol,char *destaddr,bits256 utxotxid,int32_t utxovout) { - bits256 spendtxid; int32_t spendvin; char coinaddr[64],str[65]; cJSON *retjson; struct iguana_info *coin; + bits256 spendtxid,txid,vintxid; int32_t spendvin,i,m,n; char coinaddr[64]; cJSON *array,*vins,*vin,*txobj; struct iguana_info *coin; // listtransactions or listspents - destaddr[0] = 0; coinaddr[0] = 0; memset(&spendtxid,0,sizeof(spendtxid)); - if ( LP_spendsearch(destaddr,&spendtxid,&spendvin,symbol,utxotxid,vout) > 0 ) + if ( LP_spendsearch(destaddr,&spendtxid,&spendvin,symbol,utxotxid,utxovout) > 0 ) { - //printf("spend of %s/v%d detected\n",bits256_str(str,utxotxid),vout); + //char str[65]; printf("spend of %s/v%d detected\n",bits256_str(str,utxotxid),utxovout); } - else if ( 0 && (coin= LP_coinfind(symbol)) != 0 && coin->electrum == 0 ) + else if ( (coin= LP_coinfind(symbol)) != 0 && coin->electrum == 0 ) { - if ( (retjson= LP_gettxout(symbol,coinaddr,utxotxid,vout)) == 0 ) + if ( (array= LP_listreceivedbyaddress(symbol,destaddr)) != 0 ) { - decode_hex(spendtxid.bytes,32,"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"); - printf("couldnt find spend of %s/v%d, but no gettxout\n",bits256_str(str,utxotxid),vout); - } else free_json(retjson); + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; iI.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,swap->bobcoin.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); - } + 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,swap->bobcoin.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); - } + 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); } @@ -1480,7 +1875,7 @@ void LP_swap_coinaddr(struct iguana_info *coin,char *coinaddr,uint64_t *valuep,u 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 ) + if ( (txobj= bitcoin_data2json(coin->symbol,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 ) @@ -1488,17 +1883,6 @@ void LP_swap_coinaddr(struct iguana_info *coin,char *coinaddr,uint64_t *valuep,u vout = jitem(vouts,v); if ( valuep != 0 ) *valuep = LP_value_extract(vout,1); - //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); - } - }*/ LP_destaddr(coinaddr,vout); } free_json(txobj); @@ -1507,82 +1891,84 @@ void LP_swap_coinaddr(struct iguana_info *coin,char *coinaddr,uint64_t *valuep,u 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->bobcoin,checkaddr,0,swap->bobpayment.txbytes,swap->bobpayment.I.datalen,0); - 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->bobcoin,checkaddr,0,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen,0); - 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); } @@ -1593,7 +1979,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 ) { @@ -1605,7 +1991,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]); @@ -1623,12 +2009,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); @@ -1636,77 +2016,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 locktime %u vs %u\n",dstr(swap->otherfee.I.amount),swap->otherfee.p2shaddr,swap->otherfee.I.destaddr,swap->otherfee.I.locktime,swap->I.started+1); - if ( strcmp(swap->otherfee.I.destaddr,swap->otherfee.p2shaddr) == 0 ) + if ( LP_rawtx_spendscript(swap,coin->longestchain,&swap->otherfee,0,data,datalen,0) == 0 ) { - if ( swap->otherfee.I.locktime == swap->I.started+1 ) - 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); - } + 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 < LP_AUTOTRADE_TIMEOUT ) + 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) { - if ( LP_rawtx_spendscript(swap,swap->bobcoin.longestchain,&swap->alicespend,0,data,datalen,0) == 0 ) + struct iguana_info *coin; + if ( (coin= LP_coinfind(swap->I.alicestr)) != 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 ) + if ( LP_rawtx_spendscript(swap,coin->longestchain,&swap->alicespend,0,data,datalen,0) == 0 ) { - printf("alicespend verified\n"); - return(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); } @@ -1719,110 +2116,120 @@ int32_t LP_verify_alicespend(struct basilisk_swap *swap,uint8_t *data,int32_t da 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->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; - 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,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); - 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,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,swap->bobcoin.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(swap->bobcoin.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); - } + 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.destaddr,swap->alicepayment.I.signedtxid,0,60)); - //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,swap->bobcoin.zcash)) == 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.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); - } + 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 index cb3d90a6e..227532b57 100644 --- a/iguana/exchanges/LP_utxo.c +++ b/iguana/exchanges/LP_utxo.c @@ -18,6 +18,171 @@ // 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; + if ( LP_numinuse > 0 ) + *lp = LP_inuse[--LP_numinuse]; + lp->ind = ind; + memset(&LP_inuse[LP_numinuse],0,sizeof(struct LP_inuse_info)); + //printf("_LP_inuse_delete mark as free %s/v%d find.%p\n",bits256_str(str,txid),vout,_LP_inuse_find(txid,vout)); + 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; + } + char str[65]; printf("set inuse until %u lag.%d for %s/v%d\n",expiration,(int32_t)(expiration-(uint32_t)time(NULL)),bits256_str(str,txid),vout); + return(lp); + } else printf("_LP_inuse_add [%d] overflow\n",LP_numinuse); + return(0); +} + +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_maxvalue(uint64_t *values,int32_t n) +{ + int32_t i,maxi = -1; uint64_t maxval = 0; + for (i=0; i maxval ) + { + maxi = i; + maxval = values[i]; + } + return(maxi); +} + +int32_t LP_nearestvalue(int32_t iambob,uint64_t *values,int32_t n,uint64_t targetval) +{ + int32_t i,mini = -1; int64_t dist; uint64_t mindist = (1 << 31); + for (i=0; i= 0 && dist < mindist ) + { + mini = i; + mindist = dist; + } + } + return(mini); +} + uint64_t LP_value_extract(cJSON *obj,int32_t addinterest) { double val = 0.; uint64_t value = 0; int32_t electrumflag; @@ -64,7 +229,10 @@ 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); } @@ -92,63 +260,41 @@ struct LP_address *LP_address(struct iguana_info *coin,char *coinaddr) return(ap); } -int32_t LP_address_minmax(uint64_t *balancep,uint64_t *minp,uint64_t *maxp,struct LP_address *ap) +int32_t LP_address_minmax(uint64_t *balancep,uint64_t *minp,uint64_t *maxp,struct iguana_info *coin,char *coinaddr) { - struct LP_address_utxo *up,*tmp; int32_t n = 0; + cJSON *array,*item; bits256 txid,zero; int64_t value; int32_t i,vout,height,n = 0; *minp = *maxp = *balancep = 0; - DL_FOREACH_SAFE(ap->utxos,up,tmp) + memset(zero.bytes,0,sizeof(zero)); + if ( (array= LP_listunspent(coin->symbol,coinaddr,zero,zero)) != 0 ) { - if ( up->spendheight <= 0 ) + //printf("address minmax.(%s)\n",jprint(array,0)); + if ( (n= cJSON_GetArraySize(array)) > 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++; + for (i=0; i *maxp ) + *maxp = value; + if ( *minp == 0 || value < *minp ) + *minp = value; + *balancep += value; + } } + free_json(array); } - if ( 0 && n > 0 ) - printf("n.%d %s min %.8f max %.8f\n",n,ap->coinaddr,dstr(*minp),dstr(*maxp)); return(n); } -struct LP_utxoinfo *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_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; char str[65]; - //printf("LP_address_utxo_ptrs for (%s).(%s)\n",ap->coinaddr,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); - portable_mutex_lock(&LP_utxomutex); + //portable_mutex_lock(&LP_utxomutex); DL_FOREACH_SAFE(ap->utxos,up,tmp) { - //char str[65]; printf("LP_address_utxo_ptrs %s n.%d %.8f %s v%d spendheight.%d allocated.%p\n",ap->coinaddr,n,dstr(up->U.value),bits256_str(str,up->U.txid),up->U.vout,up->spendheight,LP_allocated(up->U.txid,up->U.vout)); + //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 ) @@ -157,7 +303,7 @@ int32_t LP_address_utxo_ptrs(struct iguana_info *coin,int32_t iambob,struct LP_a { 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); + //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 ) @@ -168,7 +314,7 @@ int32_t LP_address_utxo_ptrs(struct iguana_info *coin,int32_t iambob,struct LP_a } 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); + //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; @@ -177,9 +323,9 @@ int32_t LP_address_utxo_ptrs(struct iguana_info *coin,int32_t iambob,struct LP_a } else { - if ( up->SPV <= 0 || up->U.height == 0 ) + if ( up->SPV < 0 || up->U.height == 0 ) { - printf("LP_address_utxo_ptrs skips %s/v%u due to SPV.%d ht.%d\n",bits256_str(str,up->U.txid),up->U.vout,up->SPV,up->U.height); +//printf("LP_address_utxo_ptrs skips %s/v%u due to SPV.%d ht.%d\n",bits256_str(str,up->U.txid),up->U.vout,up->SPV,up->U.height); if ( (tx= LP_transactionfind(coin,up->U.txid)) != 0 && up->U.vout < tx->numvouts ) tx->outpoints[up->U.vout].spendheight = 1; continue; @@ -190,7 +336,7 @@ int32_t LP_address_utxo_ptrs(struct iguana_info *coin,int32_t iambob,struct LP_a utxos[n++] = up; if ( n >= max ) break; - } + } //else printf("LP_allocated skip %u\n",LP_allocated(up->U.txid,up->U.vout)); } else { @@ -198,8 +344,8 @@ int32_t LP_address_utxo_ptrs(struct iguana_info *coin,int32_t iambob,struct LP_a tx->outpoints[up->U.vout].spendheight = 1; } } - portable_mutex_unlock(&LP_utxomutex); - //printf("return n.%d\n",n); + //portable_mutex_unlock(&LP_utxomutex); + //printf("return n.%d for %s %s\n",n,coin->symbol,coinaddr); return(n); } @@ -235,9 +381,9 @@ void LP_mark_spent(char *symbol,bits256 txid,int32_t vout) } } -int32_t LP_address_utxoadd(char *debug,struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight) +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_address_utxo *up,*tmp; int32_t flag,retval = 0; char str[65]; + 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 @@ -258,7 +404,8 @@ int32_t LP_address_utxoadd(char *debug,struct iguana_info *coin,char *coinaddr,b up->spendheight = spendheight, flag |= 4; if ( value != 0 && up->U.value == 0 && up->U.value != value ) up->U.value = value, flag |= 8; -//printf("found >>>>>>>>>> %s %s %s/v%d ht.%d %.8f\n",coin->symbol,coinaddr,bits256_str(str,txid),vout,height,dstr(value)); + //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; } } @@ -268,7 +415,7 @@ int32_t LP_address_utxoadd(char *debug,struct iguana_info *coin,char *coinaddr,b { if ( (txobj= LP_gettxout(coin->symbol,coinaddr,txid,vout)) == 0 ) { - //printf("prevent utxoadd since gettxout %s %s %s/v%d missing\n",coin->symbol,coinaddr,bits256_str(str,txid),vout); + //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); } @@ -278,27 +425,87 @@ int32_t LP_address_utxoadd(char *debug,struct iguana_info *coin,char *coinaddr,b up->U.height = height; up->U.value = value; up->spendheight = spendheight; - portable_mutex_lock(&coin->addrmutex); - DL_APPEND(ap->utxos,up); - portable_mutex_unlock(&coin->addrmutex); + //up->timestamp = timestamp; retval = 1; - if ( value == 0 ) + 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,m,vout,height; cJSON *array,*item,*txobj; bits256 zero; int64_t value; bits256 txid; uint32_t now; + LP_address(coin,coin->smartaddr); + //printf("call listunspent issue %s (%s)\n",coin->symbol,coin->smartaddr); + memset(zero.bytes,0,sizeof(zero)); + LP_listunspent_issue(coin->symbol,coin->smartaddr,2,zero,zero); + 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,zero,zero)) != 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=m=0; isymbol,coin->smartaddr,txid,vout)) == 0 ) + continue; + else free_json(txobj); + if ( LP_numconfirms(coin->symbol,coin->smartaddr,txid,vout,0) <= 0 ) + continue; + 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)); + else + { + m++; + //printf("%.8f ",dstr(value)); + } + } + //printf("added %d from listunspents\n",m); + } + 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(); + int32_t notarized; 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,"confirmations",LP_getheight(¬arized,coin) - up->U.height + 1); jaddnum(item,"amount",dstr(up->U.value)); jaddstr(item,"scriptPubKey",""); } @@ -316,89 +523,6 @@ cJSON *LP_address_item(struct iguana_info *coin,struct LP_address_utxo *up,int32 uint64_t _LP_unspents_metric(uint64_t total,int32_t n) { return((total<<16) | (n & 0xffff)); } -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); -} - -int32_t LP_merkleproof(struct iguana_info *coin,struct electrum_info *ep,bits256 txid,int32_t height) -{ - cJSON *merkobj,*merkles,*hdrobj; bits256 roothash,merkleroot; int32_t m,SPV = 0; - if ( (merkobj= electrum_getmerkle(coin->symbol,ep,&merkobj,txid,height)) != 0 ) - { - char str[65],str2[65],str3[65]; - SPV = -1; - memset(roothash.bytes,0,sizeof(roothash)); - if ( (merkles= jarray(&m,merkobj,"merkle")) != 0 ) - { - roothash = validate_merkle(jint(merkobj,"pos"),txid,merkles,m); - if ( (hdrobj= electrum_getheader(coin->symbol,ep,&hdrobj,height)) != 0 ) - { - if ( jobj(hdrobj,"merkle_root") != 0 ) - { - merkleroot = jbits256(hdrobj,"merkle_root"); - if ( bits256_cmp(merkleroot,roothash) == 0 ) - { - SPV = height; - //printf("validated MERK %s ht.%d -> %s root.(%s)\n",bits256_str(str,up->U.txid),up->U.height,jprint(merkobj,0),bits256_str(str2,roothash)); - } - else printf("ERROR MERK %s ht.%d -> %s root.(%s) vs %s (%s)\n",bits256_str(str,txid),height,jprint(merkobj,0),bits256_str(str2,roothash),bits256_str(str3,merkleroot),jprint(hdrobj,0)); - } else SPV = 0; - free_json(hdrobj); - } else printf("couldnt get header for ht.%d\n",height); - } - if ( SPV < 0 ) - { - printf("MERKLE DIDNT VERIFY.%s %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); -} - 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; @@ -421,7 +545,10 @@ cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrum } if ( up->spendheight <= 0 && up->U.value != 0 ) { - if ( coin->electrum == 0 || up->SPV > 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++; @@ -454,26 +581,119 @@ cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrum cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electrumret) { - cJSON *array,*retjson; int32_t i,n; uint64_t balance = 0; - if ( (array= LP_address_utxos(coin,coinaddr,1)) != 0 ) + cJSON *array,*retjson,*item; bits256 zero; int32_t i,n; uint64_t balance = 0; + memset(zero.bytes,0,sizeof(zero)); + if ( coin->electrum == 0 ) { - if ( (n= cJSON_GetArraySize(array)) > 0 ) + if ( (array= LP_listunspent(coin->symbol,coinaddr,zero,zero)) != 0 ) { - for (i=0; i 0 ) + { + for (i=0; ismartaddr,coinaddr) != 0 ) + { + if ( (retjson= electrum_address_listunspent(coin->symbol,coin->electrum,&retjson,coinaddr,2,zero,zero)) != 0 ) + free_json(retjson); } + balance = LP_unspents_load(coin->symbol,coinaddr); } retjson = cJSON_CreateObject(); jaddstr(retjson,"result","success"); jaddstr(retjson,"coin",coin->symbol); jaddstr(retjson,"address",coinaddr); jaddnum(retjson,"balance",dstr(balance)); + if ( strcmp(coin->symbol,"KMD") == 0 && strcmp(coin->smartaddr,coinaddr) == 0 ) + { + jaddnum(retjson,"zcredits",dstr(LP_myzcredits())); + jadd(retjson,"zdebits",LP_myzdebits()); + } return(retjson); } +cJSON *LP_balances(char *coinaddr) +{ + struct iguana_info *coin,*tmp; char address[64]; uint8_t addrtype,rmd160[20]; uint64_t balance,KMDvalue,sum = 0; cJSON *array,*item,*retjson; + array = cJSON_CreateArray(); + HASH_ITER(hh,LP_coins,coin,tmp) + { + if ( coin->electrum != 0 || (coinaddr != 0 && coinaddr[0] != 0 && strcmp(coinaddr,coin->smartaddr) != 0) ) + { + if ( coinaddr == 0 || coinaddr[0] == 0 ) + { + coinaddr = coin->smartaddr; + strcpy(address,coinaddr); + } + else + { + bitcoin_addr2rmd160(0,&addrtype,rmd160,coinaddr); + bitcoin_address(address,coin->taddr,coin->pubtype,rmd160,20); + } + if ( (retjson= LP_address_balance(coin,address,1)) != 0 ) + { + if ( (balance= jdouble(retjson,"balance")*SATOSHIDEN) > 0 ) + { + item = cJSON_CreateObject(); + jaddstr(item,"coin",coin->symbol); + jaddnum(item,"balance",dstr(balance)); + if ( (KMDvalue= LP_KMDvalue(coin,balance)) != 0 ) + { + jaddnum(item,"KMDvalue",dstr(KMDvalue)); + sum += KMDvalue; + } + if ( coin->electrum != 0 && strcmp(coinaddr,coin->smartaddr) == 0 && strcmp(coin->symbol,"KMD") == 0 ) + { + jaddnum(item,"zcredits",dstr(LP_myzcredits())); + jadd(item,"zdebits",LP_myzdebits()); + } + jaddi(array,item); + } + free_json(retjson); + } + } + else + { + if ( (balance= LP_RTsmartbalance(coin)) != 0 ) + { + item = cJSON_CreateObject(); + jaddstr(item,"coin",coin->symbol); + jaddnum(item,"balance",dstr(balance)); + if ( (KMDvalue= LP_KMDvalue(coin,balance)) != 0 ) + { + jaddnum(item,"KMDvalue",dstr(KMDvalue)); + sum += KMDvalue; + } + if ( strcmp(coin->symbol,"KMD") == 0 ) + { + jaddnum(item,"zcredits",dstr(LP_myzcredits())); + jadd(item,"zdebits",LP_myzdebits()); + } + jaddi(array,item); + } + } + } + if ( sum != 0 ) + { + item = cJSON_CreateObject(); + jaddstr(item,"coin","total"); + jaddnum(item,"balance",dstr(sum)); + jaddi(array,item); + } + return(array); +} + int32_t LP_unspents_array(struct iguana_info *coin,char *coinaddr,cJSON *array) { - int32_t i,n,v,ht,errs,height,count=0; uint64_t value,val; cJSON *item,*txobj; bits256 txid; + 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)); @@ -493,7 +713,7 @@ int32_t LP_unspents_array(struct iguana_info *coin,char *coinaddr,cJSON *array) char str[65]; printf("REJECT %s %s/v%d value.%llu vs %llu (%s)\n",coin->symbol,bits256_str(str,txid),v,(long long)value,(long long)val,jprint(txobj,0)); errs++; } - ht = LP_txheight(coin,txid); + //ht = LP_txheight(coin,txid); //if ( coin->height != 0 ) // ht = LP_getheight(coin) - jint(txobj,"confirmations") + 1; //else ht = 0; @@ -507,75 +727,13 @@ int32_t LP_unspents_array(struct iguana_info *coin,char *coinaddr,cJSON *array) if ( errs == 0 ) { //printf("from LP_unspents_array\n"); - LP_address_utxoadd("LP_unspents_array",coin,coinaddr,txid,v,val,height,-1); + 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)]; - /*if ( iambob != 0 ) - { - static uint32_t counter; - if ( counter++ < 3 ) - printf("_LP_utxofind deprecated iambob\n"); - return(0); - }*/ - LP_utxosetkey(key,txid,vout); - HASH_FIND(hh,G.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)]; - /*if ( iambob != 0 ) - { - printf("_LP_utxo2find deprecated iambob\n"); - return(0); - }*/ - 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; @@ -587,13 +745,15 @@ struct LP_transaction *LP_transactionfind(struct iguana_info *coin,bits256 txid) struct LP_transaction *LP_transactionadd(struct iguana_info *coin,bits256 txid,int32_t height,int32_t numvouts,int32_t numvins) { - struct LP_transaction *tx; int32_t i; + static long totalsize; + struct LP_transaction *tx; int32_t i; //char str[65]; 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)); + 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; @@ -604,7 +764,7 @@ struct LP_transaction *LP_transactionadd(struct iguana_info *coin,bits256 txid,i 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)); + } //else printf("warning adding already existing txid %s\n",bits256_str(str,tx->txid)); return(tx); } @@ -613,7 +773,7 @@ cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJS 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 ( txobj != 0 || (txobj= LP_gettx(coin->symbol,txid,0)) != 0 ) { if ( coin->electrum == 0 ) height = LP_txheight(coin,txid); @@ -631,7 +791,7 @@ cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJS 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("LP_transactioninit iter0",coin,tx->outpoints[i].coinaddr,txid,i,tx->outpoints[i].value,height,-1); + 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); } @@ -653,7 +813,7 @@ cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJS tx->outpoints[spentvout].spendtxid = txid; tx->outpoints[spentvout].spendvini = i; tx->outpoints[spentvout].spendheight = height > 0 ? height : 1; - LP_address_utxoadd("LP_transactioninit iter1",coin,tx->outpoints[spentvout].coinaddr,spenttxid,spentvout,tx->outpoints[spentvout].value,-1,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); } @@ -670,12 +830,12 @@ cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJS int32_t LP_txheight(struct iguana_info *coin,bits256 txid) { - bits256 blockhash; struct LP_transaction *tx; cJSON *blockobj,*txobj; int32_t height = 0; + bits256 blockhash; struct LP_transaction *tx; cJSON *blockobj,*retjson,*txobj; int32_t height = 0; if ( coin == 0 ) return(-1); if ( coin->electrum == 0 ) { - if ( (txobj= LP_gettx(coin->symbol,txid)) != 0 ) + if ( (txobj= LP_gettx(coin->symbol,txid,0)) != 0 ) { //*timestampp = juint(txobj,"locktime"); //*blocktimep = juint(txobj,"blocktime"); @@ -695,13 +855,23 @@ int32_t LP_txheight(struct iguana_info *coin,bits256 txid) { if ( (tx= LP_transactionfind(coin,txid)) != 0 ) height = tx->height; + if ( height == 0 ) + { + if ( (retjson= electrum_transaction(&height,coin->symbol,coin->electrum,&retjson,txid,0)) != 0 ) + { + //printf("process %s\n",jprint(retjson,0)); + free_json(retjson); + } + 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; + struct iguana_info *coin; bits256 zero; int32_t ht,notarized,numconfirms = 100; cJSON *txobj; if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) return(-1); @@ -715,12 +885,18 @@ int32_t LP_numconfirms(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int } else if ( mempool != 0 && LP_mempoolscan(symbol,txid) >= 0 ) numconfirms = 0; + else if ( (txobj= LP_gettx(symbol,txid,1)) != 0 ) + { + numconfirms = jint(txobj,"confirmations"); + free_json(txobj); + } } else { - LP_listunspent_issue(symbol,coinaddr,1); + memset(zero.bytes,0,sizeof(zero)); + LP_listunspent_issue(symbol,coinaddr,1,txid,zero); if ( (ht= LP_txheight(coin,txid)) > 0 && ht <= coin->height ) - numconfirms = (LP_getheight(coin) - ht + 1); + numconfirms = (LP_getheight(¬arized,coin) - ht + 1); else if ( mempool != 0 ) { if ( LP_waitmempool(symbol,coinaddr,txid,vout,30) >= 0 ) @@ -811,13 +987,12 @@ uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout) } else if ( coin->electrum == 0 ) { - uint64_t value; char _coinaddr[64]; + 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 ) - coinaddr = _coinaddr; - LP_destaddr(coinaddr,txobj); + 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 ) { @@ -832,9 +1007,26 @@ uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout) return(0); } +int64_t LP_outpoint_amount(char *symbol,bits256 txid,int32_t vout) +{ + int64_t amount=0; int32_t numvouts; char coinaddr[64]; cJSON *vouts,*txjson; + if ( (amount= LP_txvalue(coinaddr,symbol,txid,vout)) != 0 ) + return(amount); + else + { + if ( (txjson= LP_gettx(symbol,txid,1)) != 0 ) + { + if ( (vouts= jarray(&numvouts,txjson,"vout")) != 0 && vout < numvouts ) + amount = LP_value_extract(jitem(vouts,vout),0); + free_json(txjson); + } + } + return(amount); +} + 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; int32_t bypass = 0; char destaddr[64],destaddr2[64]; struct LP_transaction *tx; struct LP_address_utxo *up; struct iguana_info *coin = LP_coinfind(symbol); + 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"); @@ -857,8 +1049,6 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol { 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; @@ -867,18 +1057,20 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol strcpy(destaddr,destaddr2); if ( coin != 0 ) { - if ( (tx= LP_transactionfind(coin,txid)) != 0 && vout < tx->numvouts && tx->outpoints[vout].spendheight > 0 ) + if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid,vout)) == 0 ) return(0); - if ( (tx= LP_transactionfind(coin,txid2)) != 0 && vout2 < tx->numvouts && tx->outpoints[vout2].spendheight > 0 ) + else free_json(txobj); + if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid2,vout2)) == 0 ) return(0); - if ( (up= LP_address_utxofind(coin,destaddr,txid,vout)) != 0 && up->spendheight > 0 ) + else free_json(txobj); + if ( LP_numconfirms(coin->symbol,destaddr,txid,vout,0) <= 0 ) return(0); - if ( (up= LP_address_utxofind(coin,destaddr,txid2,vout2)) != 0 && up->spendheight > 0 ) + if ( LP_numconfirms(coin->symbol,destaddr,txid2,vout2,0) <= 0 ) return(0); } return(1); } - } // else printf("no val2\n"); + } else printf("no val2 %.8f < threshold %.8f\n",dstr(val),dstr(threshold)); } /*char str2[65]; if ( val != 0 && val2 != 0 ) @@ -921,10 +1113,14 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol int32_t LP_inventory_prevent(int32_t iambob,char *symbol,bits256 txid,int32_t vout) { - struct LP_utxoinfo *utxo; struct LP_transaction *tx; struct iguana_info *coin; - if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 || (utxo= LP_utxo2find(iambob,txid,vout)) != 0 ) + struct LP_address_utxo *up; struct iguana_info *coin; //struct LP_utxoinfo *utxo; struct LP_transaction *tx; + 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= LP_coinfind(symbol)) != 0 && (tx= LP_transactionfind(coin,txid)) != 0 ) + if ( coin != 0 && (tx= LP_transactionfind(coin,txid)) != 0 ) { if ( tx->outpoints[vout].spendheight > 0 ) utxo->T.spentflag = tx->outpoints[vout].spendheight; @@ -935,6 +1131,61 @@ int32_t LP_inventory_prevent(int32_t iambob,char *symbol,bits256 txid,int32_t vo //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); } diff --git a/iguana/exchanges/LP_utxos.c b/iguana/exchanges/LP_utxos.c deleted file mode 100644 index 49c11c283..000000000 --- a/iguana/exchanges/LP_utxos.c +++ /dev/null @@ -1,808 +0,0 @@ - -/****************************************************************************** - * Copyright © 2014-2017 The SuperNET Developers. * - * * - * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * - * the top-level directory of this distribution for the individual copyright * - * holder information and the developer policies on copyright and licensing. * - * * - * Unless otherwise agreed in a custom licensing agreement, no part of the * - * SuperNET software, including this file may be copied, modified, propagated * - * or distributed except according to the terms contained in the LICENSE file * - * * - * Removal or modification of this copyright notice is prohibited. * - * * - ******************************************************************************/ -// -// LP_utxos.c -// marketmaker -// - - - - -int32_t LP_ismine(struct LP_utxoinfo *utxo) -{ - if ( utxo != 0 && bits256_cmp(utxo->pubkey,G.LP_mypub25519) == 0 ) - return(1); - else return(0); -} - -int32_t LP_isavailable(struct LP_utxoinfo *utxo) -{ - if ( time(NULL) > utxo->T.swappending ) - utxo->T.swappending = 0; - if ( utxo != 0 && utxo->T.swappending == 0 && utxo->S.swap == 0 ) - return(1); - else return(0); -} - -int32_t LP_isunspent(struct LP_utxoinfo *utxo) -{ - struct LP_address_utxo *up; struct _LP_utxoinfo u; struct iguana_info *coin; - if ( (coin= LP_coinfind(utxo->coin)) == 0 ) - return(0); - if ( (up= LP_address_utxofind(coin,utxo->coinaddr,utxo->payment.txid,utxo->payment.vout)) != 0 && up->spendheight > 0 ) - { - utxo->T.spentflag = up->spendheight; - return(0); - } - u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; - if ( (up= LP_address_utxofind(coin,utxo->coinaddr,u.txid,u.vout)) != 0 && up->spendheight > 0 ) - { - utxo->T.spentflag = up->spendheight; - return(0); - } - if ( utxo != 0 && utxo->T.spentflag == 0 && LP_isavailable(utxo) > 0 ) - return(1); - else return(0); -} - -struct LP_utxoinfo *LP_utxopairfind(int32_t iambob,bits256 txid,int32_t vout,bits256 txid2,int32_t vout2) -{ - struct LP_utxoinfo *utxo=0; struct _LP_utxoinfo u; - if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 ) - { - u = (iambob != 0) ? utxo->deposit : utxo->fee; - if (vout2 == u.vout && bits256_cmp(u.txid,txid2) == 0 ) - return(utxo); - } - return(0); -} - -struct LP_utxoinfo *LP_utxofinds(int32_t iambob,bits256 txid,int32_t vout,bits256 txid2,int32_t vout2) -{ - struct LP_utxoinfo *utxo; - if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 || (utxo= LP_utxofind(iambob,txid2,vout2)) != 0 || (utxo= LP_utxo2find(iambob,txid,vout)) != 0 || (utxo= LP_utxo2find(iambob,txid2,vout2)) != 0 ) - return(utxo); - else return(0); -} - -int32_t LP_utxoaddptrs(struct LP_utxoinfo *ptrs[],int32_t n,struct LP_utxoinfo *utxo) -{ - int32_t i; - for (i=0; ipayment.txid,refutxo->payment.vout)) != 0 && utxo != refutxo ) - n = LP_utxoaddptrs(ptrs,n,utxo); - if ( (utxo= _LP_utxo2find(iambob,refutxo->payment.txid,refutxo->payment.vout)) != 0 && utxo != refutxo ) - n = LP_utxoaddptrs(ptrs,n,utxo); - u = (refutxo->iambob != 0) ? refutxo->deposit : refutxo->fee; - if ( (utxo= _LP_utxofind(iambob,u.txid,u.vout)) != 0 && utxo != refutxo ) - n = LP_utxoaddptrs(ptrs,n,utxo); - if ( (utxo= _LP_utxo2find(iambob,u.txid,u.vout)) != 0 && utxo != refutxo ) - n = LP_utxoaddptrs(ptrs,n,utxo); - } - portable_mutex_unlock(&LP_utxomutex); - if ( 0 && n > 0 ) - printf("LP_utxocollisions n.%d\n",n); - return(n); -} - -int32_t _LP_availableset(struct LP_utxoinfo *utxo) -{ - int32_t flag = 0; - if ( utxo != 0 ) - { - if ( bits256_nonz(utxo->S.otherpubkey) != 0 ) - flag = 1, memset(&utxo->S.otherpubkey,0,sizeof(utxo->S.otherpubkey)); - if ( utxo->S.swap != 0 ) - flag = 1, utxo->S.swap = 0; - if ( utxo->T.swappending != 0 ) - flag = 1, utxo->T.swappending = 0; - return(flag); - } - return(0); -} - -void _LP_unavailableset(struct LP_utxoinfo *utxo,bits256 otherpubkey) -{ - if ( utxo != 0 ) - { - utxo->T.swappending = (uint32_t)(time(NULL) + LP_RESERVETIME); - utxo->S.otherpubkey = otherpubkey; - } -} - -void LP_unavailableset(struct LP_utxoinfo *utxo,bits256 otherpubkey) -{ - struct LP_utxoinfo *ptrs[8]; int32_t i,n; struct _LP_utxoinfo u; - memset(ptrs,0,sizeof(ptrs)); - if ( (n= LP_utxocollisions(ptrs,utxo)) > 0 ) - { - for (i=0; iiambob != 0) ? utxo->deposit : utxo->fee; - char str[65],str2[65]; printf("UTXO.[%d] RESERVED %s/v%d %s/v%d collisions.%d\n",utxo->iambob,bits256_str(str,utxo->payment.txid),utxo->payment.vout,bits256_str(str2,u.txid),u.vout,n); - _LP_unavailableset(utxo,otherpubkey); -} - -void LP_availableset(struct LP_utxoinfo *utxo) -{ - struct LP_utxoinfo *ptrs[8]; int32_t i,n,count = 0; struct _LP_utxoinfo u; - if ( utxo != 0 ) - { - memset(ptrs,0,sizeof(ptrs)); - if ( (n= LP_utxocollisions(ptrs,utxo)) > 0 ) - { - for (i=0; i 0 ) - { - u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; - char str[65],str2[65]; printf("UTXO.[%d] AVAIL %s/v%d %s/v%d collisions.%d\n",utxo->iambob,bits256_str(str,utxo->payment.txid),utxo->payment.vout,bits256_str(str2,u.txid),u.vout,n); - } - } -} - -cJSON *LP_inventoryjson(cJSON *item,struct LP_utxoinfo *utxo) -{ - struct _LP_utxoinfo u; - //jaddstr(item,"method","oldutxo"); - if ( utxo == 0 ) - return(item); - if ( utxo->gui[0] != 0 ) - jaddstr(item,"gui",utxo->gui); - jaddstr(item,"coin",utxo->coin); - //jaddnum(item,"now",time(NULL)); - jaddnum(item,"iambob",utxo->iambob); - jaddstr(item,"address",utxo->coinaddr); - jaddbits256(item,"txid",utxo->payment.txid); - jaddnum(item,"vout",utxo->payment.vout); - jadd64bits(item,"value",utxo->payment.value); - jadd64bits(item,"satoshis",utxo->S.satoshis); - u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; - if ( bits256_nonz(u.txid) != 0 ) - { - jaddbits256(item,"txid2",u.txid); - jaddnum(item,"vout2",u.vout); - jadd64bits(item,"value2",u.value); - } - if ( utxo->T.swappending != 0 ) - jaddnum(item,"pending",utxo->T.swappending); - if ( utxo->iambob != 0 ) - { - jaddbits256(item,"srchash",utxo->pubkey);//LP_mypub25519); - if ( bits256_nonz(utxo->S.otherpubkey) != 0 ) - jaddbits256(item,"desthash",utxo->S.otherpubkey); - } - else - { - jaddbits256(item,"desthash",utxo->pubkey);//LP_mypub25519); - if ( bits256_nonz(utxo->S.otherpubkey) != 0 ) - jaddbits256(item,"srchash",utxo->S.otherpubkey); - } - if ( utxo->S.swap != 0 ) - jaddstr(item,"swap","in progress"); - if ( utxo->T.spentflag != 0 ) - jaddnum(item,"spent",utxo->T.spentflag); - jaddnum(item,"session",utxo->T.sessionid); - return(item); -} - -cJSON *LP_utxojson(struct LP_utxoinfo *utxo) -{ - cJSON *item = cJSON_CreateObject(); - item = LP_inventoryjson(item,utxo); - jaddbits256(item,"pubkey",utxo->pubkey); - //jaddnum(item,"profit",utxo->S.profitmargin); - jaddstr(item,"base",utxo->coin); - //jaddstr(item,"script",utxo->spendscript); - return(item); -} - -struct LP_utxoinfo *LP_utxo_bestfit(char *symbol,uint64_t destsatoshis) -{ - uint64_t srcvalue,srcvalue2; struct LP_utxoinfo *utxo,*tmp,*bestutxo = 0; int32_t iambob = 0; - if ( symbol == 0 || destsatoshis == 0 ) - { - printf("LP_utxo_bestfit error symbol.%p %.8f\n",symbol,dstr(destsatoshis)); - return(0); - } - // jl777 remove mempool - HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,tmp) - { - //char str[65]; printf("s%u %d [%.8f vs %.8f] check %s.%s avail.%d ismine.%d >= %d\n",utxo->T.spentflag,LP_iseligible(&srcvalue,&srcvalue2,utxo->iambob,symbol,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,utxo->fee.txid,utxo->fee.vout),dstr(destsatoshis),dstr(utxo->S.satoshis),utxo->coin,bits256_str(str,utxo->payment.txid),LP_isavailable(utxo) > 0,LP_ismine(utxo) > 0,utxo->S.satoshis >= destsatoshis); - if ( strcmp(symbol,utxo->coin) != 0 ) - continue; - if ( LP_isavailable(utxo) > 0 && LP_ismine(utxo) > 0 ) - { - if ( utxo->S.satoshis >= destsatoshis && (bestutxo == 0 || (bestutxo->S.satoshis < destsatoshis && utxo->S.satoshis >= destsatoshis) || (bestutxo->S.satoshis >= destsatoshis && utxo->S.satoshis < bestutxo->S.satoshis)) ) - { - if ( LP_iseligible(&srcvalue,&srcvalue2,utxo->iambob,symbol,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,utxo->fee.txid,utxo->fee.vout) == 0 ) - { - //if ( utxo->T.spentflag == 0 ) - // utxo->T.spentflag = (uint32_t)time(NULL); - continue; - } - bestutxo = utxo; - } //else printf("skip alice utxo %.8f vs dest %.8f\n",dstr(utxo->S.satoshis),dstr(destsatoshis)); - } - } - return(bestutxo); -} - -void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector) -{ - if ( utxo == 0 ) - return; - utxo->T.spentflag = (uint32_t)time(NULL); -} - -struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t vout,int64_t value,bits256 txid2,int32_t vout2,int64_t value2,char *coinaddr,bits256 pubkey,char *gui,uint32_t sessionid) -{ - uint64_t val,val2=0,tmpsatoshis,txfee; int32_t spendvini,numconfirms,selector; bits256 spendtxid; struct iguana_info *coin; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo = 0; - if ( symbol == 0 || symbol[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 || vout < 0 || vout2 < 0 || value <= 0 || value2 <= 0 )//|| sessionid == 0 ) - { - char str[65],str2[65]; printf("REJECT %s iambob.%d %s utxoadd.(%.8f %.8f) %s/v%d %s/v%d\n",coinaddr,iambob,symbol,dstr(value),dstr(value2),bits256_str(str,txid),vout,bits256_str(str2,txid2),vout2); - printf("session.%u addutxo %d %d %d %d %d %d %d %d\n",sessionid,symbol == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(txid2) == 0,vout < 0,vout2 < 0,value <= 0,value2 <= 0); - return(0); - } - if ( (coin= LP_coinfind(symbol)) == 0 || (IAMLP == 0 && coin->inactive != 0) ) - { - //printf("LP_utxoadd reject inactive %s\n",symbol); - return(0); - } - txfee = LP_txfeecalc(coin,0,0); - if ( iambob != 0 && value2 < 9 * (value >> 3) + 2*txfee ) // big txfee padding - { - if ( value2 > 2*txfee ) - tmpsatoshis = (((value2 - 2*txfee) / 9) << 3); - else - { - printf("value2 %.8f <= 2 * %.8f\n",dstr(value2),dstr(txfee)); - return(0); - } - } else tmpsatoshis = (value - txfee); - char str[65],str2[65],dispflag = 0;//(iambob == 0); - if ( iambob == 0 && bits256_cmp(pubkey,G.LP_mypub25519) != 0 ) - { - printf("trying to add Alice utxo when not mine? %s/v%d\n",bits256_str(str,txid),vout); - return(0); - } - if ( coin->inactive == 0 ) - { - if ( LP_iseligible(&val,&val2,iambob,symbol,txid,vout,tmpsatoshis,txid2,vout2) <= 0 ) - { - static uint32_t counter; - if ( counter++ < 3 ) - printf("iambob.%d utxoadd %s inactive.%u got ineligible txid value %.8f:%.8f, value2 %.8f:%.8f, tmpsatoshis %.8f\n",iambob,symbol,coin->inactive,dstr(value),dstr(val),dstr(value2),dstr(val2),dstr(tmpsatoshis)); - return(0); - } - if ( (numconfirms= LP_numconfirms(symbol,coinaddr,txid,vout,0)) <= 0 ) - { - printf("LP_utxoadd reject numconfirms.%d %s.%s\n",numconfirms,symbol,bits256_str(str,txid)); - return(0); - } - if ( (numconfirms= LP_numconfirms(symbol,coinaddr,txid2,vout2,0)) <= 0 ) - { - printf("LP_utxoadd reject2 numconfirms.%d %s %s/v%d\n",numconfirms,symbol,bits256_str(str,txid2),vout2); - return(0); - } - } - else - { - val = value; - val2 = value2; - } - dispflag = 0; - if ( dispflag != 0 ) - printf("%.8f %.8f %s iambob.%d %s utxoadd.(%.8f %.8f) %s %s\n",dstr(val),dstr(val2),coinaddr,iambob,symbol,dstr(value),dstr(value2),bits256_str(str,txid),bits256_str(str2,txid2)); - dispflag = 1; - if ( (utxo= LP_utxofinds(iambob,txid,vout,txid2,vout2)) != 0 ) - { - if ( 0 && LP_ismine(utxo) == 0 ) - { - char str2[65],str3[65]; printf("iambob.%d %s %s utxoadd.(%.8f %.8f) %s %s\n",iambob,bits256_str(str3,pubkey),symbol,dstr(value),dstr(value2),bits256_str(str,txid),bits256_str(str2,txid2)); - printf("duplicate %.8f %.8f %.8f vs utxo.(%.8f %.8f %.8f)\n",dstr(value),dstr(value2),dstr(tmpsatoshis),dstr(utxo->payment.value),dstr(utxo->deposit.value),dstr(utxo->S.satoshis)); - } - u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; - if ( bits256_cmp(txid,utxo->payment.txid) != 0 || bits256_cmp(txid2,u.txid) != 0 || vout != utxo->payment.vout || value != utxo->payment.value || tmpsatoshis != utxo->S.satoshis || vout2 != u.vout || value2 != u.value || strcmp(symbol,utxo->coin) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || bits256_cmp(pubkey,utxo->pubkey) != 0 ) - { - utxo->T.errors++; - char str[65],str2[65],str3[65],str4[65],str5[65],str6[65]; - if ( utxo->T.spentflag != 0 || LP_txvalue(0,utxo->coin,utxo->payment.txid,utxo->payment.vout) < utxo->payment.value || LP_txvalue(0,utxo->coin,u.txid,u.vout) < u.value ) - { - //if ( utxo->T.spentflag == 0 ) - // utxo->T.spentflag = (uint32_t)time(NULL); - printf("original utxo pair not valid\n"); - if ( dispflag != 0 ) - printf("error on subsequent utxo iambob.%d %.8f %.8f add.(%s %s) when.(%s %s) %d %d %d %d %d %d %d %d %d %d pubkeys.(%s vs %s)\n",iambob,dstr(val),dstr(val2),bits256_str(str,txid),bits256_str(str2,txid2),bits256_str(str3,utxo->payment.txid),bits256_str(str4,utxo->deposit.txid),bits256_cmp(txid,utxo->payment.txid) != 0,bits256_cmp(txid2,u.txid) != 0,vout != utxo->payment.vout,tmpsatoshis != utxo->S.satoshis,vout2 != u.vout,value2 != u.value,strcmp(symbol,utxo->coin) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,bits256_cmp(pubkey,utxo->pubkey) != 0,value != utxo->payment.value,bits256_str(str5,pubkey),bits256_str(str6,utxo->pubkey)); - utxo = 0; - } - } - if ( utxo != 0 ) - { - if ( utxo->T.sessionid == 0 ) - utxo->T.sessionid = sessionid; - //else if ( profitmargin > SMALLVAL ) - // utxo->S.profitmargin = profitmargin; - utxo->T.lasttime = (uint32_t)time(NULL); - //printf("return existing utxo[%d] %s %s\n",iambob,bits256_str(str,utxo->payment.txid),bits256_str(str2,iambob != 0 ? utxo->deposit.txid : utxo->fee.txid)); - return(utxo); - } - } - utxo = calloc(1,sizeof(*utxo)); - //utxo->S.profitmargin = profitmargin; - utxo->pubkey = pubkey; - safecopy(utxo->gui,gui,sizeof(utxo->gui)); - safecopy(utxo->coin,symbol,sizeof(utxo->coin)); - safecopy(utxo->coinaddr,coinaddr,sizeof(utxo->coinaddr)); - //safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript)); - utxo->payment.txid = txid; - utxo->payment.vout = vout; - utxo->payment.value = value; - utxo->S.satoshis = tmpsatoshis; - if ( (utxo->iambob= iambob) != 0 ) - { - utxo->deposit.txid = txid2; - utxo->deposit.vout = vout2; - utxo->deposit.value = value2; - } - else - { - utxo->fee.txid = txid2; - utxo->fee.vout = vout2; - utxo->fee.value = value2; - } - LP_utxosetkey(utxo->key,txid,vout); - LP_utxosetkey(utxo->key2,txid2,vout2); - if ( LP_ismine(utxo) > 0 ) - utxo->T.sessionid = G.LP_sessionid; - else utxo->T.sessionid = sessionid; - if ( coin->inactive == 0 && (selector= LP_mempool_vinscan(&spendtxid,&spendvini,symbol,coinaddr,txid,vout,txid2,vout2)) >= 0 ) - { - printf("utxoadd selector.%d spent in mempool %s vini.%d",selector,bits256_str(str,spendtxid),spendvini); - utxo->T.spentflag = (uint32_t)time(NULL); - } - //printf(" %s %.8f %.8f %p addutxo.%d (%s %s) session.%u iambob.%d <<<<<<<<<<<<<<<\n",symbol,dstr(value),dstr(value2),utxo,LP_ismine(utxo) > 0,bits256_str(str,utxo->payment.txid),bits256_str(str2,iambob != 0 ? utxo->deposit.txid : utxo->fee.txid),utxo->T.sessionid,iambob); - portable_mutex_lock(&LP_utxomutex); - HASH_ADD_KEYPTR(hh,G.LP_utxoinfos[iambob],utxo->key,sizeof(utxo->key),utxo); - if ( _LP_utxo2find(iambob,txid2,vout2) == 0 ) - HASH_ADD_KEYPTR(hh2,G.LP_utxoinfos2[iambob],utxo->key2,sizeof(utxo->key2),utxo); - portable_mutex_unlock(&LP_utxomutex); - if ( iambob != 0 ) - { - if ( LP_ismine(utxo) > 0 ) - { - //LP_utxo_clientpublish(utxo); - if ( LP_mypeer != 0 ) - utxo->T.lasttime = (uint32_t)time(NULL); - } - } - return(utxo); -} - -cJSON *LP_inventory(char *symbol) -{ - struct LP_utxoinfo *utxo,*tmp; struct _LP_utxoinfo u; char *myipaddr; cJSON *array; uint64_t val,val2; int32_t iambob = 0; struct iguana_info *coin; - array = cJSON_CreateArray(); - if ( LP_mypeer != 0 ) - myipaddr = LP_mypeer->ipaddr; - else myipaddr = "127.0.0.1"; - if ( (coin= LP_coinfind(symbol)) != 0 ) - LP_listunspent_both(symbol,coin->smartaddr,0); - HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,tmp) - { - char str[65]; - //printf("iambob.%d iterate %s\n",iambob,bits256_str(str,LP_mypub25519)); - if ( LP_isunspent(utxo) != 0 && strcmp(symbol,utxo->coin) == 0 && utxo->iambob == iambob && LP_ismine(utxo) > 0 ) - { - u = (iambob != 0) ? utxo->deposit : utxo->fee; - if ( LP_iseligible(&val,&val2,iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,u.txid,u.vout) == 0 ) - { - //if ( utxo->T.spentflag == 0 ) - // utxo->T.spentflag = (uint32_t)time(NULL); - printf("%s %s ineligible %.8f %.8f\n",utxo->coin,bits256_str(str,u.txid),dstr(val),dstr(val2)); - continue; - } - //if ( iambob != 0 ) - // LP_utxo_clientpublish(utxo); - jaddi(array,LP_inventoryjson(cJSON_CreateObject(),utxo)); - } - else if ( 0 && LP_ismine(utxo) > 0 && strcmp(symbol,utxo->coin) == 0 ) - printf("skip %s %s %d %d %d %d\n",utxo->coin,bits256_str(str,utxo->payment.txid),LP_isunspent(utxo) != 0,strcmp(symbol,utxo->coin) == 0,utxo->iambob == iambob,LP_ismine(utxo) > 0); - } - return(array); -} - -int32_t LP_maxvalue(uint64_t *values,int32_t n) -{ - int32_t i,maxi = -1; uint64_t maxval = 0; - for (i=0; i maxval ) - { - maxi = i; - maxval = values[i]; - } - return(maxi); -} - -int32_t LP_nearestvalue(int32_t iambob,uint64_t *values,int32_t n,uint64_t targetval) -{ - int32_t i,mini = -1; int64_t dist; uint64_t mindist = (1 << 31); - for (i=0; i= 0 && dist < mindist ) - { - mini = i; - mindist = dist; - } - } - return(mini); -} - -int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 myprivkey,bits256 mypub) -{ - int32_t enable_utxos = 0; - char *script,destaddr[64]; struct LP_utxoinfo *utxo; cJSON *array,*item; bits256 txid,deposittxid; int32_t used,i,flag=0,height,n,cmpflag,iambob,vout,depositvout; uint64_t *values=0,satoshis,txfee,depositval,value,total = 0; int64_t targetval; - if ( coin == 0 || (IAMLP == 0 && coin->inactive != 0) ) - { - //printf("coin not active\n"); - return(0); - } - //printf("privkey init.(%s) %s\n",coin->symbol,coin->smartaddr); - if ( coin->inactive == 0 ) - LP_listunspent_issue(coin->symbol,coin->smartaddr,0); - LP_address(coin,coin->smartaddr); - if ( coin->inactive == 0 && (array= LP_listunspent(coin->symbol,coin->smartaddr)) != 0 ) - { - txfee = LP_txfeecalc(coin,0,0); - if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) - { - //printf("LP_privkey_init %s %s\n",coin->symbol,jprint(array,0)); - for (iambob=0; iambob<=1; iambob++) - { - if ( iambob == 0 ) - values = calloc(n,sizeof(*values)); - else memset(values,0,n * sizeof(*values)); - used = 0; - for (i=0; ielectrum == 0 ) - { - txid = jbits256(item,"txid"); - vout = juint(item,"vout"); - value = LP_value_extract(item,0); - height = LP_txheight(coin,txid);//LP_getheight(coin) - jint(item,"confirmations") + 1; - } - else - { - txid = jbits256(item,"tx_hash"); - vout = juint(item,"tx_pos"); - value = j64bits(item,"value"); - height = jint(item,"height"); - } - satoshis = LP_txvalue(destaddr,coin->symbol,txid,vout); - if ( satoshis != 0 && satoshis != value ) - printf("%s %s unexpected privkey_init value mismatch %.8f vs %.8f (%s) %.8f %.8f\n",coin->symbol,coin->smartaddr,dstr(satoshis),dstr(value),jprint(item,0),jdouble(item,"amount"),jdouble(item,"interest")); - if ( LP_inventory_prevent(iambob,coin->symbol,txid,vout) == 0 && height > 0 ) - { - //printf("%s\n",jprint(item,0)); - values[i] = satoshis; - //flag += LP_address_utxoadd(coin,destaddr,txid,vout,satoshis,height,-1); - } else used++; - } - //printf("array.%d\n",n); - while ( used < n-1 ) - { - //for (i=0; i= 0 ) - { - item = jitem(array,i); - if ( coin->electrum == 0 ) - { - deposittxid = jbits256(item,"txid"); - depositvout = juint(item,"vout"); - script = jstr(item,"scriptPubKey"); - } - else - { - deposittxid = jbits256(item,"tx_hash"); - depositvout = juint(item,"tx_pos"); - script = coin->smartaddr; - } - depositval = values[i]; - values[i] = 0, used++; - if ( iambob == 0 ) - targetval = (depositval / 776) + txfee; - else targetval = (depositval / 9) * 8 + 2*txfee; - if ( targetval < txfee*2 ) - targetval = txfee*2; - //printf("iambob.%d i.%d deposit %.8f min %.8f target %.8f\n",iambob,i,dstr(depositval),dstr((1+LP_MINSIZE_TXFEEMULT)*txfee),dstr(targetval)); - if ( depositval < (1+LP_MINSIZE_TXFEEMULT)*txfee ) - continue; - i = -1; - if ( iambob != 0 ) - { - if ( (i= LP_nearestvalue(iambob,values,n,targetval)) < 0 ) - targetval /= 4; - if ( targetval < txfee*(1+LP_MINSIZE_TXFEEMULT) ) - continue; - } - if ( i >= 0 || (i= LP_nearestvalue(iambob,values,n,targetval)) >= 0 ) - { - //printf("iambob.%d i.%d %.8f target %.8f\n",iambob,i,dstr(depositval),dstr(targetval)); - item = jitem(array,i); - cmpflag = 0; - if ( coin->electrum == 0 ) - { - txid = jbits256(item,"txid"); - vout = juint(item,"vout"); - if ( jstr(item,"scriptPubKey") != 0 && strcmp(script,jstr(item,"scriptPubKey")) == 0 ) - cmpflag = 1; - } - else - { - txid = jbits256(item,"tx_hash"); - vout = juint(item,"tx_pos"); - cmpflag = 1; - } - if ( cmpflag != 0 ) - { - value = values[i]; - values[i] = 0, used++; - portable_mutex_lock(&LP_UTXOmutex); - if ( iambob != 0 ) - { - if ( (utxo= LP_utxoadd(1,coin->symbol,txid,vout,value,deposittxid,depositvout,depositval,coin->smartaddr,mypub,LP_gui,G.LP_sessionid)) != 0 ) - { - } - } - else - { - //printf("call utxoadd\n"); - if ( (utxo= LP_utxoadd(0,coin->symbol,deposittxid,depositvout,depositval,txid,vout,value,coin->smartaddr,mypub,LP_gui,G.LP_sessionid)) != 0 ) - { - } - } - portable_mutex_unlock(&LP_UTXOmutex); - total += value; - } // else printf("scriptmismatch.(%s) vs %s\n",script,jprint(item,0)); - } //else printf("nothing near i.%d\n",i); - } else break; - } - if ( enable_utxos == 0 ) - break; - } - } - free_json(array); - if ( flag != 0 ) - LP_postutxos(coin->symbol,coin->smartaddr); - } - if ( values != 0 ) - free(values); - //printf("privkey.%s %.8f\n",symbol,dstr(total)); - return(flag); -} - -char *LP_secretaddresses(void *ctx,char *prefix,char *passphrase,int32_t n,uint8_t taddr,uint8_t pubtype) -{ - int32_t i; uint8_t tmptype,pubkey33[33],rmd160[20]; char output[777*45],str[65],str2[65],buf[8192],wifstr[128],coinaddr[64]; bits256 checkprivkey,privkey,pubkey; cJSON *retjson; - retjson = cJSON_CreateObject(); - if ( prefix == 0 || prefix[0] == 0 ) - prefix = "secretaddress"; - if ( passphrase == 0 || passphrase[0] == 0 ) - passphrase = "password"; - if ( n <= 0 ) - n = 16; - else if ( n > 777 ) - n = 777; - conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); - bitcoin_priv2pub(ctx,pubkey33,coinaddr,privkey,taddr,pubtype); - printf("generator (%s) secrets.[%d] <%s> t.%u p.%u\n",coinaddr,n,passphrase,taddr,pubtype); - sprintf(output,"\"addresses\":["); - for (i=0; i %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); - if ( 0 ) - { - char str[65],str2[65]; - checkkey = iguana_wif2privkey(wifstr); - if ( bits256_cmp(checkkey,privkey) != 0 ) - printf("WIF.(%s) -> %s or %s?\n",wifstr,bits256_str(str,privkey),bits256_str(str2,checkkey)); - } - } - privkey.bytes[0] &= 248, privkey.bytes[31] &= 127, privkey.bytes[31] |= 64; - bitcoin_priv2pub(ctx,coin->pubkey33,coin->smartaddr,privkey,coin->taddr,coin->pubtype); - if ( coin->counter == 0 ) - { - coin->counter++; - memcpy(G.LP_pubsecp,coin->pubkey33,33); - bitcoin_priv2wif(coin->wiftaddr,tmpstr,privkey,coin->wiftype); - bitcoin_addr2rmd160(coin->taddr,&tmptype,G.LP_myrmd160,coin->smartaddr); - LP_privkeyadd(privkey,G.LP_myrmd160); - G.LP_privkey = privkey; - if ( 0 && (coin->pubtype != 60 || strcmp(coin->symbol,"KMD") == 0) ) - printf("%s (%s) %d wif.(%s) (%s)\n",coin->symbol,coin->smartaddr,coin->pubtype,tmpstr,passphrase); - if ( G.counter++ == 0 ) - { - bitcoin_priv2wif(coin->wiftaddr,G.USERPASS_WIFSTR,privkey,188); - bitcoin_wif2priv(coin->wiftaddr,&tmptype,&checkkey,G.USERPASS_WIFSTR); - if ( bits256_cmp(checkkey,privkey) != 0 ) - { - char str[65],str2[65]; - printf("FATAL ERROR converting USERPASS_WIFSTR %s -> %s != %s\n",G.USERPASS_WIFSTR,bits256_str(str,checkkey),bits256_str(str2,privkey)); - exit(-1); - } - conv_NXTpassword(userpass.bytes,pubkeyp->bytes,(uint8_t *)G.USERPASS_WIFSTR,(int32_t)strlen(G.USERPASS_WIFSTR)); - userpub = curve25519(userpass,curve25519_basepoint9()); - printf("userpass.(%s)\n",bits256_str(G.USERPASS,userpub)); - } - if ( coin->electrum == 0 && coin->userpass[0] != 0 ) - { - LP_listunspent_issue(coin->symbol,coin->smartaddr,0); - if ( (retjson= LP_importprivkey(coin->symbol,tmpstr,coin->smartaddr,-1)) != 0 ) - { - if ( jobj(retjson,"error") != 0 ) - { - printf("cant importprivkey.%s -> (%s), abort session\n",coin->symbol,jprint(retjson,1)); - exit(-1); - } - } else free_json(retjson); - } - } - vcalc_sha256(0,checkkey.bytes,privkey.bytes,sizeof(privkey)); - checkkey.bytes[0] &= 248, checkkey.bytes[31] &= 127, checkkey.bytes[31] |= 64; - G.LP_mypub25519 = *pubkeyp = curve25519(checkkey,curve25519_basepoint9()); - G.LP_mypriv25519 = checkkey; - LP_pubkeyadd(G.LP_mypub25519); - return(privkey); -} - -void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase) -{ - struct iguana_info *coin,*tmp; bits256 pubkey,privkey; uint8_t pubkey33[33]; int32_t initonly; - initonly = (passphrase != 0); - memset(privkey.bytes,0,sizeof(privkey)); - memset(pubkey.bytes,0,sizeof(pubkey)); - //printf("Total coins: %d\n", HASH_COUNT(LP_coins)); - //int num_iter = 0; - HASH_ITER(hh,LP_coins,coin,tmp) - { - //printf("LP_privkey_updates [%02d / %02d]\n", num_iter++, HASH_COUNT(LP_coins)); - if ( initonly != 0 ) - { - coin->counter = 0; - memset(coin->smartaddr,0,sizeof(coin->smartaddr)); - if ( bits256_nonz(privkey) == 0 || coin->smartaddr[0] == 0 ) - privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,coin,passphrase,""); - } - //printf("i.%d of %d\n",i,LP_numcoins); - else if ( IAMLP == 0 || coin->inactive == 0 ) - { - //printf("from updates %s\n",coin->symbol); - if ( LP_privkey_init(pubsock,coin,G.LP_privkey,G.LP_mypub25519) == 0 && (rand() % 10) == 0 ) - LP_postutxos(coin->symbol,coin->smartaddr); - } - } -} - -int32_t LP_passphrase_init(char *passphrase,char *gui) -{ - static void *ctx; int32_t iambob,counter; struct LP_utxoinfo *utxo,*tmp; - if ( ctx == 0 ) - ctx = bitcoin_ctx(); - if ( G.LP_pendingswaps != 0 ) - return(-1); - G.initializing = 1; - if ( gui == 0 ) - gui = "cli"; - counter = G.USERPASS_COUNTER; - while ( G.waiting == 0 ) - { - printf("waiting for G.waiting\n"); - sleep(5); - } - for (iambob=0; iambob<2; iambob++) - { - if ( G.LP_utxoinfos[iambob] != 0 ) - { - HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,tmp) - { - HASH_DELETE(hh,G.LP_utxoinfos[iambob],utxo); - //free(utxo); - } - } - if ( G.LP_utxoinfos2[iambob] != 0 ) - { - G.LP_utxoinfos2[iambob] = 0; - /*HASH_ITER(hh,G.LP_utxoinfos2[iambob],utxo,tmp) - { - HASH_DELETE(hh,G.LP_utxoinfos2[iambob],utxo); - free(utxo); - }*/ - } - } - memset(&G,0,sizeof(G)); - LP_privkey_updates(ctx,LP_mypubsock,passphrase); - init_hexbytes_noT(G.LP_myrmd160str,G.LP_myrmd160,20); - G.LP_sessionid = (uint32_t)time(NULL); - safecopy(G.gui,gui,sizeof(G.gui)); - G.USERPASS_COUNTER = counter; - return(0); -} - - diff --git a/iguana/exchanges/Makefile b/iguana/exchanges/Makefile index a77a5405f..be75a297c 100644 --- a/iguana/exchanges/Makefile +++ b/iguana/exchanges/Makefile @@ -1,10 +1,15 @@ #cd .. - #emcc -s ASSERTIONS=1 -s ASYNCIFY=1 -s TOTAL_MEMORY=134217728 --preload-file coins.json -D__PNACL -DFROM_JS -O2 -I../includes -I../crypto777 -s PTHREAD_POOL_SIZE=8 -s USE_PTHREADS=1 -o /var/www/html/index.html exchanges/mm.c $(CRYPTO777_SRCS) mini-gmp.c secp256k1/src/secp256k1.c -lm -lc #include ../crypto777/crypto777.sources #emcc -s ASSERTIONS=1 -s ASYNCIFY=1 -s TOTAL_MEMORY=134217728 --preload-file coins.json -D__PNACL -DFROM_JS -O2 -I../includes -I../crypto777 -o /var/www/html/index.html exchanges/mm.c $(CRYPTO777_SRCS) mini-gmp.c secp256k1/src/secp256k1.c -lm -lc +#emcc -s WASM=1 -s EXPORTED_FUNCTIONS="['_main', '_barterDEX']" -s ABORTING_MALLOC=0 -s ASSERTIONS=1 -s ASYNCIFY=1 -s TOTAL_MEMORY=167772160 --embed-file coins.json -DFROM_JS -O2 -I../includes -I../crypto777 -o /var/www/html/index.html exchanges/mm.c ../crypto777/*.c ../crypto777/jpeg/*.c ../crypto777/jpeg/unix/*.c mini-gmp.c secp256k1/src/secp256k1.c -lm + +#emcc -s WASM=1 -s EXPORTED_FUNCTIONS="['_barterDEX', '_main']" -s ABORTING_MALLOC=0 -s ASSERTIONS=1 -s ASYNCIFY=1 -s TOTAL_MEMORY=167772160 --embed-file coins.json -DFROM_JS -I../includes -I../crypto777 -o /var/www/html/index.hmtl exchanges/mm.c ../crypto777/*.c ../crypto777/jpeg/*.c ../crypto777/jpeg/unix/*.c mini-gmp.c secp256k1/src/secp256k1.c -lm + +#emcc -s EXPORTED_FUNCTIONS="['_main', '_barterDEX']" -s ABORTING_MALLOC=0 -s ASSERTIONS=1 -s ASYNCIFY=1 -s TOTAL_MEMORY=167772160 --embed-file coins.json -DFROM_JS -I../includes -I../crypto777 -o /var/www/html/barterDEX.js exchanges/barterDEX.c + all: - emcc -s PTHREAD_POOL_SIZE=8 -s USE_PTHREADS=1 -s ABORTING_MALLOC=0 -s ASSERTIONS=1 -s ASYNCIFY=1 -s TOTAL_MEMORY=536870912 --preload-file coins.json -DFROM_JS -O2 -I../includes -I../crypto777 -s PTHREAD_POOL_SIZE=8 -s USE_PTHREADS=1 -o /var/www/html/index.html exchanges/mm.c ../crypto777/*.c ../crypto777/jpeg/*.c ../crypto777/jpeg/unix/*.c mini-gmp.c secp256k1/src/secp256k1.c -lm -lpthread + emcc -s WASM=1 -s EXPORTED_FUNCTIONS="['_main', '_barterDEX']" -s ABORTING_MALLOC=0 -s ASSERTIONS=1 -s ASYNCIFY=1 -s TOTAL_MEMORY=167772160 --embed-file coins.json -DFROM_JS -O2 -I../includes -I../crypto777 -o /var/www/html/index.html exchanges/mm.c ../crypto777/*.c ../crypto777/jpeg/*.c ../crypto777/jpeg/unix/*.c mini-gmp.c secp256k1/src/secp256k1.c -lm diff --git a/iguana/exchanges/auto_chipsbtc b/iguana/exchanges/auto_chipsbtc new file mode 100755 index 000000000..c45fffe5d --- /dev/null +++ b/iguana/exchanges/auto_chipsbtc @@ -0,0 +1,2 @@ +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"CHIPS\",\"rel\":\"BTC\",\"margin\":0.01,\"refbase\":\"chips\",\"refrel\":\"coinmarketcap\"}" diff --git a/iguana/exchanges/auto_chipskmd b/iguana/exchanges/auto_chipskmd new file mode 100755 index 000000000..10f7874c0 --- /dev/null +++ b/iguana/exchanges/auto_chipskmd @@ -0,0 +1,2 @@ +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"CHIPS\",\"rel\":\"KMD\",\"margin\":0.01,\"refbase\":\"chips\",\"refrel\":\"coinmarketcap\"}" diff --git a/iguana/exchanges/balances b/iguana/exchanges/balances new file mode 100755 index 000000000..1eb527b8f --- /dev/null +++ b/iguana/exchanges/balances @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"balances\"}" 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/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/bots b/iguana/exchanges/bots new file mode 100755 index 000000000..b64e65088 --- /dev/null +++ b/iguana/exchanges/bots @@ -0,0 +1,4 @@ +#!/bin/bash +source userpass +# this will only work for watchonly addresses that have been rescanned and with active coins +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RNdqHx26GWy9bk8MtmH1UiXjQcXE4RKK2P\",\"divisor\":1000000}" diff --git a/iguana/exchanges/claim b/iguana/exchanges/claim new file mode 100755 index 000000000..85cd18c15 --- /dev/null +++ b/iguana/exchanges/claim @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"instantdex_claim\"}" diff --git a/iguana/exchanges/coins b/iguana/exchanges/coins index 60511920f..ce0c36849 100644 --- a/iguana/exchanges/coins +++ b/iguana/exchanges/coins @@ -1,4 +1,4 @@ -export coins="[{\"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}]" +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\":\"MSHARK\",\"asset\":\"MSHARK\",\"rpcport\":8846}, {\"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 index cadc82f08..ea25d7c8b 100644 --- a/iguana/exchanges/coins.json +++ b/iguana/exchanges/coins.json @@ -1,2 +1,4 @@ -[{\"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\":\"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\":\"MSHARK\",\"asset\":\"MSHARK\",\"rpcport\":8846}, {\"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/deposit1 b/iguana/exchanges/deposit1 new file mode 100755 index 000000000..9b2e411b7 --- /dev/null +++ b/iguana/exchanges/deposit1 @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"instantdex_deposit\",\"weeks\":1,\"amount\":10.0,\"broadcast\":1}" diff --git a/iguana/exchanges/deposit10 b/iguana/exchanges/deposit10 new file mode 100755 index 000000000..f0ba9bcf7 --- /dev/null +++ b/iguana/exchanges/deposit10 @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"instantdex_deposit\",\"weeks\":10,\"amount\":10.0,\"broadcast\":1}" diff --git a/iguana/exchanges/dex b/iguana/exchanges/dex new file mode 100755 index 000000000..721768833 --- /dev/null +++ b/iguana/exchanges/dex @@ -0,0 +1,4 @@ +#!/bin/bash +source userpass +# this will only work for watchonly addresses that have been rescanned and with active coins +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf\",\"divisor\":1000000}" diff --git a/iguana/exchanges/dynamictrust b/iguana/exchanges/dynamictrust new file mode 100755 index 000000000..0a22e9fd9 --- /dev/null +++ b/iguana/exchanges/dynamictrust @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"dynamictrust\",\"address\":\"RMfQwu5ey23eWJ4as2ckd8dqsQJwo836ny\"}" diff --git a/iguana/exchanges/enable b/iguana/exchanges/enable index 90b006dfe..eb53f31d6 100755 --- a/iguana/exchanges/enable +++ b/iguana/exchanges/enable @@ -1,5 +1,15 @@ #!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"REVS\"}" -curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"CHIPS\"}" -curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"MNZ\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"KMD\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"BTC\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"SUPERNET\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"CRYPTO\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"DEX\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"BOTS\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"BET\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"HODL\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"MSHARK\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"MGW\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"PANGEA\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"JUMBLR\"}" diff --git a/iguana/exchanges/fundvalue b/iguana/exchanges/fundvalue new file mode 100755 index 000000000..3e46662f6 --- /dev/null +++ b/iguana/exchanges/fundvalue @@ -0,0 +1,4 @@ +#!/bin/bash +source userpass +# this will only work for watchonly addresses that have been rescanned and with active coins +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":13000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":10000}, {\"coin\":\"syscoin\",\"balance\":20000000}, {\"coin\":\"waves\",\"balance\":700000}, {\"coin\":\"bitcoin\",\"balance\":625}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":375000}, {\"coin\":\"chips\",\"balance\":2577006 }, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }],\"divisor\":650000}" diff --git a/iguana/exchanges/hodl b/iguana/exchanges/hodl new file mode 100755 index 000000000..b70cf5456 --- /dev/null +++ b/iguana/exchanges/hodl @@ -0,0 +1,4 @@ +#!/bin/bash +source userpass +# this will only work for watchonly addresses that have been rescanned and with active coins +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RNcUaMUEFLxVwtTo7rgruhwYanGk1jTkeU\",\"holdings\":[{\"coin\":\"siacoin\",\"balance\":185000000,\"comment\":\"using siafunds equal to million siacoin\"}],\"divisor\":10000000}" diff --git a/iguana/exchanges/install b/iguana/exchanges/install index 4ec27cffc..cbf46ca5f 100755 --- a/iguana/exchanges/install +++ b/iguana/exchanges/install @@ -1,5 +1,5 @@ #!/bin/bash -cp guistats pubkeystats pendings coinswaps baserelswaps setpassphrase notarizations getrawtransaction parselog statsdisp m_js trust trusted setconfirms balance listunspent electrum snapshot_balance snapshot_loop secretaddresses dividends snapshot goals goal portfolio autoprice deletemessages getmessages debug buy sell bestfit orderbook client run_osx client_osx run coins disable enable myprice myprices getcoins getpeers getpeersIP getprices help inv setprice status ../dexscripts +cp auto_chipskmd auto_chipsbtc pendingswaps fundvalue balances dynamictrust getcoin kickstart tradesarray claim deposit10 deposit1 invreset sendrawtransaction processfiles stop millis mnzservers bot_buy bot_list bot_statuslist bot_pause bot_resume bot_sell bot_settings bot_status bot_stop guistats pubkeystats pendings coinswaps baserelswaps setpassphrase notarizations getrawtransaction parselog statsdisp m_js trust trusted setconfirms balance listunspent electrum snapshot_balance snapshot_loop secretaddresses dividends snapshot goals goal portfolio autoprice deletemessages getmessages debug buy sell bestfit orderbook client run_osx client_osx run coins disable enable myprice myprices getcoins getpeers getpeersIP getprices help inv setprice status ../dexscripts cp coins.json .. cd ../dexscripts #cp ../exchanges/passphrase ../exchanges/userpass . 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/jumblr b/iguana/exchanges/jumblr new file mode 100755 index 000000000..501a99333 --- /dev/null +++ b/iguana/exchanges/jumblr @@ -0,0 +1,4 @@ +#!/bin/bash +source userpass +# this will only work for watchonly addresses that have been rescanned and with active coins +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RGhxXpXSSBTBm9EvNsXnTQczthMCxHX91t\",\"divisor\":1000000}" diff --git a/iguana/exchanges/kickstart b/iguana/exchanges/kickstart new file mode 100755 index 000000000..46e353ee2 --- /dev/null +++ b/iguana/exchanges/kickstart @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"KMD\",\"ipaddr\":\"\",\"port\":0}" 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 7477b00ab..5382b33c3 100644 --- a/iguana/exchanges/mm.c +++ b/iguana/exchanges/mm.c @@ -19,11 +19,13 @@ // Copyright © 2017 SuperNET. All rights reserved. // + void PNACL_message(char *arg,...) { } #define FROM_MARKETMAKER + #include #include #ifndef NATIVE_WINDOWS @@ -32,7 +34,7 @@ void PNACL_message(char *arg,...) #include "../../crypto777/OS_portable.h" #endif // !_WIN_32 - +uint32_t DOCKERFLAG; #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" @@ -74,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; @@ -415,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 ) { @@ -804,62 +806,6 @@ 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; uint16_t port; cJSON *argjson = ptr; @@ -869,7 +815,7 @@ void LP_main(void *ptr) LP_profitratio += profitmargin; if ( (port= juint(argjson,"rpcport")) < 1000 ) port = LP_RPCPORT; - LPinit(port,LP_RPCPORT+1,LP_RPCPORT+2,LP_RPCPORT+3,passphrase,jint(argjson,"client"),jstr(argjson,"userhome"),argjson); + LPinit(port,LP_RPCPORT+10,LP_RPCPORT+20,LP_RPCPORT+30,passphrase,jint(argjson,"client"),jstr(argjson,"userhome"),argjson); } } @@ -878,16 +824,32 @@ int main(int argc, const char * argv[]) 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; - if ( argc == 1 ) + OS_init(); + if ( strstr(argv[0],"btc2kmd") != 0 && argv[1] != 0 ) { - LP_NXT_redeems(); - sleep(3); - return(0); + uint8_t addrtype,rmd160[20],rmd160b[20]; char coinaddr[64],coinaddr2[64]; + bitcoin_addr2rmd160(0,&addrtype,rmd160,(char *)argv[1]); + if ( addrtype == 0 ) + { + bitcoin_address(coinaddr,0,60,rmd160,20); + bitcoin_addr2rmd160(0,&addrtype,rmd160b,coinaddr); + bitcoin_address(coinaddr2,0,0,rmd160b,20); + } + else if ( addrtype == 60 ) + { + bitcoin_address(coinaddr,0,0,rmd160,20); + bitcoin_addr2rmd160(0,&addrtype,rmd160b,coinaddr); + bitcoin_address(coinaddr2,0,60,rmd160b,20); + } + printf("(%s) -> %s -> %s\n",(char *)argv[1],coinaddr,coinaddr2); + if ( strcmp((char *)argv[1],coinaddr2) != 0 ) + printf("ERROR\n"); + exit(0); } - 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\"}"); @@ -895,8 +857,18 @@ int main(int argc, const char * argv[]) 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 ( jint(retjson,"docker") == 1 ) + DOCKERFLAG = 1; + else if ( jstr(retjson,"docker") != 0 ) + DOCKERFLAG = (uint32_t)calc_ipbits(jstr(retjson,"docker")); if ( (passphrase= jstr(retjson,"passphrase")) == 0 ) jaddstr(retjson,"passphrase","test"); if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_main,(void *)retjson) != 0 ) @@ -906,7 +878,7 @@ int main(int argc, const char * argv[]) } //else printf("(%s) launched.(%s)\n",argv[1],passphrase); incr = 100.; while ( (1) ) - sleep(1); + sleep(100000); profitmargin = jdouble(retjson,"profitmargin"); minask = jdouble(retjson,"minask"); maxbid = jdouble(retjson,"maxbid"); 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/mshark b/iguana/exchanges/mshark new file mode 100755 index 000000000..fc1f045db --- /dev/null +++ b/iguana/exchanges/mshark @@ -0,0 +1,4 @@ +#!/bin/bash +source userpass +# this will only work for watchonly addresses that have been rescanned and with active coins +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RTu3JZZKLJTcfNwBa19dWRagEfQq49STqC\",\"holdings\":[{\"coin\":\"iota\",\"balance\":5000000}],\"divisor\":1400000}" diff --git a/iguana/exchanges/pendingswaps b/iguana/exchanges/pendingswaps new file mode 100755 index 000000000..6cd5f50dd --- /dev/null +++ b/iguana/exchanges/pendingswaps @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"swapstatus\",\"pending\":1}" 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/sell b/iguana/exchanges/sell index fccc4d61e..ddbff6118 100755 --- a/iguana/exchanges/sell +++ b/iguana/exchanges/sell @@ -1,3 +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}" +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/stats.c b/iguana/exchanges/stats.c index 2ff62895d..f8c4dea27 100644 --- a/iguana/exchanges/stats.c +++ b/iguana/exchanges/stats.c @@ -32,13 +32,15 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t mypubsock,cJSON *argjson,char char *stats_validmethods[] = { - "getprices", "listunspent", "notify", "getpeers", "uitem", // from issue_ - "orderbook", "help", "getcoins", "pricearray", "balance" + "psock", "balances", "getprice", "notify", "getpeers", // from issue_ "uitem", "listunspent", + "orderbook", "statsdisp", "fundvalue", "help", "getcoins", "pricearray", "balance", "tradesarray" }; int32_t LP_valid_remotemethod(cJSON *argjson) { char *method; int32_t i; + if ( DOCKERFLAG != 0 ) + return(1); if ( (method= jstr(argjson,"method")) != 0 ) { for (i=0; i= 0 ) @@ -310,7 +312,7 @@ cJSON *SuperNET_urlconv(char *value,int32_t bufsize,char *urlstr) jaddstr(json,key,value); else jaddistr(array,key); len += (n + 1); - if ( strcmp(key,"Content-Length") == 0 && (datalen= atoi(value)) > 0 ) + if ( (strcmp(key,"Content-Length") == 0 || strcmp(key,"content-length") == 0) && (datalen= atoi(value)) > 0 ) { data = &urlstr[totallen - datalen]; data[-1] = 0; @@ -329,8 +331,7 @@ extern void *bitcoin_ctx(); char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *postflagp,char *urlstr,char *remoteaddr,char *filetype,uint16_t port) { static void *ctx; - cJSON *tokens,*argjson,*origargjson,*tmpjson=0,*json = 0; long filesize; char *myipaddr="127.0.0.1",symbol[64],buf[4096],*userpass=0,urlmethod[16],*data,url[8192],furl[8192],*retstr,*filestr,*token = 0; int32_t i,j,n,num=0; - //printf("rpcparse.(%s)\n",urlstr); + cJSON *tokens,*argjson,*origargjson,*tmpjson=0,*json = 0; long filesize; char *myipaddr="127.0.0.1",symbol[64],buf[4096],*userpass=0,urlmethod[16],*data,url[8192],furl[8192],*retstr=0,*filestr,*token = 0; int32_t i,j,n,num=0; if ( ctx == 0 ) ctx = bitcoin_ctx(); for (i=0; i 0 ) - { - cJSON *retitem,*retarray = cJSON_CreateArray(); - origargjson = argjson; - symbol[0] = 0; - for (i=0; i 0 ) { - argjson = jitem(origargjson,i); - 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 ) + cJSON *retitem,*retarray = cJSON_CreateArray(); + origargjson = argjson; + symbol[0] = 0; + for (i=0; i 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); } - } 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); - } #endif - //printf("(%s) {%s} -> (%s) postflag.%d (%s)\n",urlstr,jprint(argjson,0),cJSON_Print(json),*postflagp,retstr); + //printf("(%s) {%s} -> (%s) postflag.%d (%s)\n",urlstr,jprint(argjson,0),jprint(json,0),*postflagp,retstr); + } + free_json(origargjson); + retstr = jprint(retarray,1); } - free_json(origargjson); - retstr = jprint(retarray,1); - } - else - { - cJSON *arg; - if ( jstr(argjson,"agent") != 0 && strcmp(jstr(argjson,"agent"),"bitcoinrpc") != 0 && jobj(argjson,"params") != 0 ) + else { - arg = jobj(argjson,"params"); - if ( is_cJSON_Array(arg) != 0 && cJSON_GetArraySize(arg) == 1 ) - arg = jitem(arg,0); - } else arg = argjson; - //printf("ARGJSON.(%s)\n",jprint(arg,0)); - if ( userpass != 0 && jstr(arg,"userpass") == 0 ) - jaddstr(arg,"userpass",userpass); + cJSON *arg; + if ( jstr(argjson,"agent") != 0 && strcmp(jstr(argjson,"agent"),"bitcoinrpc") != 0 && jobj(argjson,"params") != 0 ) + { + arg = jobj(argjson,"params"); + if ( is_cJSON_Array(arg) != 0 && cJSON_GetArraySize(arg) == 1 ) + arg = jitem(arg,0); + } else arg = argjson; + //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\"}"); + 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); + retstr = stats_JSON(ctx,myipaddr,-1,arg,remoteaddr,port); #endif + } + free_json(argjson); } - free_json(argjson); free_json(json); if ( tmpjson != 0 ) free(tmpjson); @@ -562,15 +570,17 @@ char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *po } free_json(argjson); if ( tmpjson != 0 ) - free(tmpjson); + free_json(tmpjson); + if ( tokens != 0 ) + free_json(tokens); *jsonflagp = 1; return(clonestr("{\"error\":\"couldnt process packet\"}")); } int32_t iguana_getcontentlen(char *buf,int32_t recvlen) { - char *str,*clenstr = "Content-Length: "; int32_t len = -1; - if ( (str= strstr(buf,clenstr)) != 0 ) + char *str,*clenstr = "Content-Length: ",*clenstr2 = "content-length: "; int32_t len = -1; + if ( (str= strstr(buf,clenstr)) != 0 || (str= strstr(buf,clenstr2)) != 0 ) { //printf("strstr.(%s)\n",str); str += strlen(clenstr); @@ -589,24 +599,32 @@ int32_t iguana_getheadersize(char *buf,int32_t recvlen) } uint16_t RPC_port; -extern portable_mutex_t LP_commandmutex; +extern portable_mutex_t LP_commandmutex,LP_gcmutex; +extern struct rpcrequest_info *LP_garbage_collector; void LP_rpc_processreq(void *_ptr) { - uint64_t arg64 = *(uint64_t *)_ptr; + static uint32_t spawned,maxspawned; char filetype[128],content_type[128]; int32_t recvlen,flag,postflag=0,contentlen,remains,sock,numsent,jsonflag=0,hdrsize,len; - char helpname[512],remoteaddr[64],*buf,*retstr,*space,*jsonbuf; - uint32_t ipbits,i,size = 32*IGUANA_MAXPACKETSIZE + 512; - ipbits = (arg64 >> 32); + char helpname[512],remoteaddr[64],*buf,*retstr,space[8192],space2[32786],*jsonbuf; struct rpcrequest_info *req = _ptr; + uint32_t ipbits,i,size = IGUANA_MAXPACKETSIZE + 512; + ipbits = req->ipbits;; expand_ipbits(remoteaddr,ipbits); - sock = (arg64 & 0xffffffff); + sock = req->sock; recvlen = flag = 0; retstr = 0; - space = calloc(1,size); + //space = calloc(1,size); jsonbuf = calloc(1,size); + //printf("alloc jsonbuf.%p\n",jsonbuf); remains = size-1; buf = jsonbuf; + spawned++; + if ( spawned > maxspawned ) + { + printf("max rpc threads spawned and alive %d <- %d\n",maxspawned,spawned); + maxspawned = spawned; + } while ( remains > 0 ) { //printf("flag.%d remains.%d recvlen.%d\n",flag,remains,recvlen); @@ -617,10 +635,12 @@ void LP_rpc_processreq(void *_ptr) printf("EAGAIN for len %d, remains.%d\n",len,remains); usleep(10000); } + //printf("errno.%d len.%d remains.%d\n",errno,len,remains); break; } else { + //printf("received len.%d\n%s\n",len,buf); if ( len > 0 ) { buf[len] = 0; @@ -651,8 +671,7 @@ void LP_rpc_processreq(void *_ptr) else { usleep(10000); - //printf("got.(%s) %d remains.%d of total.%d\n",jsonbuf,recvlen,remains,len); - //retstr = iguana_rpcparse(space,size,&postflag,jsonbuf); + printf("got.(%s) %d remains.%d of total.%d\n",jsonbuf,recvlen,remains,len); if ( flag == 0 ) break; } @@ -663,9 +682,7 @@ void LP_rpc_processreq(void *_ptr) { jsonflag = postflag = 0; portable_mutex_lock(&LP_commandmutex); - retstr = stats_rpcparse(space,size,&jsonflag,&postflag,jsonbuf,remoteaddr,filetype,RPC_port); - //if ( strcmp("5.9.253.195",remoteaddr) == 0 ) - // printf("RPC.(%s)%s\n",jsonbuf,retstr); + retstr = stats_rpcparse(space,size,&jsonflag,&postflag,jsonbuf,remoteaddr,filetype,req->port); portable_mutex_unlock(&LP_commandmutex); if ( filetype[0] != 0 ) { @@ -690,16 +707,23 @@ void LP_rpc_processreq(void *_ptr) //printf("RETURN.(%s) jsonflag.%d postflag.%d\n",retstr,jsonflag,postflag); if ( jsonflag != 0 || postflag != 0 ) { - if ( retstr == 0 ) - retstr = clonestr("{}"); - response = malloc(strlen(retstr)+1024+1+1); + if ( strlen(retstr)+1024+1+1 < sizeof(space2) ) + response = space2; + else + { + response = malloc(strlen(retstr)+1024+1+1); + //printf("alloc response.%p\n",response); + } sprintf(hdrs,"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Credentials: true\r\nAccess-Control-Allow-Methods: GET, POST\r\nCache-Control : no-cache, no-store, must-revalidate\r\n%sContent-Length : %8d\r\n\r\n",content_type,(int32_t)strlen(retstr)); response[0] = '\0'; strcat(response,hdrs); strcat(response,retstr); strcat(response,"\n"); if ( retstr != space ) + { + //printf("free retstr0.%p\n",retstr); free(retstr); + } retstr = response; //printf("RET.(%s)\n",retstr); } @@ -720,61 +744,121 @@ void LP_rpc_processreq(void *_ptr) remains -= numsent; i += numsent; if ( remains > 0 ) - printf("iguana sent.%d remains.%d of len.%d\n",numsent,remains,recvlen); + printf("iguana sent.%d remains.%d of recvlen.%d (%s)\n",numsent,remains,recvlen,jsonbuf); } } - if ( retstr != space) + if ( retstr != space && retstr != space2 ) + { + //printf("free retstr.%p\n",retstr); free(retstr); + } } - free(space); + //free(space); + //printf("free jsonbuf.%p\n",jsonbuf); free(jsonbuf); closesocket(sock); + if ( 1 ) + { + portable_mutex_lock(&LP_gcmutex); + DL_APPEND(LP_garbage_collector,req); + portable_mutex_unlock(&LP_gcmutex); + } + else + { + //printf("free req.%p\n",req); + free(req); + } + spawned--; } +extern int32_t IAMLP; +//int32_t LP_bindsock_reset,LP_bindsock = -1; + void stats_rpcloop(void *args) { - uint16_t port; int32_t sock,bindsock; socklen_t clilen; struct sockaddr_in cli_addr; uint32_t ipbits; uint64_t arg64; void *arg64ptr; + 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; - RPC_port = port; - while ( (bindsock= iguana_socket(1,"0.0.0.0",port)) < 0 ) - { - //if ( coin->MAXPEERS == 1 ) - // break; - //exit(-1); - sleep(3); - } - printf(">>>>>>>>>> DEX stats 127.0.0.1:%d bind sock.%d DEX stats API enabled <<<<<<<<<\n",port,bindsock); - while ( bindsock >= 0 ) + 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 ) + { + 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 usock.%d errno %d %s\n",sock,errno,strerror(errno)); + printf("iguana_rpcloop ERROR on accept port.%u usock.%d errno %d %s\n",port,sock,errno,strerror(errno)); + closesocket(bindsock); + bindsock = -1; continue; } - memcpy(&ipbits,&cli_addr.sin_addr.s_addr,sizeof(ipbits)); - //printf("remote RPC request from (%s) %x\n",remoteaddr,ipbits); - arg64 = ((uint64_t)ipbits << 32) | (sock & 0xffffffff); - arg64ptr = malloc(sizeof(arg64)); - memcpy(arg64ptr,&arg64,sizeof(arg64)); - if ( 1 ) +/*#else + if ( sock < 0 ) { - LP_rpc_processreq((void *)&arg64); - free(arg64ptr); + //fprintf(stderr,"."); + if ( IAMLP == 0 ) + usleep(50000); + else usleep(2500); + continue; } - else if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_rpc_processreq,arg64ptr) != 0 ) +#endif*/ + memcpy(&ipbits,&cli_addr.sin_addr.s_addr,sizeof(ipbits)); + if ( DOCKERFLAG != 0 && (DOCKERFLAG == 1 || ipbits == DOCKERFLAG) ) + ipbits = localhostbits; + if ( port == RPC_port && ipbits != localhostbits ) { - printf("error launching rpc handler on port %d\n",port); + //printf("port.%u RPC_port.%u ipbits %x != %x\n",port,RPC_port,ipbits,localhostbits); + closesocket(sock); + continue; } - // yes, small leak per command + req = calloc(1,sizeof(*req)); + //printf("alloc req.%p\n",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) + { + DL_DELETE(LP_garbage_collector,req2); + free(req2); + } + portable_mutex_unlock(&LP_gcmutex); + if ( (retval= OS_thread_create(&req->T,NULL,(void *)LP_rpc_processreq,req)) != 0 ) + { + printf("error2 launching rpc handler on port %d, retval.%d\n",port,retval); + LP_rpc_processreq(req); + } + } } + 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) { @@ -1042,7 +1126,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"); @@ -1086,6 +1170,7 @@ 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 = LP_RPCPORT; @@ -1136,3 +1221,4 @@ int main(int argc, const char * argv[]) return 0; } #endif +#endif diff --git a/iguana/exchanges/supernet b/iguana/exchanges/supernet new file mode 100755 index 000000000..5374d5423 --- /dev/null +++ b/iguana/exchanges/supernet @@ -0,0 +1,20 @@ +#!/bin/bash +source userpass +# this will only work for watchonly addresses that have been rescanned and with active coins +echo mshark +./mshark +echo hodl +./hodl +echo dex +./dex +echo jumblr +./jumblr +echo bots +./bots +echo supernet + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"balances\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\"}" +echo supernet +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":13000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":10000}, {\"coin\":\"syscoin\",\"balance\":20000000}, {\"coin\":\"waves\",\"balance\":700000}, {\"coin\":\"bitcoin\",\"balance\":625}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":375000}, {\"coin\":\"chips\",\"balance\":2577006 }, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }],\"divisor\":816016}" + +#curl --url "http://5.9.253.196:7782" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":13000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":10000}, {\"coin\":\"syscoin\",\"balance\":20000000}, {\"coin\":\"waves\",\"balance\":700000}, {\"coin\":\"bitcoin\",\"balance\":625}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":375000}, {\"coin\":\"chips\",\"balance\":2577006 }, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }],\"divisor\":816016}" diff --git a/iguana/exchanges/tradesarray b/iguana/exchanges/tradesarray new file mode 100755 index 000000000..982bdca7c --- /dev/null +++ b/iguana/exchanges/tradesarray @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"tradesarray\",\"base\":\"REVS\",\"rel\":\"KMD\",\"timescale\":3600}" diff --git a/iguana/iguana777.h b/iguana/iguana777.h index 74412e6f0..843ed9c77 100755 --- a/iguana/iguana777.h +++ b/iguana/iguana777.h @@ -18,6 +18,17 @@ copy that into basilisk as coin, changing RELAY -> 0 */ +/* + To add a new dPoW'ed assetchain with DEX* API support: + 1. add to komodo/src: assetchains, assetchains.old, dpowassets, fiat-cli + 2. add to end of NOTARY_CURRENCIES[] array in fundnotaries (iguana_notary.c) + 3. create fiat/ + 4. add to m_notary coins/ get gen_acname from where komodod was launched, change RELAY:-1 and port to 7776 and make _7776 variant + 5. make coins/basilisk/ + 6. launch from a single node with -gen, launch a second node using -addnode= but without -gen + 7. from a single node, fundnotaries to get notaries able to dPoW + */ + #ifndef iguana777_net_h #define iguana777_net_h diff --git a/iguana/iguana_init.c b/iguana/iguana_init.c index 8abd4e50d..bb3c92135 100755 --- a/iguana/iguana_init.c +++ b/iguana/iguana_init.c @@ -15,17 +15,6 @@ #include "iguana777.h" -/* - To add a new dPoW'ed assetchain with DEX* API support: - 1. add to komodo/src: assetchains, dpowassets, fiat-cli - 2. add to end of NOTARY_CURRENCIES[] array in fundnotaries (iguana_notary.c) - 3. create fiat/ - 4. add to m_notary coins/ get gen_acname from where komodod was launched, change RELAY:-1 and port to 7776 and make _7776 variant - 5. make coins/basilisk/ - 6. launch from a single node with -gen, launch a second node using -addnode= but without -gen - 7. from a single node, fundnotaries to get notaries able to dPoW - */ - void iguana_initQ(queue_t *Q,char *name) { struct stritem *tst,*item; diff --git a/iguana/iguana_notary.c b/iguana/iguana_notary.c index 65d42428e..eb36de1e1 100755 --- a/iguana/iguana_notary.c +++ b/iguana/iguana_notary.c @@ -145,8 +145,10 @@ void dpow_srcupdate(struct supernet_info *myinfo,struct dpow_info *dp,int32_t he } else { - freq = 1; minsigs = DPOW_MIN_ASSETCHAIN_SIGS; + if ( strcmp("CHIPS",dp->symbol) == 0 ) + freq = 100; + else freq = 1; } dpow_fifoupdate(myinfo,dp->srcfifo,dp->last); if ( strcmp(dp->dest,"KMD") == 0 ) @@ -556,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", "MNZ", "CHIPS" }; // "LTC", + "REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "SHARK", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "MNZ", "CHIPS", "MSHARK" }; // "LTC", ZERO_ARGS(dpow,notarychains) { 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 9a4fbb305..0d4d9a9c4 100755 --- a/iguana/m_notary +++ b/iguana/m_notary @@ -2,50 +2,4 @@ pkill -15 iguana rm -f ../agents/iguana *.o git pull -cd secp256k1; ./m_unix; cd .. -cd ../crypto777; ./m_LP; cd ../iguana -#gcc -g -fno-aggressive-loop-optimizations -Wno-deprecated -c -O2 -DISNOTARYNODE=1 -DLIQUIDITY_PROVIDER=1 *.c ../basilisk/basilisk.c ../gecko/gecko.c ../datachain/datachain.c -clang -g -Wno-deprecated -c -O2 -DISNOTARYNODE=1 -DLIQUIDITY_PROVIDER=1 *.c ../basilisk/basilisk.c ../gecko/gecko.c ../datachain/datachain.c -#gcc -g -fno-aggressive-loop-optimizations -Wno-deprecated -c -DISNOTARYNODE=1 -DLIQUIDITY_PROVIDER=1 main.c iguana777.c iguana_bundles.c ../basilisk/basilisk.c -clang -g -Wno-deprecated -c -DISNOTARYNODE=1 -DLIQUIDITY_PROVIDER=1 main.c iguana777.c iguana_bundles.c ../basilisk/basilisk.c -clang -g -o ../agents/iguana *.o ../agents/libcrypto777.a -lnanomsg -lcurl -lssl -lcrypto -lpthread -lz -lm - -../agents/iguana notary & #> iguana.log 2> error.log & - -myip=`curl -s4 checkip.amazonaws.com` -source pubkey.txt - -sleep 4 -curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"SuperNET\",\"method\":\"myipaddr\",\"ipaddr\":\"$myip\"}" -sleep 3 -tests/addnotarys_7776 -coins/btc_7776 -coins/ltc_7776 -coins/kmd_7776 -coins/chips_7776 -./wp_7776 - -coins/revs_7776 -coins/supernet_7776 -coins/dex_7776 -coins/bet_7776 -coins/bots_7776 -coins/hodl_7776 -coins/shark_7776 -coins/jumblr_7776 -coins/crypto_7776 -coins/pangea_7776 -coins/mgw_7776 -#coins/mvp_7776 -coins/coqui_7776 -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\"}" -curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"KMD\",\"pubkey\":\"$pubkey\"}" - -sleep 17 +./m_notary_run diff --git a/iguana/m_notary_run b/iguana/m_notary_run new file mode 100755 index 000000000..4c64de6ff --- /dev/null +++ b/iguana/m_notary_run @@ -0,0 +1,47 @@ +#!/bin/bash + +cd secp256k1; ./m_unix; cd .. +cd ../crypto777; ./m_LP; cd ../iguana +#gcc -g -fno-aggressive-loop-optimizations -Wno-deprecated -c -O2 -DISNOTARYNODE=1 -DLIQUIDITY_PROVIDER=1 *.c ../basilisk/basilisk.c ../gecko/gecko.c ../datachain/datachain.c +clang -g -Wno-deprecated -c -O2 -DISNOTARYNODE=1 -DLIQUIDITY_PROVIDER=1 *.c ../basilisk/basilisk.c ../gecko/gecko.c ../datachain/datachain.c +#gcc -g -fno-aggressive-loop-optimizations -Wno-deprecated -c -DISNOTARYNODE=1 -DLIQUIDITY_PROVIDER=1 main.c iguana777.c iguana_bundles.c ../basilisk/basilisk.c +clang -g -Wno-deprecated -c -DISNOTARYNODE=1 -DLIQUIDITY_PROVIDER=1 main.c iguana777.c iguana_bundles.c ../basilisk/basilisk.c +clang -g -o ../agents/iguana *.o ../agents/libcrypto777.a -lnanomsg -lcurl -lssl -lcrypto -lpthread -lz -lm + +../agents/iguana notary & #> iguana.log 2> error.log & + +myip=`curl -s4 checkip.amazonaws.com` +source pubkey.txt + +sleep 4 +curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"SuperNET\",\"method\":\"myipaddr\",\"ipaddr\":\"$myip\"}" +sleep 3 +tests/addnotarys_7776 +coins/btc_7776 +coins/ltc_7776 +coins/kmd_7776 +coins/chips_7776 +./wp_7776 + +coins/revs_7776 +coins/supernet_7776 +coins/dex_7776 +coins/bet_7776 +coins/bots_7776 +coins/hodl_7776 +coins/shark_7776 +coins/mshark_7776 +coins/jumblr_7776 +coins/crypto_7776 +coins/pangea_7776 +coins/mgw_7776 +coins/coqui_7776 +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\"}" +curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"dpow\",\"symbol\":\"KMD\",\"pubkey\":\"$pubkey\"}" diff --git a/iguana/m_splitfund b/iguana/m_splitfund index 342f8e6de..9e445cd6b 100755 --- a/iguana/m_splitfund +++ b/iguana/m_splitfund @@ -14,6 +14,7 @@ curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"BET\",\"agent\":\"iguana\ curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CRYPTO\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"HODL\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"SHARK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MSHARK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"BOTS\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MGW\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" #curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MVP\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" @@ -24,36 +25,36 @@ curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CEAL\",\"agent\":\"iguana 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}" +#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}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"JPY\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"GBP\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"AUD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CAD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CHF\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"NZD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CNY\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"RUB\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MXN\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"BRL\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"INR\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"HKD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"TRY\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"ZAR\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"PLN\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"NOK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"SEK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"DKK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CZK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"HUF\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"ILS\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"KRW\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MYR\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"PHP\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"RON\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"SGD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"THB\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"BGN\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"IDR\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" -curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"HRK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"JPY\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"GBP\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"AUD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CAD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CHF\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"NZD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CNY\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"RUB\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MXN\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"BRL\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"INR\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"HKD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"TRY\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"ZAR\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"PLN\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"NOK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"SEK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"DKK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CZK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"HUF\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"ILS\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"KRW\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MYR\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"PHP\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"RON\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"SGD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"THB\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"BGN\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"IDR\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"HRK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" diff --git a/iguana/main.c b/iguana/main.c index 85510c3fb..b89521a04 100755 --- a/iguana/main.c +++ b/iguana/main.c @@ -793,7 +793,7 @@ void iguana_launchdaemons(struct supernet_info *myinfo) if ( COMMANDLINE_ARGFILE == 0 ) iguana_launch(0,"rpcloop",iguana_rpcloop,myinfo,IGUANA_PERMTHREAD); // limit to oneprocess printf("launch mainloop\n"); - OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)DEX_explorerloop,(void *)myinfo); + // disable basilisk: OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)DEX_explorerloop,(void *)myinfo); OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)jumblr_loop,(void *)myinfo); OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)dpow_psockloop,(void *)myinfo); mainloop(myinfo); 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/marketmaker.vcxproj b/marketmaker.vcxproj index b441d6ab4..7d3862568 100644 --- a/marketmaker.vcxproj +++ b/marketmaker.vcxproj @@ -87,7 +87,7 @@ Level2 Disabled _CRT_SECURE_NO_WARNINGS;NATIVE_WINDOWS;WIN32;_DEBUG;_CONSOLE;IGUANA_LOG2PACKETSIZE=20;IGUANA_MAXPACKETSIZE=1572864;%(PreprocessorDefinitions) - 1Byte + 8Bytes .\iguana;%(AdditionalIncludeDirectories) @@ -104,7 +104,7 @@ Level3 Disabled _DEBUG;_CONSOLE;NATIVE_WINDOWS;WIN32;IGUANA_LOG2PACKETSIZE=20;IGUANA_MAXPACKETSIZE=1572864;%(PreprocessorDefinitions) - 1Byte + 8Bytes Console @@ -122,7 +122,7 @@ true true _CRT_SECURE_NO_WARNINGS;NATIVE_WINDOWS;WIN32;_CONSOLE;NDEBUG;IGUANA_LOG2PACKETSIZE=20;IGUANA_MAXPACKETSIZE=1572864;%(PreprocessorDefinitions) - 1Byte + 8Bytes MachineX86 @@ -130,6 +130,7 @@ Console true true + Ws2_32.lib;Advapi32.lib;$(SolutionDir)OSlibs\win\release\pthreadVC2.lib;libcurl.lib;nanomsg.lib;%(AdditionalDependencies) @@ -141,7 +142,7 @@ true true WIN64;_WIN64;_CRT_SECURE_NO_WARNINGS;NATIVE_WINDOWS;WIN32;WIN32_LEAN_AND_MEAN;_CONSOLE;NDEBUG;IGUANA_LOG2PACKETSIZE=20;IGUANA_MAXPACKETSIZE=1572864;%(PreprocessorDefinitions) - 1Byte + 8Bytes MultiThreaded 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 + )