diff --git a/.gitignore b/.gitignore index c65237e28..37c54960f 100755 --- a/.gitignore +++ b/.gitignore @@ -244,3 +244,9 @@ iguana/DB/KMD/0/.tmpmarker iguana/myipaddr iguana/DB/UNSPENTS/.tmpmarker + +*.RQ4z6KrMZeEnCSCsChv1ZoR9ExQitHjbpg + +iguana/DB/instantdex_RQ4z6KrMZeEnCSCsChv1ZoR9ExQitHjbpg_append.json + +iguana/DB/instantdex_RQ4z6KrMZeEnCSCsChv1ZoR9ExQitHjbpg.json diff --git a/crypto777/OS_portable.h b/crypto777/OS_portable.h index 3d90521bd..8c109e5d0 100755 --- a/crypto777/OS_portable.h +++ b/crypto777/OS_portable.h @@ -326,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 f624cd342..d6c6f69f4 100755 --- a/crypto777/bitcoind_RPC.c +++ b/crypto777/bitcoind_RPC.c @@ -30,6 +30,7 @@ void *LP_alloc(uint64_t len); void LP_free(void *ptr); char *LP_clonestr(char *str);*/ +int32_t bitcoind_RPC_inittime; #if LIQUIDITY_PROVIDER #include @@ -73,7 +74,7 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char * char *retstr = 0; cJSON *json,*result,*error; #ifdef FROM_MARKETMAKER - usleep(3000); + //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 ) @@ -96,6 +97,7 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char * if ( (error->type&0xff) == cJSON_NULL && (result->type&0xff) != cJSON_NULL ) { retstr = jprint(result,0); + //printf("%s %s rpc retstr.%p\n",command,params,retstr); len = strlen(retstr); if ( retstr[0] == '"' && retstr[len-1] == '"' ) { @@ -112,7 +114,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); @@ -186,7 +191,16 @@ try_again: 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 ) - curl_easy_setopt(curl_handle,CURLOPT_TIMEOUT, timeout); // causes problems with iguana timeouts + { + if ( bitcoind_RPC_inittime != 0 ) + { +#ifndef _WIN32 + curl_easy_setopt(curl_handle,CURLOPT_TIMEOUT,1); +#else + curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT_MS, timeout*100); +#endif + } else curl_easy_setopt(curl_handle,CURLOPT_TIMEOUT,timeout); // causes problems with iguana timeouts + } if ( strncmp(url,"https",5) == 0 ) { curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0); @@ -231,30 +245,30 @@ try_again: free(databuf); databuf = 0; } + retstr = chunk.memory; // retstr = s.ptr; if ( res != CURLE_OK ) { numretries++; if ( specialcase != 0 || timeout != 0 ) { - //printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res); - free(chunk.memory); //free(s.ptr); + //printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,retstr,res); + free(retstr); return(0); } else if ( numretries >= 4 ) { printf( "curl_easy_perform() failed: %s %s.(%s %s), retries: %d\n",curl_easy_strerror(res),debugstr,url,command,numretries); //printf("Maximum number of retries exceeded!\n"); - free(chunk.memory);//free(s.ptr); + free(retstr); return(0); } - free(chunk.memory);//free(s.ptr); + free(retstr); sleep((1<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); diff --git a/crypto777/iguana_OS.c b/crypto777/iguana_OS.c index 2000651a9..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 ) diff --git a/crypto777/iguana_utils.c b/crypto777/iguana_utils.c index 2e8f8e18b..5f978e305 100755 --- a/crypto777/iguana_utils.c +++ b/crypto777/iguana_utils.c @@ -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/crypto777/ramcoder.c b/crypto777/ramcoder.c index ea1076736..54daeee5e 100755 --- a/crypto777/ramcoder.c +++ b/crypto777/ramcoder.c @@ -430,19 +430,22 @@ int32_t ramcoder_decoder(struct ramcoder *coder,int32_t updateprobs,uint8_t *buf return(n); } -int32_t ramcoder_compress(uint8_t *bits,int32_t maxlen,uint8_t *data,int32_t datalen,bits256 seed) +int32_t ramcoder_compress(uint8_t *bits,int32_t maxlen,uint8_t *data,int32_t datalen,bits256 origseed) { - int32_t numbits; HUFF H,*hp = &H; + uint64_t histo[256]; bits256 seed; char str[65]; int32_t numbits; HUFF H,*hp = &H; _init_HUFF(hp,maxlen,bits); - if ( ramcoder_encoder(0,1,data,datalen,hp,0,&seed) < 0 ) + memset(histo,0,sizeof(histo)); + seed = origseed; + if ( ramcoder_encoder(0,1,data,datalen,hp,histo,&seed) < 0 ) return(-1); + printf("seed.%s\n",bits256_str(str,seed)); numbits = hp->bitoffset; - if ( (0) ) + if ( (1) ) { void *malloc(size_t); void free(void *); int32_t i,checklen; uint8_t *checkbuf; checkbuf = malloc(datalen*2); - memset(seed.bytes,0,sizeof(seed)); + seed = origseed; hrewind(hp); checklen = ramcoder_decoder(0,1,checkbuf,datalen*2,hp,&seed); if ( checklen != datalen || memcmp(checkbuf,data,datalen) != 0 ) @@ -457,7 +460,7 @@ int32_t ramcoder_compress(uint8_t *bits,int32_t maxlen,uint8_t *data,int32_t dat printf("%02x ",checkbuf[i]); printf("checklen.%d\n",checklen); getchar(); - } // else printf("CODEC passed datalen.%d -> numbits %d %d\n",datalen,numbits,numbits/8); + } else printf("CODEC passed datalen.%d -> numbits %d %d origseed.%s\n",datalen,numbits,numbits/8,bits256_str(str,origseed)); free(checkbuf); } return(numbits); diff --git a/iguana/coins/axo_7776 b/iguana/coins/axo_7776 new file mode 100755 index 000000000..5a4cd4bd8 --- /dev/null +++ b/iguana/coins/axo_7776 @@ -0,0 +1,2 @@ +curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"AXO.conf\",\"path\":\"${HOME#"/"}/.komodo/AXO\",\"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\":\"AXO\",\"name\":\"AXO\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"ba009d17\",\"p2p\":12926,\"rpc\":12927,\"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/basilisk/axo b/iguana/coins/basilisk/axo new file mode 100755 index 000000000..d2b6990b9 --- /dev/null +++ b/iguana/coins/basilisk/axo @@ -0,0 +1,2 @@ +curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"AXO.conf\",\"path\":\"${HOME#"/"}/.komodo/AXO\",\"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\":\"AXO\",\"name\":\"AXO\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"ba009d17\",\"p2p\":12926,\"rpc\":12927,\"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/basilisk/btch b/iguana/coins/basilisk/btch new file mode 100755 index 000000000..a74832995 --- /dev/null +++ b/iguana/coins/basilisk/btch @@ -0,0 +1 @@ +curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"BTCH.conf\",\"path\":\"${HOME#"/"}/.komodo/BTCH\",\"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\":\"BTCH\",\"name\":\"BTCH\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"b0ed1968\",\"p2p\":8799,\"rpc\":8800,\"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/basilisk/etomic b/iguana/coins/basilisk/etomic new file mode 100755 index 000000000..4f63e424d --- /dev/null +++ b/iguana/coins/basilisk/etomic @@ -0,0 +1,2 @@ +curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"ETOMIC.conf\",\"path\":\"${HOME#"/"}/.komodo/ETOMIC\",\"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\":\"ETOMIC\",\"name\":\"ETOMIC\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"072a90e8\",\"p2p\":10270,\"rpc\":10271,\"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/basilisk/mshark b/iguana/coins/basilisk/mshark new file mode 100755 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/btch_7776 b/iguana/coins/btch_7776 new file mode 100755 index 000000000..d36d143d8 --- /dev/null +++ b/iguana/coins/btch_7776 @@ -0,0 +1,2 @@ +curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"BTCH.conf\",\"path\":\"${HOME#"/"}/.komodo/BTCH\",\"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\":\"BTCH\",\"name\":\"BTCH\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"b0ed1968\",\"p2p\":8799,\"rpc\":8800,\"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/etomic_7776 b/iguana/coins/etomic_7776 new file mode 100755 index 000000000..c17f7c733 --- /dev/null +++ b/iguana/coins/etomic_7776 @@ -0,0 +1,2 @@ +curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"ETOMIC.conf\",\"path\":\"${HOME#"/"}/.komodo/ETOMIC\",\"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\":\"ETOMIC\",\"name\":\"ETOMIC\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"072a90e8\",\"p2p\":10270,\"rpc\":10271,\"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/genREVS b/iguana/coins/genREVS old mode 100644 new mode 100755 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/dpow/dpow_network.c b/iguana/dpow/dpow_network.c index 9899b9cac..0f6fb2c6a 100755 --- a/iguana/dpow/dpow_network.c +++ b/iguana/dpow/dpow_network.c @@ -21,56 +21,6 @@ struct signed_nnpacket uint8_t packet[]; } PACKED; -/* - NN_CONNECT to (tcp://167.114.118.5:7775) -NN_CONNECT to (tcp://10.0.0.4:7775) -NN_CONNECT to (tcp://85.143.211.6:7775) -NN_CONNECT to (tcp://158.69.25.7:7775) -NN_CONNECT to (tcp://123.249.79.12:7775) -NN_CONNECT to (tcp://141.105.66.18:7775) -NN_CONNECT to (tcp://198.27.75.27:7775) -NN_CONNECT to (tcp://198.204.226.34:7775) -NN_CONNECT to (tcp://144.76.94.38:7775) -NN_CONNECT to (tcp://142.54.174.42:7775) -NN_CONNECT to (tcp://88.198.70.43:7775) -NN_CONNECT to (tcp://182.162.169.44:7775) -NN_CONNECT to (tcp://104.168.128.50:7775) -NN_CONNECT to (tcp://167.114.64.64:7775) -NN_CONNECT to (tcp://185.169.229.64:7775) -NN_CONNECT to (tcp://46.4.68.72:7775) -NN_CONNECT to (tcp://173.208.203.74:7775) -NN_CONNECT to (tcp://192.99.232.81:7775) -NN_CONNECT to (tcp://149.56.28.84:7775) -NN_CONNECT to (tcp://148.251.190.89:7775) -NN_CONNECT to (tcp://149.56.240.91:7775) -NN_CONNECT to (tcp://88.99.56.99:7775) -NN_CONNECT to (tcp://217.106.238.109:7775) -NN_CONNECT to (tcp://142.54.164.114:7775) -NN_CONNECT to (tcp://163.172.101.118:7775) -NN_CONNECT to (tcp://189.1.174.119:7775) -NN_CONNECT to (tcp://1.234.19.123:7775) -NN_CONNECT to (tcp://221.121.144.138:7775) -NN_CONNECT to (tcp://46.166.168.138:7775) -NN_CONNECT to (tcp://221.121.144.140:7775) -NN_CONNECT to (tcp://163.172.100.144:7775) -NN_CONNECT to (tcp://185.106.122.147:7775) -NN_CONNECT to (tcp://103.18.58.150:7775) -NN_CONNECT to (tcp://23.88.234.153:7775) -NN_CONNECT to (tcp://164.132.202.176:7775) -NN_CONNECT to (tcp://178.63.85.196:7775) -NN_CONNECT to (tcp://69.12.77.197:7775) -NN_CONNECT to (tcp://192.157.238.198:7775) -NN_CONNECT to (tcp://209.58.183.199:7775) -NN_CONNECT to (tcp://149.202.65.200:7775) -NN_CONNECT to (tcp://173.208.184.202:7775) -NN_CONNECT to (tcp://94.102.63.208:7775) -NN_CONNECT to (tcp://5.9.109.208:7775) -NN_CONNECT to (tcp://94.102.63.209:7775) -NN_CONNECT to (tcp://197.189.248.210:7775) -NN_CONNECT to (tcp://149.56.19.212:7775) -NN_CONNECT to (tcp://46.165.243.214:7775) -NN_CONNECT to (tcp://45.64.168.216:7775) -*/ void dex_init(struct supernet_info *myinfo) { @@ -584,6 +534,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/exchanges/LP_NXT.c b/iguana/exchanges/LP_NXT.c new file mode 100644 index 000000000..81ab96131 --- /dev/null +++ b/iguana/exchanges/LP_NXT.c @@ -0,0 +1,344 @@ + +/****************************************************************************** + * 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; + //sleep 1; fiat/supernet sendtoaddress RNZZuQYu8xJLZHuekhd96hYfoQuiCMz99T 1001.44150000 # txnum.8537615468620726612 + //sleep 1; fiat/pangea sendtoaddress RWMdRaUmMZqKkEibwEhY6XS3RLCXJDWHTi 22.10910000 # txnum.2649622877615958504 + uint64_t txnum_marker = calc_nxt64bits("8537615468620726612"); // 2649622877615958504"); // set to most recent processed + uint64_t txnum_marker2 = calc_nxt64bits("7256847492742571143"); // dont change, end marker + 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 53466e5e7..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[65],refrel[65]; - int32_t numswaps,numavoidtxids,numwhitelist,numblacklist,numpendings,pending_swaps[1024]; - bits256 avoidtxids[8192],whitelist[1024],blacklist[1024],pending_pubkeys[1024]; + char refbase[128],refrel[128]; + int64_t pending_kmdvalue[LP_NUMRT]; + int32_t numswaps,numavoidtxids,numwhitelist,numblacklist,numpendings,pending_swaps[LP_NUMRT]; + bits256 avoidtxids[8192],whitelist[LP_NUMRT],blacklist[LP_NUMRT],pending_pubkeys[LP_NUMRT]; } LP_RTmetrics; int32_t LP_bits256_find(bits256 *list,int32_t num,bits256 val) @@ -72,11 +74,14 @@ int32_t LP_RTmetrics_blacklistadd(bits256 pubkey) return(LP_bits256_add("LP_RTmetrics_blacklistadd blacklist",LP_RTmetrics.blacklist,&LP_RTmetrics.numblacklist,(int32_t)(sizeof(LP_RTmetrics.blacklist)/sizeof(*LP_RTmetrics.blacklist)),pubkey)); } -int32_t LP_RTmetrics_pendingswap(bits256 pubkey) +int32_t LP_RTmetrics_pendingswap(bits256 pubkey,int64_t kmdvalue) { int32_t ind; if ( (ind= LP_bits256_add("LP_RTmetrics_pendingswap",LP_RTmetrics.pending_pubkeys,&LP_RTmetrics.numpendings,(int32_t)(sizeof(LP_RTmetrics.pending_pubkeys)/sizeof(*LP_RTmetrics.pending_pubkeys)),pubkey)) >= 0 ) + { LP_RTmetrics.pending_swaps[ind]++; + LP_RTmetrics.pending_kmdvalue[ind] += kmdvalue; + } return(ind); } @@ -113,7 +118,9 @@ void LP_RTmetrics_swapsinfo(char *refbase,char *refrel,cJSON *swaps,int32_t nums base = ""; if ( (rel= jstr(item,"rel")) == 0 ) rel = ""; - if ( strcmp(base,refbase) != 0 && strcmp(base,refrel) != 0 && strcmp(rel,refbase) != 0 && strcmp(rel,refrel) != 0 ) + if ( refbase[0] != 0 && strcmp(base,refbase) != 0 && strcmp(base,refrel) != 0 ) + continue; + if ( refrel[0] != 0 && strcmp(rel,refbase) != 0 && strcmp(rel,refrel) != 0 ) continue; aliceid = j64bits(item,"aliceid"); basesatoshis = SATOSHIDEN * jdouble(item,"basevol"); @@ -123,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); } + 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) { diff --git a/iguana/exchanges/LP_bitcoin.c b/iguana/exchanges/LP_bitcoin.c index 1444658c9..ff4860c98 100644 --- a/iguana/exchanges/LP_bitcoin.c +++ b/iguana/exchanges/LP_bitcoin.c @@ -1959,13 +1959,13 @@ int32_t bitcoin_timelockspend(uint8_t *script,int32_t n,uint8_t rmd160[20],uint3 return(n); } -int32_t bitcoin_performancebond(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,uint32_t unlocktimestamp,uint8_t cltv_rmd160[20],uint8_t anytime_rmd160[20]) +int32_t bitcoin_performancebond(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,uint32_t unlocktimestamp,uint8_t *cltvpub33,uint8_t *elsepub33) { script[n++] = SCRIPT_OP_IF; n = bitcoin_checklocktimeverify(script,n,unlocktimestamp); - n = bitcoin_standardspend(script,n,cltv_rmd160); + n = bitcoin_pubkeyspend(script,n,cltvpub33); script[n++] = SCRIPT_OP_ELSE; - n = bitcoin_standardspend(script,n,anytime_rmd160); + n = bitcoin_pubkeyspend(script,n,elsepub33); script[n++] = SCRIPT_OP_ENDIF; calc_rmd160_sha256(p2sh_rmd160,script,n); return(n); @@ -2008,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)); } @@ -2135,30 +2137,46 @@ int32_t base58encode_checkbuf(uint8_t taddr,uint8_t addrtype,uint8_t *data,int32 int32_t bitcoin_wif2priv(uint8_t wiftaddr,uint8_t *addrtypep,bits256 *privkeyp,char *wifstr) { - int32_t offset,len = -1; bits256 hash; uint8_t buf[256]; + int32_t offset,len = -1; bits256 hash; uint8_t buf[256],*ptr; offset = 1 + (wiftaddr != 0); memset(buf,0,sizeof(buf)); + memset(privkeyp,0,sizeof(*privkeyp)); if ( (len= bitcoin_base58decode(buf,wifstr)) >= 4 ) { - // validate with trailing hash, then remove hash - if ( len < 38 ) + if ( len >= 32+offset ) + memcpy(privkeyp,buf+offset,32); + else + { + //printf("wif %s -> buf too short len.%d\n",wifstr,len); + return(-1); + } + ptr = buf; + /*if ( len < 38 ) + { + memset(pbuf,0,sizeof(pbuf)); + memcpy(pbuf,buf,len-4); + memcpy(&pbuf[34],&buf[len-4],4); + ptr = pbuf; + int32_t i; for (i=0; i<38; i++) + printf("%02x ",pbuf[i]); + printf("pbuf from %d\n",len); len = 38; - hash = bits256_doublesha256(0,buf,len - 4); - *addrtypep = (wiftaddr == 0) ? *buf : buf[1]; - memcpy(privkeyp,buf+offset,32); - if ( (buf[len - 4]&0xff) == hash.bytes[31] && (buf[len - 3]&0xff) == hash.bytes[30] &&(buf[len - 2]&0xff) == hash.bytes[29] && (buf[len - 1]&0xff) == hash.bytes[28] ) + }*/ + hash = bits256_doublesha256(0,ptr,len - 4); + *addrtypep = (wiftaddr == 0) ? *ptr : ptr[1]; + if ( (ptr[len - 4]&0xff) == hash.bytes[31] && (ptr[len - 3]&0xff) == hash.bytes[30] &&(ptr[len - 2]&0xff) == hash.bytes[29] && (ptr[len - 1]&0xff) == hash.bytes[28] ) { //int32_t i; for (i=0; i= 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; @@ -2408,14 +2439,7 @@ int32_t bitcoin_scriptget(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint32_ } 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); } @@ -2583,39 +2607,6 @@ int32_t iguana_calcrmd160(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,char *a return(vp->type); } -uint32_t iguana_vinscriptparse(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,struct vin_info *vp,uint32_t *sigsizep,uint32_t *pubkeysizep,uint32_t *p2shsizep,uint32_t *userdatalenp,uint8_t *vinscript,int32_t scriptlen) -{ - uint32_t hashtype; uint8_t *userdata = 0; - *sigsizep = *pubkeysizep = *p2shsizep = *userdatalenp = 0; - if ( bitcoin_scriptget(taddr,pubtype,p2shtype,&hashtype,sigsizep,pubkeysizep,&userdata,userdatalenp,vp,vinscript,scriptlen,0) < 0 ) - { - printf("iguana_vinscriptparse: error parsing vinscript?\n"); - return(-1); - } - if ( userdata != 0 && *userdatalenp > 0 ) - memcpy(vp->userdata,userdata,*userdatalenp); - if ( vp->type == IGUANA_SCRIPT_P2SH ) - { - *p2shsizep = vp->p2shlen + 1 + (vp->p2shlen >= 0xfd)*2; - //printf("P2SHSIZE.%d\n",*p2shsizep); - } - return(hashtype); -} - -/*char *iguana_scriptget(struct iguana_info *coin,char *scriptstr,char *asmstr,int32_t max,int32_t hdrsi,uint32_t unspentind,bits256 txid,int32_t vout,uint8_t *rmd160,int32_t type,uint8_t *pubkey33) -{ - int32_t scriptlen; uint8_t script[IGUANA_MAXSCRIPTSIZE]; struct vin_info V,*vp = &V; - memset(vp,0,sizeof(*vp)); - scriptstr[0] = 0; - if ( asmstr != 0 ) - asmstr[0] = 0; - if ( pubkey33 != 0 && bitcoin_pubkeylen(pubkey33) > 0 ) - memcpy(vp->signers[0].pubkey,pubkey33,33); - scriptlen = iguana_scriptgen(coin,&vp->M,&vp->N,vp->coinaddr,script,asmstr,rmd160,type,(const struct vin_info *)vp,vout); - init_hexbytes_noT(scriptstr,script,scriptlen); - return(scriptstr); -}*/ - cJSON *bitcoin_txscript(char *asmstr,char **vardata,int32_t numvars) { int32_t i; cJSON *scriptjson,*array; @@ -3040,7 +3031,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) ) { @@ -3279,58 +3270,186 @@ 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,uint32_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; + int32_t i,len,sbtcflag = 0; bits256 sigtxid,txid,revsigtxid; struct iguana_msgtx dest; dest = *msgtx; dest.vins = calloc(dest.tx_in,sizeof(*dest.vins)); dest.vouts = calloc(dest.tx_out,sizeof(*dest.vouts)); 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 ( strcmp(symbol,"SBTC") == 0 ) + sbtcflag = 1; + 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); + if ( sbtcflag != 0 ) + { + memcpy(&serialized[len],"sbtc",4); + len += 4; + } } - dest.vins[i].p2shlen = 0; - dest.vins[i].redeemscript = 0; - dest.vins[i].userdata = 0; - dest.vins[i].userdatalen = 0; + revsigtxid = bits256_doublesha256(0,serialized,len); + 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 + /* + https://github.com/Bitcoin-UAHF/spec/blob/master/replay-protected-sighash.md + CHashWriter ss(SER_GETHASH, 0); + // Version + ss << txTo.nVersion; + // Input prevouts/nSequence (none/all, depending on flags) + ss << hashPrevouts; + ss << hashSequence; + // The input being signed (replacing the scriptSig with scriptCode + + // amount). The prevout may already be contained in hashPrevout, and the + // nSequence may already be contain in hashSequence. + ss << txTo.vin[nIn].prevout; + ss << static_cast(scriptCode); + ss << amount; + ss << txTo.vin[nIn].nSequence; + // Outputs (none/one/all, depending on flags) + ss << hashOutputs; + // Locktime + ss << txTo.nLockTime; + // Sighash type + ss << ((GetForkId() << 8) | nHashType); + return ss.GetHash(); + } + Computation of midstates: + + uint256 GetPrevoutHash(const CTransaction &txTo) { + CHashWriter ss(SER_GETHASH, 0); + for (unsigned int n = 0; n < txTo.vin.size(); n++) { + ss << txTo.vin[n].prevout; + } + + return ss.GetHash(); + } + + uint256 GetSequenceHash(const CTransaction &txTo) { + CHashWriter ss(SER_GETHASH, 0); + for (unsigned int n = 0; n < txTo.vin.size(); n++) { + ss << txTo.vin[n].nSequence; + } + + return ss.GetHash(); + } + + uint256 GetOutputsHash(const CTransaction &txTo) { + CHashWriter ss(SER_GETHASH, 0); + for (unsigned int n = 0; n < txTo.vout.size(); n++) { + ss << txTo.vout[n]; + } + + return ss.GetHash(); + } + */ + bits256 prevouthash,seqhash,outputhash; + for (i=len=0; i sighash.fc55acc3666c43b8f75908ca06ea2d343cd09eb846f14c5d7d0748a11e081a9d*/ + len = 0; + len += iguana_rwnum(1,&serialized[len],sizeof(dest.version),&dest.version); + len += iguana_rwbignum(1,&serialized[len],sizeof(prevouthash),prevouthash.bytes); + len += iguana_rwbignum(1,&serialized[len],sizeof(seqhash),seqhash.bytes); + len += iguana_rwbignum(1,&serialized[len],sizeof(dest.vins[vini].prev_hash),dest.vins[vini].prev_hash.bytes); + len += iguana_rwnum(1,&serialized[len],sizeof(dest.vins[vini].prev_vout),&dest.vins[vini].prev_vout); + serialized[len++] = spendlen; + memcpy(&serialized[len],spendscript,spendlen), len += spendlen; + len += iguana_rwnum(1,&serialized[len],sizeof(spendamount),&spendamount); + len += iguana_rwnum(1,&serialized[len],sizeof(dest.vins[vini].sequence),&dest.vins[vini].sequence); + len += iguana_rwbignum(1,&serialized[len],sizeof(outputhash),outputhash.bytes); + len += iguana_rwnum(1,&serialized[len],sizeof(dest.lock_time),&dest.lock_time); len += iguana_rwnum(1,&serialized[len],sizeof(hashtype),&hashtype); + //for (i=0; iversion),&msg->version); if ( json != 0 ) @@ -3535,10 +3670,9 @@ int32_t iguana_rwmsgtx(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t is { uint32_t sighash; iguana_vinobjset(&msg->vins[i],jitem(vins,i),spendscript,sizeof(spendscript)); - sighash = SIGHASH_ALL; - if ( zcash == LP_IS_BITCOINCASH ) - sighash |= SIGHASH_FORKID; - sigtxid = bitcoin_sigtxid(taddr,pubtype,p2shtype,isPoS,height,sigser,maxsize*2,msg,i,msg->vins[i].spendscript,msg->vins[i].spendlen,sighash,vpnstr,suppress_pubkeys,zcash); + 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)); @@ -3636,13 +3770,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); @@ -3670,7 +3804,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 ) @@ -3681,7 +3815,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); @@ -3699,7 +3833,7 @@ cJSON *bitcoin_data2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t return(txobj); } -cJSON *bitcoin_hex2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,char *txbytes,uint8_t *extraspace,int32_t extralen,uint8_t *origserialized,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash) +cJSON *bitcoin_hex2json(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,char *txbytes,uint8_t *extraspace,int32_t extralen,uint8_t *origserialized,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash) { int32_t len; uint8_t *serialized; cJSON *txobj; if ( txbytes == 0 ) @@ -3708,7 +3842,7 @@ cJSON *bitcoin_hex2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t i if ( (serialized= origserialized) == 0 ) serialized = calloc(1,len+4096); decode_hex(serialized,len,txbytes); - txobj = bitcoin_data2json(taddr,pubtype,p2shtype,isPoS,height,txidp,msgtx,extraspace,extralen,serialized,len,vins,suppress_pubkeys,zcash); + txobj = bitcoin_data2json(symbol,taddr,pubtype,p2shtype,isPoS,height,txidp,msgtx,extraspace,extralen,serialized,len,vins,suppress_pubkeys,zcash); if ( serialized != origserialized ) free(serialized); return(txobj); diff --git a/iguana/exchanges/LP_cache.c b/iguana/exchanges/LP_cache.c index fbce9ddff..194ab75c0 100644 --- a/iguana/exchanges/LP_cache.c +++ b/iguana/exchanges/LP_cache.c @@ -23,7 +23,7 @@ cJSON *LP_transaction_fromdata(struct iguana_info *coin,bits256 txid,uint8_t *se 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); + txobj = bitcoin_data2json(coin->symbol,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->height,&checktxid,&msgtx,extraspace,4000000,serialized,len,0,0,coin->zcash); //printf("TX.(%s) match.%d\n",jprint(txobj,0),bits256_cmp(txid,checktxid)); free(extraspace); if ( bits256_cmp(txid,checktxid) != 0 ) @@ -45,10 +45,9 @@ struct LP_transaction *LP_create_transaction(struct iguana_info *coin,bits256 tx vins = jarray(&numvins,txobj,"vin"); vouts = jarray(&numvouts,txobj,"vout"); tx = LP_transactionadd(coin,txid,height,numvouts,numvins); - tx->serialized = 0;//serialized; - free(serialized); + tx->serialized = serialized, tx->len = len; + // free(serialized), tx->len = 0; tx->fpos = fpos; - tx->len = 0;//tx->len; tx->SPV = tx->height = height; //printf("tx.%s numvins.%d numvouts.%d\n",bits256_str(str,txid),numvins,numvouts); for (i=0; ismartaddr) == 0 ) { - if ( (retjson= electrum_transaction(coin->symbol,ep,&retjson,txid,0)) != 0 ) + if ( (retjson= electrum_transaction(&ht,coin->symbol,ep,&retjson,txid,0)) != 0 ) free_json(retjson); } if ( tx != 0 ) { - tx->height = height; + 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); } @@ -262,7 +268,7 @@ int32_t LP_merkleproof(struct iguana_info *coin,char *coinaddr,struct electrum_i if ( tx != 0 ) { tx->SPV = height; - if ( tx->serialized != 0 ) + if ( strcmp(coinaddr,coin->smartaddr) != 0 && tx->serialized != 0 ) { free(tx->serialized); tx->serialized = 0; @@ -314,7 +320,7 @@ void LP_unspents_cache(char *symbol,char *addr,char *arraystr,int32_t updatedfla uint64_t LP_unspents_load(char *symbol,char *addr) { - char *arraystr; uint64_t balance = 0; int32_t i,n; cJSON *retjson,*item; struct iguana_info *coin; + 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 ) @@ -330,7 +336,8 @@ uint64_t LP_unspents_load(char *symbol,char *addr) balance += j64bits(item,"value"); } } - electrum_process_array(coin,coin->electrum,coin->smartaddr,retjson,1); + memset(zero.bytes,0,sizeof(zero)); + electrum_process_array(coin,coin->electrum,addr,retjson,1,zero,zero); free_json(retjson); } free(arraystr); diff --git a/iguana/exchanges/LP_coins.c b/iguana/exchanges/LP_coins.c index 7f43a005a..5293f12a4 100644 --- a/iguana/exchanges/LP_coins.c +++ b/iguana/exchanges/LP_coins.c @@ -99,7 +99,34 @@ void LP_statefname(char *fname,char *symbol,char *assetname,char *str,char *name { if ( confpath != 0 && confpath[0] != 0 ) { - strcpy(fname,confpath); + #if defined(NATIVE_WINDOWS) + // need to do something with "confpath":"`${process.env.HOME}`/.muecore/mue.conf" under Windows + char *ht = "`${process.env.USERHOME}`", *ht_start, *p_ht; + char ht_symbol[2]; + + ht_start = strstr(confpath, ht); + + if (ht_start) { + ht_start = ht_start + strlen(ht); + sprintf(fname, "%s\\", LP_getdatadir()); + p_ht = ht_start; + if (p_ht[0] == '/' && p_ht[1] == '.') { + p_ht += 2; + //printf("%s\n", p_ht); + while (p_ht[0] != '\0') { + if (p_ht[0] == '/') strcat(fname, "\\"); else + { + ht_symbol[0] = p_ht[0]; ht_symbol[1] = '\0'; + strcat(fname, ht_symbol); + } + p_ht++; + } + //printf("%s\n", fname); + } + } else strcpy(fname, confpath); + #else + strcpy(fname,confpath); + #endif return; } sprintf(fname,"%s",LP_getdatadir()); @@ -119,7 +146,7 @@ void LP_statefname(char *fname,char *symbol,char *assetname,char *str,char *name else if ( name != 0 ) { char name2[64]; -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(NATIVE_WINDOWS) int32_t len; strcpy(name2,name); name2[0] = toupper(name2[0]); @@ -164,7 +191,7 @@ uint16_t LP_userpass(char *userpass,char *symbol,char *assetname,char *confroot, sprintf(confname,"%s.conf",confroot); if ( 0 ) printf("%s (%s) %s confname.(%s) confroot.(%s)\n",symbol,assetname,name,confname,confroot); -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(NATIVE_WINDOWS) int32_t len; confname[0] = toupper(confname[0]); len = (int32_t)strlen(confname); @@ -187,7 +214,7 @@ uint16_t LP_userpass(char *userpass,char *symbol,char *assetname,char *confroot, cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif) { - struct electrum_info *ep; uint64_t balance; char wifstr[128],ipaddr[64]; uint8_t tmptype; bits256 checkkey; cJSON *item = cJSON_CreateObject(); + struct electrum_info *ep; bits256 zero; int32_t notarized; uint64_t balance; char wifstr[128],ipaddr[64]; uint8_t tmptype; bits256 checkkey; cJSON *item = cJSON_CreateObject(); jaddstr(item,"coin",coin->symbol); if ( showwif != 0 ) { @@ -200,7 +227,9 @@ 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)); + 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); @@ -230,6 +259,17 @@ cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif) jaddnum(item,"p2shtype",coin->p2shtype); jaddnum(item,"wiftype",coin->wiftype); 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); } @@ -314,6 +354,9 @@ uint16_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *asse char *name2; memset(coin,0,sizeof(*coin)); safecopy(coin->symbol,symbol,sizeof(coin->symbol)); + if ( strcmp(symbol,"PART") == 0 ) + coin->txversion = 160; + else coin->txversion = 1; coin->updaterate = (uint32_t)time(NULL); coin->isPoS = isPoS; coin->taddr = taddr; @@ -353,6 +396,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); } @@ -464,3 +512,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 d2f72406d..f1d3819c6 100644 --- a/iguana/exchanges/LP_commands.c +++ b/iguana/exchanges/LP_commands.c @@ -34,11 +34,11 @@ 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,*userpass,*base,*rel,*coin,*retstr = 0; int32_t changed,flag = 0; cJSON *retjson,*reqjson = 0; struct iguana_info *ptr; + char *method,*userpass,*base,*rel,*coin,*passphrase,*retstr = 0; int32_t authenticated=0,changed,flag = 0; cJSON *retjson,*reqjson = 0; struct iguana_info *ptr; method = jstr(argjson,"method"); if ( method != 0 && (strcmp(method,"addr_unspents") == 0 || strcmp(method,"uitem") == 0 || strcmp(method,"postutxos") == 0) ) return(0); -//printf("stats_JSON %s\n",method); +//printf("stats_JSON.(%s)\n",jprint(argjson,0)); /*if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 && (method == 0 || strcmp(method,"electrum") != 0) ) { if ( strcmp(ipaddr,"127.0.0.1") != 0 && argport >= 1000 ) @@ -68,8 +68,16 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r } if ( strcmp(method,"hello") == 0 ) { + //int32_t i; cJSON *array = cJSON_CreateArray(); + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jaddstr(retjson,"status","got hello"); + //for (i=0; i<10000; i++) + // jaddinum(array,i); + //jadd(retjson,"array",array); + return(jprint(retjson,1)); //printf("got hello from %s:%u\n",ipaddr!=0?ipaddr:"",argport); - return(clonestr("{\"result\":\"success\",\"status\":\"got hello\"}")); + //return(clonestr("{\"result\":\"success\",\"status\":\"got hello\"}")); } /*else if ( strcmp(method,"sendmessage") == 0 && jobj(argjson,"userpass") == 0 ) { @@ -94,29 +102,30 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r else if ( strcmp(method,"help") == 0 ) return(clonestr("{\"result\":\" \ available localhost RPC commands: \n \ -pricearray(base, rel, starttime=0, endtime=-1, timescale=60) -> [timestamp, avebid, aveask, highbid, lowask]\n\ -setprice(base, rel, price)\n\ +setprice(base, rel, price, broadcast=1)\n\ autoprice(base, rel, fixed, minprice, margin, refbase, refrel, factor, offset)*\n\ goal(coin=*, val=)\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\ +ticker(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, reset=0, [passphrase=])\n\ -bestfit(rel, relvolume)\n\ lastnonce()\n\ -buy(base, rel, price, relvolume, timeout=10, duration=3600, nonce, destpubkey="")\n\ -sell(base, rel, price, basevolume, timeout=10, duration=3600, nonce, destpubkey="")\n\ +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\ @@ -127,8 +136,11 @@ 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\ +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\ @@ -146,7 +158,9 @@ bot_settings(botid, newprice, newvolume)\n\ bot_status(botid)\n\ bot_stop(botid)\n\ bot_pause(botid)\n\ -bot_resume(botid)\n\ +instantdex_deposit(weeks, amount, broadcast=1)\n\ +instantdex_claim()\n\ +jpg(srcfile, destfile, power2=7, passphrase, data="", required)\n\ \"}")); //sell(base, rel, price, basevolume, timeout=10, duration=3600)\n\ @@ -160,18 +174,32 @@ bot_resume(botid)\n\ { if ( G.USERPASS_COUNTER == 0 ) { + char pub33str[67]; G.USERPASS_COUNTER = 1; retjson = cJSON_CreateObject(); jaddstr(retjson,"userpass",G.USERPASS); jaddbits256(retjson,"mypubkey",G.LP_mypub25519); + init_hexbytes_noT(pub33str,G.LP_pubsecp,33); + jaddstr(retjson,"pubsecp",pub33str); jadd(retjson,"coins",LP_coinsjson(LP_showwif)); return(jprint(retjson,1)); } - if ( strcmp(method,"passphrase") != 0 && ((userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,G.USERPASS) != 0) ) + // if passphrase api and passphrase is right, ignore userpass, use hass of passphrase + if ( strcmp(method,"passphrase") == 0 && (passphrase= jstr(argjson,"passphrase")) != 0 ) + { + bits256 passhash; char str[65],str2[65]; + vcalc_sha256(0,passhash.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); + if ( bits256_cmp(passhash,G.LP_passhash) == 0 ) + authenticated = 1; + else printf("passhash %s != G %s\n",bits256_str(str,passhash),bits256_str(str2,G.LP_passhash)); + } + if ( authenticated == 0 && ((userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,G.USERPASS) != 0) ) return(clonestr("{\"error\":\"authentication error you need to make sure userpass is set\"}")); - jdelete(argjson,"userpass"); + if ( jobj(argjson,"userpass") != 0 ) + jdelete(argjson,"userpass"); if ( strcmp(method,"passphrase") == 0 ) { + char coinaddr[64],pub33str[67]; G.USERPASS_COUNTER = 1; if ( LP_passphrase_init(jstr(argjson,"passphrase"),jstr(argjson,"gui")) < 0 ) return(clonestr("{\"error\":\"couldnt change passphrase\"}")); @@ -180,9 +208,39 @@ bot_resume(botid)\n\ jaddstr(retjson,"result","success"); jaddstr(retjson,"userpass",G.USERPASS); jaddbits256(retjson,"mypubkey",G.LP_mypub25519); + init_hexbytes_noT(pub33str,G.LP_pubsecp,33); + jaddstr(retjson,"pubsecp",pub33str); + 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,"instantdex_deposit") == 0 ) + { + if ( (ptr= LP_coinsearch("KMD")) != 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("{\"error\":\"cant find KMD\"}")); + } + else if ( strcmp(method,"instantdex_claim") == 0 ) + { + if ( (ptr= LP_coinsearch("KMD")) != 0 ) + { + return(LP_instantdex_claim(ptr)); + } + return(clonestr("{\"error\":\"cant find KMD\"}")); + } + else if ( strcmp(method,"jpg") == 0 ) + { + return(LP_jpg(jstr(argjson,"srcfile"),jstr(argjson,"destfile"),jint(argjson,"power2"),jstr(argjson,"passphrase"),jstr(argjson,"data"),jint(argjson,"required"))); + } /*else if ( strcmp(method,"sendmessage") == 0 ) { if ( jobj(argjson,"method2") == 0 ) @@ -224,15 +282,13 @@ bot_resume(botid)\n\ 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\"}")); } @@ -240,16 +296,13 @@ bot_resume(botid)\n\ { return(LP_portfolio()); } - else if ( strcmp(method,"parselog") == 0 ) + else if ( strcmp(method,"statsdisp") == 0 ) { - bits256 zero; int32_t n = LP_statslog_parse(); - memset(zero.bytes,0,sizeof(zero)); - return(LP_statslog_disp(n,2000000000,2000000000,"",zero)); + 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,"statsdisp") == 0 ) + else if ( strcmp(method,"ticker") == 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(LP_ticker(jstr(argjson,"base"),jstr(argjson,"rel"))); } else if ( strcmp(method,"secretaddresses") == 0 ) { @@ -262,12 +315,29 @@ bot_resume(botid)\n\ { uint32_t requestid,quoteid; if ( (requestid= juint(argjson,"requestid")) != 0 && (quoteid= juint(argjson,"quoteid")) != 0 ) - return(basilisk_swapentry(requestid,quoteid)); + return(basilisk_swapentry(requestid,quoteid,1)); else if ( coin[0] != 0 ) return(basilisk_swapentries(coin,0,jint(argjson,"limit"))); else if ( base[0] != 0 && rel[0] != 0 ) return(basilisk_swapentries(base,rel,jint(argjson,"limit"))); - else return(basilisk_swaplist(0,0)); + else 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\"}")); } else if ( (retstr= LP_istradebots_command(ctx,pubsock,method,argjson)) != 0 ) return(retstr); @@ -276,10 +346,24 @@ bot_resume(botid)\n\ double price,bid,ask; if ( strcmp(method,"autoprice") == 0 ) { - if ( LP_autoprice(base,rel,argjson) < 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"); @@ -289,22 +373,10 @@ bot_resume(botid)\n\ return(clonestr("{\"error\":\"couldnt set price\"}")); //else if ( LP_mypriceset(&changed,rel,base,1./price) < 0 ) // return(clonestr("{\"error\":\"couldnt set price\"}")); - else return(LP_pricepings(ctx,myipaddr,LP_mypubsock,base,rel,price * LP_profitratio)); - } - else if ( strcmp(method,"pricearray") == 0 ) - { - uint32_t firsttime; - if ( base[0] != 0 && rel[0] != 0 ) - { - if ( (firsttime= juint(argjson,"firsttime")) < time(NULL)-30*24*3600 ) - firsttime = (uint32_t)(time(NULL)-30*24*3600); - return(jprint(LP_pricearray(base,rel,firsttime,juint(argjson,"lasttime"),jint(argjson,"timescale")),1)); - } else return(clonestr("{\"error\":\"pricearray needs base and rel\"}")); + else if ( 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 ) @@ -336,13 +408,13 @@ bot_resume(botid)\n\ } else return(clonestr("{\"error\":\"no price set\"}")); } } - else if ( rel[0] != 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[0] != 0 ) { if ( strcmp(method,"enable") == 0 ) @@ -353,21 +425,29 @@ bot_resume(botid)\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; - if ( ptr->smartaddr[0] != 0 ) - LP_unspents_load(coin,ptr->smartaddr); - if ( LP_getheight(ptr) <= 0 ) + 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 LP_unspents_load(coin,ptr->smartaddr); + } + else + { + if ( ptr->smartaddr[0] != 0 ) + LP_unspents_load(coin,ptr->smartaddr); + LP_unspents_load(coin,ptr->smartaddr); + if ( strcmp(ptr->symbol,"KMD") == 0 ) + LP_importaddress("KMD",BOTS_BONDADDRESS); + } + if ( 0 && strcmp(coin,"BCH") == 0 ) + test_validate(ptr,"010000000110b365ea6b8a9f2d56dc12de868e382dc787b2e29355f9b357dcf764c5e29cb1010000006b483045022100c605b993f1db5f31046ebb9065bea0a047f478342bbad8fcfc6af81d05236bd502206e9993a737a8814b935b5e522e750c915e7d37e3bd8367f087d4510f66acac47412102ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92ffffffff014bc22900000000001976a91459fdba29ea85c65ad90f6d38f7a6646476b26b1688ac00000000"); array = cJSON_CreateArray(); jaddi(array,LP_coinjson(ptr,0)); return(jprint(array,1)); @@ -389,7 +469,8 @@ bot_resume(botid)\n\ { if ( (ptr= LP_coinsearch(coin)) != 0 ) { - char *coinaddr; + char *coinaddr; bits256 zero; + memset(zero.bytes,0,sizeof(zero)); if ( (coinaddr= jstr(argjson,"address")) != 0 ) { if ( coinaddr[0] != 0 ) @@ -397,20 +478,13 @@ bot_resume(botid)\n\ LP_address(ptr,coinaddr); if ( strcmp(coinaddr,ptr->smartaddr) == 0 && bits256_nonz(G.LP_privkey) != 0 ) { - LP_listunspent_issue(coin,coinaddr,2); - LP_privkey_init(-1,ptr,G.LP_privkey,G.LP_mypub25519); - //LP_smartutxos_push(ptr); - if ( ptr->electrum != 0 ) - return(LP_unspents_filestr(coin,ptr->smartaddr)); - else return(jprint(LP_address_utxos(ptr,coinaddr,1),1)); - } - else - { - return(clonestr("{\"error\":\"not my address\"}")); + 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(jprint(LP_address_utxos(ptr,coinaddr,1),1)); - } else return(clonestr("{\"error\":\"no address specified\"}")); + } + return(clonestr("{\"error\":\"no address specified\"}")); } else return(clonestr("{\"error\":\"cant find coind\"}")); } else if ( strcmp(method,"balance") == 0 ) @@ -433,7 +507,7 @@ bot_resume(botid)\n\ } else if ( strcmp(method,"getrawtransaction") == 0 ) { - return(jprint(LP_gettx(coin,jbits256(argjson,"txid")),1)); + return(jprint(LP_gettx(coin,jbits256(argjson,"txid"),0),1)); } else if ( strcmp(method,"withdraw") == 0 ) { @@ -480,7 +554,11 @@ bot_resume(botid)\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; @@ -500,9 +578,11 @@ bot_resume(botid)\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)); } } @@ -539,18 +619,58 @@ bot_resume(botid)\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; @@ -569,7 +689,7 @@ bot_resume(botid)\n\ 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,"wantnotify") == 0 ) diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index 3bea50380..390e473ae 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -21,11 +21,19 @@ #ifndef LP_INCLUDE_H #define LP_INCLUDE_H +#ifdef FROMGUI +#define printf dontprintf + +voind dontprintf(char *formatstr,...) {} +#endif + #define LP_MAJOR_VERSION "0" #define LP_MINOR_VERSION "1" -#define LP_BUILD_NUMBER "15256" +#define LP_BUILD_NUMBER "17752" #define LP_BARTERDEX_VERSION 1 -#define LP_MAGICBITS 8 +#define LP_MAGICBITS 1 + +#define LP_DONT_IMPORTPRIVKEY #ifdef FROM_JS #include @@ -43,23 +51,25 @@ void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping #define LP_MAXVINS 64 #define LP_HTTP_TIMEOUT 3 // 1 is too small due to edge cases of time(NULL) -#define LP_AUTOTRADE_TIMEOUT 30 -#define LP_RESERVETIME (LP_AUTOTRADE_TIMEOUT * 2) -#define ELECTRUM_TIMEOUT 7 +#define LP_AUTOTRADE_TIMEOUT 60 +#define LP_RESERVETIME 600 //(LP_AUTOTRADE_TIMEOUT * 2) +#define ELECTRUM_TIMEOUT 13 #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 ? 128 : 64) -#define LP_MINDESIRED_UTXOS (IAMLP != 0 ? 32 : 16) +#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 @@ -82,7 +92,7 @@ void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping #define LP_SWAPSTEP_TIMEOUT 30 #define LP_MIN_TXFEE 10000 #define LP_MINVOL 20 -#define LP_MINCLIENTVOL 100 +#define LP_MINCLIENTVOL 200 #define LP_MINSIZE_TXFEEMULT 10 #define LP_REQUIRED_TXFEE 0.8 @@ -98,6 +108,11 @@ void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping #define TIERNOLAN_RMD160 "daedddd8dbe7a2439841ced40ba9c3d375f98146" #define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu" #define INSTANTDEX_KMD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf" +#define BOTS_BONDADDRESS "RNdqHx26GWy9bk8MtmH1UiXjQcXE4RKK2P" +#define BOTS_BONDPUBKEY33 "03e641d22e1ff5a7d45c8880537e0b0a114d7b9fee2c18a6b4a8a80b6285292990" +#define LP_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 @@ -113,15 +128,29 @@ void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping #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; }; @@ -155,12 +184,12 @@ struct vin_info 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; @@ -266,18 +295,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 numutxos,longestchain,firstrefht,firstscanht,lastscanht,bussock,height; uint16_t busport; - uint32_t loadedcache,electrumlist,lastunspent,importedprivkey,lastpushtime,lastutxosync,addr_listunspent_requested,lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,obooktime; + int32_t numutxos,notarized,longestchain,firstrefht,firstscanht,lastscanht,bussock,height; uint16_t busport; + uint32_t txversion,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[128],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; int32_t privkeydepth; - bits256 cachedtxid; uint8_t *cachedtxiddata; int32_t cachedtxidlen; - bits256 cachedmerkle; int32_t cachedmerkleheight; + 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; }; @@ -288,7 +317,7 @@ struct LP_utxobob { struct _LP_utxoinfo utxo,deposit; }; struct LP_utxoalice { struct _LP_utxoinfo utxo,fee; }; -struct LP_utxoswap { bits256 otherpubkey; uint64_t satoshis; }; +//struct LP_utxoswap { bits256 otherpubkey; uint64_t satoshis; }; struct LP_utxoinfo { @@ -296,7 +325,8 @@ 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)]; @@ -316,11 +346,11 @@ 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 @@ -337,6 +367,7 @@ 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,tradeid; int32_t vout,vout2,destvout,feevout,pair; @@ -357,11 +388,10 @@ struct basilisk_swap 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 @@ -372,15 +402,30 @@ struct LP_pubkey_quote uint8_t baseind,relind,numutxos,scale; }; +struct LP_swapstats +{ + UT_hash_handle hh; + struct LP_quoteinfo Q; + bits256 bobdeposit,alicepayment,bobpayment,paymentspent,Apaymentspent,depositspent; + 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; struct LP_pubkey_quote *quotes; - //float matrix[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS]; - //uint32_t timestamps[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS]; - uint32_t timestamp,numerrors,lasttime; + 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; }; @@ -398,7 +443,20 @@ struct electrum_info uint8_t buf[]; }; -int32_t LP_pubkey_sigcheck(struct LP_pubkeyinfo *pubp,cJSON *item); +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); @@ -406,38 +464,41 @@ 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(bits256 txid,int32_t vout); int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2); int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsock,int32_t pullsock); +int64_t LP_listunspent_parseitem(struct iguana_info *coin,bits256 *txidp,int32_t *voutp,int32_t *heightp,cJSON *item); void LP_unspents_cache(char *symbol,char *addr,char *arraystr,int32_t updatedflag); uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired); //void LP_utxo_clientpublish(struct LP_utxoinfo *utxo); int32_t LP_coinbus(uint16_t coin_busport); int32_t LP_nanomsg_recvs(void *ctx); +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); +void LP_autoprices_update(char *method,char *base,double basevol,char *rel,double relvol); cJSON *LP_cache_transaction(struct iguana_info *coin,bits256 txid,uint8_t *serialized,int32_t len); cJSON *LP_transaction_fromdata(struct iguana_info *coin,bits256 txid,uint8_t *serialized,int32_t len); uint64_t LP_RTsmartbalance(struct iguana_info *coin); -int32_t LP_getheight(struct iguana_info *coin); +int32_t LP_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); @@ -449,9 +510,13 @@ 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 test_validate(struct iguana_info *coin,char *signedtx); +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); @@ -460,8 +525,9 @@ cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJS 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); +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); @@ -470,15 +536,22 @@ 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); +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(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 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..ef6081efa --- /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 ( 0 && 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_mmjson.c b/iguana/exchanges/LP_mmjson.c new file mode 100644 index 000000000..1239c4180 --- /dev/null +++ b/iguana/exchanges/LP_mmjson.c @@ -0,0 +1,708 @@ +/****************************************************************************** + * 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_mmjson.c +// marketmaker +// +#define MMJSON_IPADDR 255 +#define MMJSON_BITS256 254 +#define MMJSON_SECP33 253 +#define MMJSON_SIG 252 +#define MMJSON_RMD160 251 +#define MMJSON_DECIMAL8 250 +#define MMJSON_DECIMAL8STR 249 +#define MMJSON_DECIMAL16 248 +#define MMJSON_DECIMAL16STR 247 +#define MMJSON_DECIMAL24 246 +#define MMJSON_DECIMAL24STR 245 +#define MMJSON_DECIMAL32 244 +#define MMJSON_DECIMAL32STR 243 +#define MMJSON_DECIMAL40 242 +#define MMJSON_DECIMAL40STR 241 +#define MMJSON_DECIMAL48 240 +#define MMJSON_DECIMAL48STR 239 +#define MMJSON_DOUBLE 238 +#define MMJSON_DECIMAL64 237 +#define MMJSON_DECIMAL64STR 236 +#define MMJSON_TIMESTAMP 235 +#define MMJSON_TIMEDIFF8 234 +#define MMJSON_TIMEDIFF16 233 +#define MMJSON_ZERO 232 +#define MMJSON_ZEROSTR 231 +#define MMJSON_COIN 230 +#define MMJSON_STRING 229 +#define MMJSON_ARRAY8 228 +#define MMJSON_ARRAY16 227 +#define MMJSON_ARRAY32 226 +#define MMJSON_BOUNDARY 98 + +int32_t MM_numfields; +char *MM_fields[256] = +{ + "timestamp", "getdPoW", "dPoW", "aliceid", "src", "base", "basevol", "dest", "rel", "relvol", "price", "requestid", "quoteid", "finished", "expired", "bobdeposit", "alicepayment", "bobpayment", "paymentspent", "Apaymentspent", "depositspent", "ind", "method", "swapstatus", "method2", "gettradestatus", "coin", "rmd160", "pub", "pubsecp", "sig", "session", "notify", "pubkey", "price64", "credits", "utxocoin", "n", "bal", "min", "max", "postprice", "notarized", "notarizedhash", "notarizationtxid", "wantnotify", "isLP", "gui", "nogui", "tradeid", "address", "txid", "vout", "srchash", "txfee", "quotetime", "satoshis", "desthash", "txid2", "vout2", "destaddr", "desttxid", "destvout", "feetxid", "feevout", "desttxfee", "destsatoshis", "pending", "reserved", "broadcast", "ismine", "simplegui", "request", "proof", "connect", "expiration", "iambob", "Bgui", "", "Agui", "bob", "srcamount", "bobtxfee", "alice", "destamount", "alicetxfee", "sentflags", "values", "result", "success", "status", "finishtime", "tradestatus", "pair", "connected", "warning", "critical", "endcritical", +}; + +char *MM_coins[256] = +{ + "KMD", "BTC", "CRC", "VOT", "INN", "MOON", "CRW", "EFL", "GBX", "BCO", "BLK", "BTG", "BCH", "ABY", "STAK", "XZC", "QTUM", "PURA", "DSR", "MNZ", "BTCZ", "MAGA", "BSD", "IOP", "BLOCK", "CHIPS", "888", "ARG", "GLT", "ZER", "HODLC", "UIS", "HUC", "PIVX", "BDL", "ARC", "ZCL", "VIA", "ERC", "FAIR", "FLO", "SXC", "CREA", "TRC", "BTA", "SMC", "NMC", "NAV", "EMC2", "SYS", "I0C", "DASH", "STRAT", "MUE", "MONA", "XMY", "MAC", "BTX", "XRE", "LBC", "SIB", "VTC", "REVS", "JUMBLR", "DOGE", "HUSH", "ZEC", "DGB", "ZET", "GAME", "LTC", "SUPERNET", "WLC", "PANGEA", "DEX", "BET", "CRYPTO", "HODL", "MSHARK", "BOTS", "MGW", "COQUI", "KV", "CEAL", "MESH", +}; + +int32_t mmjson_coinfind(char *symbol) +{ + int32_t i; + for (i=0; i>= 8; + } + } + else + { + for (i=n-1; i>=0; i--) + { + l <<= 8; + l |= buf[i]; + } + *longp = l; + } + return(n); +} + +int32_t MMJSON_decodeitem(cJSON *lineobj,uint8_t *linebuf,int32_t i,int32_t len,char *fieldstr,uint32_t *timestampp) +{ + int32_t c,valind,j; char tmpstr[64],ipaddr[64],hexstr[256],arbstr[8192]; uint64_t l; + switch ( (valind= linebuf[i++]) ) + { + case MMJSON_IPADDR: + i += MMJSON_rwnum(0,&linebuf[i],&l,4); + expand_ipbits(ipaddr,(uint32_t)l); + jaddstr(lineobj,fieldstr,ipaddr); + break; + case MMJSON_BITS256: + init_hexbytes_noT(hexstr,&linebuf[i],32); + i += 32; + jaddstr(lineobj,fieldstr,hexstr); + break; + case MMJSON_SECP33: + init_hexbytes_noT(hexstr,&linebuf[i],33); + i += 33; + jaddstr(lineobj,fieldstr,hexstr); + break; + case MMJSON_SIG: + init_hexbytes_noT(hexstr,&linebuf[i],65); + i += 65; + jaddstr(lineobj,fieldstr,hexstr); + break; + case MMJSON_RMD160: + init_hexbytes_noT(hexstr,&linebuf[i],20); + i += 20; + jaddstr(lineobj,fieldstr,hexstr); + break; + case MMJSON_DECIMAL8: + l = linebuf[i++]; + jaddnum(lineobj,fieldstr,l); + break; + case MMJSON_DECIMAL8STR: + l = linebuf[i++]; + jadd64bits(lineobj,fieldstr,l); + break; + case MMJSON_DECIMAL16: + i += MMJSON_rwnum(0,&linebuf[i],&l,2); + jaddnum(lineobj,fieldstr,l); + break; + case MMJSON_DECIMAL16STR: + i += MMJSON_rwnum(0,&linebuf[i],&l,2); + jadd64bits(lineobj,fieldstr,l); + break; + case MMJSON_DECIMAL24: + i += MMJSON_rwnum(0,&linebuf[i],&l,3); + jaddnum(lineobj,fieldstr,l); + break; + case MMJSON_DECIMAL24STR: + i += MMJSON_rwnum(0,&linebuf[i],&l,3); + sprintf(tmpstr,"%llu",(long long)l); + jaddstr(lineobj,fieldstr,tmpstr); + break; + case MMJSON_DECIMAL32: + i += MMJSON_rwnum(0,&linebuf[i],&l,4); + //printf("decimal32.%u %08x\n",(uint32_t)l,(uint32_t)l); + jaddnum(lineobj,fieldstr,l); + break; + case MMJSON_DECIMAL32STR: + i += MMJSON_rwnum(0,&linebuf[i],&l,4); + //printf("decimal32.%u %08x\n",(uint32_t)l,(uint32_t)l); + jadd64bits(lineobj,fieldstr,l); + break; + case MMJSON_DECIMAL40: + i += MMJSON_rwnum(0,&linebuf[i],&l,5); + jaddnum(lineobj,fieldstr,l); + break; + case MMJSON_DECIMAL40STR: + i += MMJSON_rwnum(0,&linebuf[i],&l,5); + jadd64bits(lineobj,fieldstr,l); + break; + case MMJSON_DECIMAL48: + i += MMJSON_rwnum(0,&linebuf[i],&l,6); + jaddnum(lineobj,fieldstr,l); + break; + case MMJSON_DECIMAL48STR: + i += MMJSON_rwnum(0,&linebuf[i],&l,6); + jadd64bits(lineobj,fieldstr,l); + break; + case MMJSON_DOUBLE: + i += MMJSON_rwnum(0,&linebuf[i],&l,8); + //printf("double %llu -> %.8f\n",(long long)l,dstr(l)); + jaddnum(lineobj,fieldstr,dstr(l)); + break; + case MMJSON_DECIMAL64: + i += MMJSON_rwnum(0,&linebuf[i],&l,8); + jadd64bits(lineobj,fieldstr,l); + break; + case MMJSON_DECIMAL64STR: + i += MMJSON_rwnum(0,&linebuf[i],&l,8); + jadd64bits(lineobj,fieldstr,l); + break; + case MMJSON_TIMESTAMP: + if ( *timestampp == 0 ) + { + i += MMJSON_rwnum(0,&linebuf[i],&l,4); + *timestampp = (uint32_t)l; + jaddnum(lineobj,fieldstr,l); + } + else + { + printf("timestamp %u already exists\n",*timestampp); + free_json(lineobj); + return(-1); + } + break; + case MMJSON_TIMEDIFF8: + jaddnum(lineobj,fieldstr,*timestampp + linebuf[i++]); + break; + case MMJSON_TIMEDIFF16: + i += MMJSON_rwnum(0,&linebuf[i],&l,2); + jaddnum(lineobj,fieldstr,*timestampp + l); + break; + case MMJSON_ZERO: + jaddnum(lineobj,fieldstr,0); + break; + case MMJSON_ZEROSTR: + //printf("%s.zerostr\n",fieldstr); + jadd64bits(lineobj,fieldstr,0); + break; + case MMJSON_COIN: + jaddstr(lineobj,fieldstr,MM_coins[linebuf[i++]]); + break; + case MMJSON_STRING: + j = 0; + while ( (c= linebuf[i++]) != 0 ) + { + if ( i > len ) + { + printf("string overflow i.%d vs len.%d\n",i,len); + free_json(lineobj); + return(-1); + } + arbstr[j++] = c; + } + arbstr[j] = 0; + jaddstr(lineobj,fieldstr,arbstr); + break; + default: + if ( valind < MMJSON_BOUNDARY ) + jaddstr(lineobj,fieldstr,MM_fields[valind]); + else + { + printf("%s unhandled valind.%d k.%d len.%d (%s)\n",fieldstr,valind,i,len,jprint(lineobj,0)); + free_json(lineobj); + return(-1); + } + break; + } + return(i); +} + +char *MMJSON_decode(uint8_t *linebuf,int32_t len) +{ + uint32_t timestamp = 0; char *fieldstr; uint64_t l; int32_t ind,i=0,j,m=-1; cJSON *obj,*item,*array,*lineobj = cJSON_CreateObject(); + while ( i+1 < len ) + { + //printf("ind.%d i.%d vs len.%d\n",linebuf[i],i,len); + if ( (ind= linebuf[i++]) >= MMJSON_BOUNDARY ) + { + if ( ind != MMJSON_STRING ) + { + printf("illegal field ind.%d (%s)\n",ind,jprint(lineobj,0)); + free_json(lineobj); + return(0); + } + else + { + fieldstr = (char *)&linebuf[i++]; + while ( linebuf[i] != 0 ) + i++; + i++; + } + } else fieldstr = MM_fields[ind]; + if ( linebuf[i] == MMJSON_ARRAY8 ) + { + i++; + m = linebuf[i++]; + } + else if ( linebuf[i] == MMJSON_ARRAY16 ) + { + i++; + i += MMJSON_rwnum(0,&linebuf[i],&l,2); + m = (int32_t)l; + } + else if ( linebuf[i] == MMJSON_ARRAY32 ) + { + i++; + i += MMJSON_rwnum(0,&linebuf[i],&l,4); + m = (int32_t)l; + } else m = -1; + if ( m >= 0 ) + { + //printf("%s i.%d m.%d\n",fieldstr,i,m); + array = cJSON_CreateArray(); + for (j=0; j= 0 ) + { + fieldstr = MM_fields[ind]; + if ( strcmp("utxocoin",fieldstr) == 0 || strcmp("alice",fieldstr) == 0 || strcmp("bob",fieldstr) == 0 || strcmp("base",fieldstr) == 0 || strcmp("rel",fieldstr) == 0 || strcmp("coin",fieldstr) == 0 || strcmp("txfee",fieldstr) == 0 || strcmp("desttxfee",fieldstr) == 0 || strcmp("price64",fieldstr) == 0 || strcmp("satoshis",fieldstr) == 0 || strcmp("destsatoshis",fieldstr) == 0 ) + isstr = 1; + else isstr = 0; + } + //printf("%s.(%s) k.%d\n",fieldstr,v,k); + if ( (valind= mmfind(v)) >= 0 ) + { + linebuf[k++] = valind; + return(k); + } + else if ( strcmp("0",v) == 0 ) + { + if ( isstr != 0 ) + linebuf[k++] = MMJSON_ZEROSTR; + else linebuf[k++] = MMJSON_ZERO; + return(k); + } + for (j=dots=0; v[j]!=0; j++) + { + if ( (v[j] < '0' || v[j] > '9') && v[j] != '.' ) + break; + else if ( v[j] == '.' ) + dots++; + } + if ( dots == 3 && v[j] == 0 && strlen(v) < 17 && is_ipaddr(v) != 0 ) + { + //printf(" "); + linebuf[k++] = MMJSON_IPADDR; + l = calc_ipbits(v); + k += MMJSON_rwnum(1,&linebuf[k],&l,4); + } + else if ( dots == 1 && v[j] == 0 ) + { + if ( (val= atof(v)) > SMALLVAL ) + { + l = SATOSHIDEN * (val + 0.000000005); + sprintf(checkstr,"%.8f",dstr(l)); + if ( strcmp(checkstr,v) == 0 ) + { + //printf(" "); + linebuf[k++] = MMJSON_DOUBLE; + k += MMJSON_rwnum(1,&linebuf[k],&l,8); + } else printf("ERR.<%s %s> ",v,checkstr); + } + } + else if ( (len= is_hexstr(v,0)) == 64 ) + { + //printf(" "); + linebuf[k++] = MMJSON_BITS256; + decode_hex(&linebuf[k],32,v), k += 32; + } + else if ( len == 66 ) + { + //printf(" "); + linebuf[k++] = MMJSON_SECP33; + decode_hex(&linebuf[k],33,v), k += 33; + } + else if ( len == 65*2 ) + { + //printf(" "); + linebuf[k++] = MMJSON_SIG; + decode_hex(&linebuf[k],65,v), k += 65; + } + else if ( len == 40 ) + { + //printf(" "); + linebuf[k++] = MMJSON_RMD160; + decode_hex(&linebuf[k],20,v), k += 20; + } + else if ( len > 40 ) + { + printf("ERR. ",len/2); + } + else if ( is_decimalstr(v) != 0 && (l= calc_nxt64bits(v)) > 0 ) + { + if ( l < 0x100 ) + { + //printf(" "); + if ( l == 0 ) + { + linebuf[k++] = isstr != 0 ? MMJSON_ZEROSTR : MMJSON_ZERO; + } + else + { + linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL8STR : MMJSON_DECIMAL8; + linebuf[k++] = (uint8_t)l; + } + } + else if ( l < 0x10000 ) + { + //printf(" "); + linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL16STR : MMJSON_DECIMAL16; + k += MMJSON_rwnum(1,&linebuf[k],&l,2); + } + else if ( l < 0x1000000 ) + { + linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL24STR : MMJSON_DECIMAL24; + //printf("decimal24 %llu %s (%s) %d\n",(long long)l,v,fieldstr,linebuf[k-1]); + k += MMJSON_rwnum(1,&linebuf[k],&l,3); + } + else if ( l < 0x100000000LL ) + { + if ( v[0] != '"' && *timestampp == 0 && strcmp(fieldstr,"timestamp") == 0 ) + { + *timestampp = (uint32_t)atol(v); + //printf(" "); + linebuf[k++] = MMJSON_TIMESTAMP; + l = *timestampp; + k += MMJSON_rwnum(1,&linebuf[k],&l,4); + } + else if ( v[0] != '"' && *timestampp != 0 && (diff= ((uint32_t)atol(v)-*timestampp)) < 0x100 && diff >= 0 ) + { + //printf(" "); + linebuf[k++] = MMJSON_TIMEDIFF8; + linebuf[k++] = (uint8_t)diff; + } + else if ( v[0] != '"' && *timestampp != 0 && (diff= ((uint32_t)atol(v)-*timestampp)) < 0x10000 && diff >= 0 ) + { + //printf(" "); + linebuf[k++] = MMJSON_TIMEDIFF16; + l = diff; + k += MMJSON_rwnum(1,&linebuf[k],&l,2); + } + else + { + //printf(".%u %08x\n",(uint32_t)l,(uint32_t)l); + linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL32STR : MMJSON_DECIMAL32; + k += MMJSON_rwnum(1,&linebuf[k],&l,4); + } + } + else if ( l < 0x10000000000LL ) + { + //printf(" "); + linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL40STR : MMJSON_DECIMAL40; + k += MMJSON_rwnum(1,&linebuf[k],&l,5); + } + else if ( l < 0x1000000000000LL ) + { + //printf(" "); + linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL48STR : MMJSON_DECIMAL48; + k += MMJSON_rwnum(1,&linebuf[k],&l,6); + } + //else if ( l < 0x100000000000000LL ) + // printf(" "); + else + { + //printf(" "); + linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL64STR : MMJSON_DECIMAL64; + k += MMJSON_rwnum(1,&linebuf[k],&l,8); + } + } + else + { + if ( (ind= mmfind(v)) >= 0 ) + linebuf[k++] = ind; + else + { + for (j=0; v[j]!=0; j++) + { + if ( v[j] >= 'a' && v[j] <= 'z' ) + continue; + else break; + } + if ( v[j] == 0 ) + { + printf("unexpected missing string value.(%s)\n",v); + //ind = mmadd(v); + //printf("%s.<%s>.%d ",s,v,ind); + //linebuf[k++] = ind; + linebuf[k++] = MMJSON_STRING; + memcpy(&linebuf[k],v,strlen(v)+1); + k += (int32_t)strlen(v) + 1; + } + else + { + for (j=0; v[j]!=0; j++) + { + if ( v[j] >= 'A' && v[j] <= 'Z' ) + continue; + else break; + } + if ( v[j] == 0 && (coinind= mmjson_coinfind(v)) >= 0 ) + { + //printf(" "); + linebuf[k++] = MMJSON_COIN; + linebuf[k++] = coinind; + } + /*else if ( strlen(v) == 34 ) + { + printf(" "); + k += 22; + }*/ + else + { + linebuf[k++] = MMJSON_STRING; + if ( v[0] == '"' ) + { + v++; + v[strlen(v)-1] = 0; + } + //printf("str.<%s> ",v); + memcpy(&linebuf[k],v,strlen(v)+1); + k += (int32_t)strlen(v) + 1; + } + } + } + } + return(k); +} + +int32_t MMJSON_encode(uint8_t *linebuf,char *line) +{ + uint32_t timestamp; uint64_t l; char *decodestr,*s,*v=0; cJSON *lineobj,*array,*ptr; int32_t k=0,m,i,asize,ind,z,allocv_flag; + timestamp = 0; + if ( (lineobj= cJSON_Parse(line)) != 0 ) + { + if ( line[strlen(line)-1] == '\n' ) + line[strlen(line)-1] = 0; + //printf("%s\n",jprint(lineobj,0)); + if ( (m= cJSON_GetArraySize(lineobj)) > 0 ) + { + ptr = lineobj->child; + for (i=0; inext) + { + allocv_flag = 0; + s = jfieldname(ptr); + if ( (ind= mmfind(s)) < 0 ) + { + printf("missing field.(%s) add to MM_fields[]\n",s); + linebuf[k++] = MMJSON_STRING; + memcpy(&linebuf[k],s,strlen(s)+1); + k += (int32_t)strlen(s) + 1; + //ind = mmadd(s); + } else linebuf[k++] = ind; + //printf("%s ",s); + if ( (array= jobj(lineobj,s)) != 0 && is_cJSON_Array(array) != 0 ) + { + asize = cJSON_GetArraySize(array); + if ( asize < 0x100 ) + { + linebuf[k++] = MMJSON_ARRAY8; + linebuf[k++] = asize; + } + else if ( asize < 0x10000 ) + { + linebuf[k++] = MMJSON_ARRAY16; + l = asize; + k += MMJSON_rwnum(1,&linebuf[k],&l,2); + } + else + { + linebuf[k++] = MMJSON_ARRAY32; + l = asize; + k += MMJSON_rwnum(1,&linebuf[k],&l,4); + } + for (z=0; z (%s)\n",k,line,decodestr==0?"":decodestr); + if ( decodestr != 0 ) + free(decodestr); + return(-1); + } //else printf("decoded\n"); + free(decodestr); + } + return(k); +} + +#ifndef FROM_MARKETMAKER +#define packetout "/Users/mac/mmjson/packet.out" +#define packetlog "/Users/mac/mmjson/packet.log" + +int main(int argc, const char * argv[]) +{ + FILE *fp,*outfp; uint8_t linebuf[8192]; char line[8192],str[65]; int32_t i,k,compressed=0,n=0,total = 0; + outfp = fopen(packetout,"wb"); + if ( (fp= fopen(packetlog,"rb")) != 0 ) + { + while ( fgets(line,sizeof(line),fp) > 0 ) + { + n++; + total += strlen(line); + if ( (k= MMJSON_encode(linebuf,line)) > 0 ) + { + //printf("\n"); + if ( outfp != 0 ) + fwrite(linebuf,1,k,outfp); + compressed += k; + } + else + { + compressed += strlen(line); + //printf("error parsing.(%s)\n",line); + } + } + fclose(fp); + if ( outfp != 0 ) + { + uint8_t *data,*bits; int32_t numbits; bits256 seed; long fsize = ftell(outfp); + fclose(outfp); + if ( (0) && (outfp= fopen(packetout,"rb")) != 0 ) + { + data = calloc(1,fsize); + bits = calloc(1,fsize); + if ( fread(data,1,fsize,outfp) == fsize ) + { + memset(seed.bytes,0,sizeof(seed)); + decode_hex(seed.bytes,32,"ffffff070000810478800084000800b200101400002001400404844402d29fc4"); + numbits = ramcoder_compress(bits,(int32_t)fsize,data,(int32_t)fsize,seed); + fclose(outfp); + printf("numbits.%d %d bytes %.1f seed.%s\n",numbits,numbits/8+1,(double)compressed/(numbits/8),bits256_str(str,seed)); + } + } + } + } else printf("cant find packet.log\n"); + printf("char *MM_fields[256] = \n{\n"); + for (i=0; i 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 @@ -35,8 +38,9 @@ struct LP_millistats double lastmilli,millisum,threshold; uint32_t count; char name[64]; -} LP_psockloop_stats,LP_reserved_msgs_stats,utxosQ_loop_stats,command_rpcloop_stats,queue_loop_stats,prices_loop_stats,LP_coinsloop_stats,LP_coinsloopBTC_stats,LP_coinsloopKMD_stats,LP_pubkeysloop_stats,LP_privkeysloop_stats,LP_swapsloop_stats,LP_gcloop_stats; +} 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) { @@ -56,7 +60,7 @@ void LP_millistats_update(struct LP_millistats *mp) mp = &LP_coinsloopBTC_stats, printf("%32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,OS_milliseconds() - mp->lastmilli,mp->threshold,mp->millisum/(mp->count > 0 ? mp->count: 1),mp->count); mp = &LP_coinsloopKMD_stats, printf("%32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,OS_milliseconds() - mp->lastmilli,mp->threshold,mp->millisum/(mp->count > 0 ? mp->count: 1),mp->count); mp = &LP_pubkeysloop_stats, printf("%32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,OS_milliseconds() - mp->lastmilli,mp->threshold,mp->millisum/(mp->count > 0 ? mp->count: 1),mp->count); - mp = &LP_privkeysloop_stats, printf("%32s lag %10.2f millis, threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,OS_milliseconds() - mp->lastmilli,mp->threshold,mp->millisum/(mp->count > 0 ? mp->count: 1),mp->count); + mp = &LP_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); } @@ -73,7 +77,7 @@ void LP_millistats_update(struct LP_millistats *mp) if ( mp->threshold != 0. && elapsed > mp->threshold ) { //if ( IAMLP == 0 ) - printf("%32s elapsed %10.2f millis > threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,elapsed,mp->threshold,mp->millisum/mp->count,mp->count); + 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; } @@ -81,21 +85,21 @@ void LP_millistats_update(struct LP_millistats *mp) } #include "LP_include.h" -portable_mutex_t LP_peermutex,LP_UTXOmutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex,LP_forwardmutex,LP_pubkeymutex,LP_networkmutex,LP_psockmutex,LP_coinmutex,LP_messagemutex,LP_portfoliomutex,LP_electrummutex,LP_butxomutex,LP_reservedmutex,LP_nanorecvsmutex,LP_tradebotsmutex,LP_gcmutex,LP_inusemutex,LP_cJSONmutex; +portable_mutex_t LP_peermutex,LP_UTXOmutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex,LP_forwardmutex,LP_pubkeymutex,LP_networkmutex,LP_psockmutex,LP_coinmutex,LP_messagemutex,LP_portfoliomutex,LP_electrummutex,LP_butxomutex,LP_reservedmutex,LP_nanorecvsmutex,LP_tradebotsmutex,LP_gcmutex,LP_inusemutex,LP_cJSONmutex,LP_logmutex,LP_statslogmutex,LP_tradesmutex; int32_t LP_canbind; char *Broadcaststr,*Reserved_msgs[2][1000]; int32_t num_Reserved_msgs[2],max_Reserved_msgs[2]; struct LP_peerinfo *LP_peerinfos,*LP_mypeer; struct LP_forwardinfo *LP_forwardinfos; struct iguana_info *LP_coins; -struct LP_pubkeyinfo *LP_pubkeyinfos; +struct LP_pubkey_info *LP_pubkeyinfos; struct rpcrequest_info *LP_garbage_collector; struct LP_address_utxo *LP_garbage_collector2; - +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,LP_swap_endcritical,LP_swap_critical; +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; @@ -106,13 +110,13 @@ struct LP_privkey { bits256 privkey; uint8_t rmd160[20]; }; struct LP_globals { - struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2]; - bits256 LP_mypub25519,LP_privkey,LP_mypriv25519; + //struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2]; + bits256 LP_mypub25519,LP_privkey,LP_mypriv25519,LP_passhash; uint64_t LP_skipstatus[10000]; uint8_t LP_myrmd160[20],LP_pubsecp[33]; uint32_t LP_sessionid,counter; int32_t LP_IAMLP,LP_pendingswaps,USERPASS_COUNTER,LP_numprivkeys,initializing,waiting,LP_numskips; - char USERPASS[65],USERPASS_WIFSTR[64],LP_myrmd160str[41],gui[16]; + char USERPASS[65],USERPASS_WIFSTR[64],LP_myrmd160str[41],gui[16],LP_NXTaddr[64]; struct LP_privkey LP_privkeys[100]; } G; @@ -134,9 +138,9 @@ 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" }; // + //"24.54.206.138", "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", "173.212.225.176", "136.243.45.140" +}; // stubs @@ -160,11 +164,13 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_ return(0); } +#include "LP_mmjson.c" #include "LP_socket.c" #include "LP_secp.c" #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" @@ -173,9 +179,10 @@ 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" @@ -186,7 +193,7 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_ char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen) { - char *retstr=0; + char *retstr=0; cJSON *retjson; bits256 zero; if ( jobj(argjson,"result") != 0 || jobj(argjson,"error") != 0 ) return(0); if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,data,datalen) <= 0 ) @@ -197,18 +204,24 @@ char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson //if ( pubsock >= 0 ) //strncmp("{\"error\":",retstr,strlen("{\"error\":")) != 0 && //LP_send(pubsock,retstr,(int32_t)strlen(retstr)+1,0); } - } //else printf("finished tradecommand (%s)\n",jprint(argjson,0)); + } + else if ( LP_statslog_parse() > 0 ) + { + memset(zero.bytes,0,sizeof(zero)); + if ( (retjson= LP_statslog_disp(2000000000,2000000000,"",zero,0,0))) // pending swaps + free_json(retjson); + } return(retstr); } -char *LP_decrypt(uint8_t *ptr,int32_t *recvlenp) +char *LP_decrypt(uint8_t decoded[LP_ENCRYPTED_MAXSIZE + crypto_box_ZEROBYTES],uint8_t *ptr,int32_t *recvlenp) { - uint8_t decoded[LP_ENCRYPTED_MAXSIZE + crypto_box_ZEROBYTES],*nonce,*cipher; int32_t recvlen,cipherlen; char *jsonstr = 0; + uint8_t *nonce,*cipher; int32_t recvlen,cipherlen; char *jsonstr = 0; recvlen = *recvlenp; nonce = &ptr[2]; cipher = &ptr[2 + crypto_box_NONCEBYTES]; cipherlen = recvlen - (2 + crypto_box_NONCEBYTES); - if ( cipherlen > 0 && cipherlen <= sizeof(decoded) ) + if ( cipherlen > 0 && cipherlen <= LP_ENCRYPTED_MAXSIZE + crypto_box_ZEROBYTES ) { if ( (jsonstr= (char *)_SuperNET_decipher(nonce,cipher,decoded,cipherlen,GENESIS_PUBKEY,G.LP_mypriv25519)) != 0 ) { @@ -219,7 +232,7 @@ char *LP_decrypt(uint8_t *ptr,int32_t *recvlenp) jsonstr = 0; } //else printf("decrypted (%s)\n",jsonstr); } - } else printf("cipher.%d too big for %d\n",cipherlen,(int32_t)sizeof(decoded)); + } else printf("cipher.%d too big for %d\n",cipherlen,LP_ENCRYPTED_MAXSIZE + crypto_box_ZEROBYTES); *recvlenp = recvlen; return(jsonstr); } @@ -227,7 +240,7 @@ char *LP_decrypt(uint8_t *ptr,int32_t *recvlenp) char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock,uint8_t *ptr,int32_t recvlen,int32_t recvsock) { static uint32_t dup,uniq; - int32_t i,len,cipherlen,datalen=0,duplicate=0,encrypted=0; char *method,*method2,*tmp,*cipherstr,*retstr=0,*jsonstr=0; cJSON *argjson; uint32_t crc32; + uint8_t jdecoded[LP_ENCRYPTED_MAXSIZE + crypto_box_ZEROBYTES]; int32_t i,len,cipherlen,datalen=0,duplicate=0,encrypted=0; char *method,*method2,*tmp,*cipherstr,*retstr=0,*jsonstr=0; cJSON *argjson; uint32_t crc32; //double millis = OS_milliseconds(); crc32 = calc_crc32(0,&ptr[2],recvlen-2); if ( (crc32 & 0xff) == ptr[0] && ((crc32>>8) & 0xff) == ptr[1] ) @@ -244,7 +257,7 @@ char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock, if ( i >= 0 ) LP_crc32find(&duplicate,i,crc32); if ( encrypted != 0 ) - jsonstr = LP_decrypt(ptr,&recvlen); + jsonstr = LP_decrypt(jdecoded,ptr,&recvlen); else if ( (datalen= is_hexstr((char *)ptr,0)) > 0 ) { datalen >>= 1; @@ -265,7 +278,7 @@ char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock, cipherlen >>= 1; decode_hex(decoded,cipherlen,cipherstr); crc32 = calc_crc32(0,&decoded[2],cipherlen-2); - if ( (tmp= LP_decrypt(decoded,&cipherlen)) != 0 ) + if ( (tmp= LP_decrypt(jdecoded,decoded,&cipherlen)) != 0 ) { jsonstr = tmp; free_json(argjson); @@ -307,8 +320,8 @@ char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock, else { memset(zero.bytes,0,sizeof(zero)); - /*if ( (method= jstr(reqjson,"method")) != 0 && (strcmp(method,"request") == 0 || strcmp(method,"requested") == 0 || strcmp(method,"connect") == 0 || strcmp(method,"connected") == 0) ) - printf("broadcast.(%s)\n",Broadcaststr);*/ + if ( 0 && (method= jstr(reqjson,"method")) != 0 && (strcmp(method,"tradestatus") == 0) ) + printf("broadcast.(%s)\n",Broadcaststr); LP_reserved_msg(0,"","",zero,jprint(reqjson,0)); } retstr = clonestr("{\"result\":\"success\"}"); @@ -334,11 +347,15 @@ char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock, int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int32_t sock,char *remoteaddr,int32_t maxdepth) { - int32_t recvlen=1,nonz = 0; cJSON *argjson; void *ptr; char methodstr[64],*retstr,*str; struct nn_pollfd pfd; + static char *line; + int32_t recvlen=1,msglen,nonz = 0; cJSON *argjson,*recvjson; void *ptr,*msg; char methodstr[64],*decodestr,*retstr,*str; struct nn_pollfd pfd; + if ( line == 0 ) + line = calloc(1,1024*1024); if ( sock >= 0 ) { while ( nonz < maxdepth && recvlen > 0 ) { + decodestr = 0; nonz++; memset(&pfd,0,sizeof(pfd)); pfd.fd = sock; @@ -346,56 +363,67 @@ int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int if ( nn_poll(&pfd,1,1) != 1 ) break; ptr = 0; - //buf = malloc(1000000); - //if ( (recvlen= nn_recv(sock,buf,1000000,0)) > 0 ) if ( (recvlen= nn_recv(sock,&ptr,NN_MSG,0)) > 0 ) { - //ptr = buf; - methodstr[0] = 0; - //printf("%s.(%s)\n",typestr,(char *)ptr); - if ( 0 ) + decodestr = 0; + if ( recvlen > 32768 ) { - cJSON *recvjson; char *mstr;//,*cstr; - if ( (recvjson= cJSON_Parse((char *)ptr)) != 0 ) + printf("unexpectedly large packet\n"); + } + else + { + msg = ptr; + msglen = recvlen; + if ( (recvjson= cJSON_Parse((char *)ptr)) == 0 ) { - if ( (mstr= jstr(recvjson,"method")) != 0 )//&& strcmp(mstr,"uitem") == 0 && (cstr= jstr(recvjson,"coin")) != 0 && strcmp(cstr,"REVS") == 0 ) + if ( (decodestr= MMJSON_decode(ptr,recvlen)) != 0 ) { - //printf("%s RECV.(%s)\n",typestr,(char *)ptr); - } - safecopy(methodstr,jstr(recvjson,"method"),sizeof(methodstr)); - free_json(recvjson); + if ( (recvjson= cJSON_Parse(decodestr)) != 0 ) + { + msg = decodestr; + msglen = (int32_t)strlen(decodestr) + 1; + } + //printf("decoded.(%s)\n",decodestr); + } else printf("couldnt decode linebuf[%d]\n",recvlen); } - } - int32_t validreq = 0; - if ( strlen((char *)ptr)+sizeof(bits256) <= recvlen ) - { - if ( LP_magic_check(ptr,recvlen,remoteaddr) <= 0 ) + methodstr[0] = 0; + //printf("%s.(%s)\n",typestr,(char *)ptr); + if ( recvjson != 0 ) { - //printf("magic check error\n"); - } else validreq = 1; - recvlen -= sizeof(bits256); - } - if ( validreq != 0 ) - { - if ( (retstr= LP_process_message(ctx,typestr,myipaddr,pubsock,ptr,recvlen,sock)) != 0 ) - free(retstr); - if ( Broadcaststr != 0 ) + safecopy(LP_methodstr,jstr(recvjson,"method"),sizeof(LP_methodstr)); + free_json(recvjson); + } + int32_t validreq = 1; + /*if ( strlen((char *)ptr)+sizeof(bits256) <= recvlen ) + { + if ( LP_magic_check(ptr,recvlen,remoteaddr) <= 0 ) + { + //printf("magic check error\n"); + } else validreq = 1; + recvlen -= sizeof(bits256); + }*/ + if ( validreq != 0 ) { - //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,msg,msglen,sock)) != 0 ) + free(retstr); + if ( Broadcaststr != 0 ) { - portable_mutex_lock(&LP_commandmutex); - 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 ) { - if ( (retstr= stats_JSON(ctx,myipaddr,pubsock,argjson,remoteaddr,0)) != 0 ) - free(retstr); + portable_mutex_lock(&LP_commandmutex); + if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,0,0) <= 0 ) + { + if ( (retstr= stats_JSON(ctx,myipaddr,pubsock,argjson,remoteaddr,0)) != 0 ) + free(retstr); + } + portable_mutex_unlock(&LP_commandmutex); + free_json(argjson); } - portable_mutex_unlock(&LP_commandmutex); - free_json(argjson); + free(str); } - free(str); } } } @@ -404,6 +432,8 @@ int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int nn_freemsg(ptr), ptr = 0; //free(buf); } + if ( decodestr != 0 ) + free(decodestr); } } return(nonz); @@ -445,12 +475,11 @@ 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.; + command_rpcloop_stats.threshold = 2500.; while ( 1 ) { LP_millistats_update(&command_rpcloop_stats); @@ -468,21 +497,9 @@ void command_rpcloop(void *myipaddr) } } -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); - } -} - void LP_coinsloop(void *_coins) { - struct LP_address *ap=0,*atmp; struct LP_transaction *tx; cJSON *retjson; struct LP_address_utxo *up,*tmp; struct iguana_info *coin,*ctmp; char str[65]; struct electrum_info *ep,*backupep=0; bits256 zero; int32_t oldht,j,nonz; char *coins = _coins; + 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 ) { strcpy(LP_coinsloopBTC_stats.name,"BTC coin loop"); @@ -527,20 +544,23 @@ void LP_coinsloop(void *_coins) if ( coin->inactive != 0 ) continue; if ( coin->longestchain == 1 ) // special init value - coin->longestchain = LP_getheight(coin); + 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 ( (ap= LP_addressfind(coin,coin->smartaddr)) != 0 ) - { - if ( (retjson= electrum_address_listunspent(coin->symbol,ep,&retjson,ap->coinaddr,1)) != 0 ) - free_json(retjson); - } + 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 ( (retjson= electrum_address_listunspent(coin->symbol,ep,&retjson,ap->coinaddr,1)) != 0 ) + if ( strcmp(coin->smartaddr,ap->coinaddr) != 0 && (retjson= electrum_address_listunspent(coin->symbol,ep,&retjson,ap->coinaddr,1,zero,zero)) != 0 ) free_json(retjson); } if ( (ap= LP_addressfind(coin,coin->smartaddr)) != 0 ) @@ -567,7 +587,7 @@ void LP_coinsloop(void *_coins) 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,coin->smartaddr,backupep,up->U.txid,up->U.height); if ( up->SPV <= 0 ) @@ -582,8 +602,9 @@ void LP_coinsloop(void *_coins) if ( time(NULL) > ep->keepalive+LP_ELECTRUM_KEEPALIVE ) { //printf("%s electrum.%p needs a keepalive: lag.%d\n",ep->symbol,ep,(int32_t)(time(NULL) - ep->keepalive)); - if ( (retjson= electrum_address_listunspent(coin->symbol,ep,&retjson,coin->smartaddr,1)) != 0 ) + if ( (retjson= electrum_banner(coin->symbol,ep,&retjson)) != 0 ) free_json(retjson); + ep->keepalive = (uint32_t)time(NULL); } ep = ep->prev; } @@ -613,21 +634,26 @@ void LP_coinsloop(void *_coins) coin->lastscanht = coin->firstscanht; continue; } - nonz++; - if ( 0 && coin->lastscanht < coin->longestchain-3 ) - printf("[%s]: %s ref.%d scan.%d to %d, longest.%d\n",coins,coin->symbol,coin->firstrefht,coin->firstscanht,coin->lastscanht,coin->longestchain); - for (j=0; j<100; j++) + if ( 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++) { - static uint32_t counter; - if ( counter++ < 3 ) - 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 ) @@ -639,8 +665,8 @@ void LP_coinsloop(void *_coins) int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int32_t pubsock,char *pushaddr,uint16_t myport) { - static uint32_t counter; - struct iguana_info *coin,*ctmp; char *origipaddr; uint32_t now; int32_t height,nonz = 0; + 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 ) @@ -648,19 +674,32 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht { now = (uint32_t)time(NULL); - if ( (coin->addr_listunspent_requested != 0 && now > coin->lastpushtime+LP_ORDERBOOK_DURATION*.5) || now > coin->lastpushtime+LP_ORDERBOOK_DURATION*5 ) +#ifdef bruteforce + if ( IAMLP != 0 && coin->inactive == 0 && coin->electrum == 0 && didinstantdex == 0 && strcmp("KMD",coin->symbol) == 0 ) + { + LP_instantdex_deposits(coin); + didinstantdex = now; + } +#endif + /*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->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 ( 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); @@ -673,19 +712,25 @@ 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; char *symbol; struct iguana_info *coin; + 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); + 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; } @@ -697,12 +742,12 @@ void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins) item = jitem(coins,i); if ( (symbol= jstr(item,"coin")) != 0 ) { - printf("%s ",jstr(item,"coin")); + printf("%s, ",jstr(item,"coin")); LP_coincreate(item); LP_priceinfoadd(jstr(item,"coin")); if ( (coin= LP_coinfind(symbol)) != 0 ) { - if ( LP_getheight(coin) <= 0 ) + if ( LP_getheight(¬arized,coin) <= 0 ) coin->inactive = (uint32_t)time(NULL); else LP_unspents_load(coin->symbol,coin->smartaddr); if ( coin->txfee == 0 && strcmp(coin->symbol,"BTC") != 0 ) @@ -710,6 +755,11 @@ void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins) } } } + for (i=0; ielectrum != 0 && time(NULL) > coin->lastunspent+30 ) - { - //printf("call electrum listunspent.%s\n",coin->symbol); - if ( (retjson= electrum_address_listunspent(coin->symbol,coin->electrum,&retjson,coin->smartaddr,2)) != 0 ) - free_json(retjson); - coin->lastunspent = (uint32_t)time(NULL); - } - } if ( time(NULL) > lasttime+LP_ORDERBOOK_DURATION*0.5 ) { //printf("LP_pubkeysloop %u\n",(uint32_t)time(NULL)); @@ -785,22 +825,7 @@ void LP_pubkeysloop(void *ctx) } } -void LP_privkeysloop(void *ctx) -{ - strcpy(LP_privkeysloop_stats.name,"LP_privkeysloop"); - LP_privkeysloop_stats.threshold = (LP_ORDERBOOK_DURATION * .8 * 1000) + 10000; - sleep(20); - while ( 1 ) - { - LP_millistats_update(&LP_privkeysloop_stats); - LP_counter += 1000; -//printf("LP_privkeysloop %u\n",LP_counter); - LP_privkey_updates(ctx,LP_mypubsock,0); - sleep(LP_ORDERBOOK_DURATION * .777); - } -} - -void LP_swapsloop(void *ignore) +void LP_swapsloop(void *ctx) { char *retstr; strcpy(LP_swapsloop_stats.name,"LP_swapsloop"); @@ -809,14 +834,153 @@ void LP_swapsloop(void *ignore) while ( 1 ) { LP_millistats_update(&LP_swapsloop_stats); - LP_counter += 10000; -//printf("LP_swapsloop %u\n",LP_counter); - if ( (retstr= basilisk_swapentry(0,0)) != 0 ) + if ( (retstr= basilisk_swapentry(0,0,0)) != 0 ) free(retstr); sleep(600); } } +void gc_loop(void *ctx) +{ + uint32_t now; struct LP_address_utxo *up,*utmp; struct rpcrequest_info *req,*rtmp; int32_t flag = 0; + strcpy(LP_gcloop_stats.name,"gc_loop"); + LP_gcloop_stats.threshold = 11000.; + while ( 1 ) + { + flag = 0; + LP_millistats_update(&LP_gcloop_stats); + portable_mutex_lock(&LP_gcmutex); + DL_FOREACH_SAFE(LP_garbage_collector,req,rtmp) + { + DL_DELETE(LP_garbage_collector,req); + //printf("garbage collect ipbits.%x\n",req->ipbits); + free(req); + flag++; + } + now = (uint32_t)time(NULL); + DL_FOREACH_SAFE(LP_garbage_collector2,up,utmp) + { + if ( now > (uint32_t)up->spendheight+120 ) + { + DL_DELETE(LP_garbage_collector2,up); + //char str[65]; printf("garbage collect %s/v%d lag.%d\n",bits256_str(str,up->U.txid),up->U.vout,now-up->spendheight); + free(up); + } + flag++; + } + portable_mutex_unlock(&LP_gcmutex); + if ( 0 && flag != 0 ) + printf("gc_loop.%d\n",flag); + sleep(10); + } +} + +void queue_loop(void *ctx) +{ + struct LP_queue *ptr,*tmp; cJSON *json; uint8_t linebuf[32768]; int32_t k,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 ( 0 ) + { + static FILE *fp; + if ( fp == 0 ) + fp = fopen("packet.log","wb"); + if ( fp != 0 ) + { + fprintf(fp,"%s\n",(char *)ptr->msg); + fflush(fp); + } + } + if ( (json= cJSON_Parse((char *)ptr->msg)) != 0 ) + { + if ( ptr->msglen < sizeof(linebuf) ) + { + if ( (k= MMJSON_encode(linebuf,(char *)ptr->msg)) > 0 ) + { + if ( (sentbytes= nn_send(ptr->sock,linebuf,k,0)) != k ) + printf("%d LP_send mmjson sent %d instead of %d\n",n,sentbytes,k); + else flag++; + } + } + free_json(json); + } + if ( flag == 0 ) + { + if ( (sentbytes= nn_send(ptr->sock,ptr->msg,ptr->msglen,0)) != ptr->msglen ) + printf("%d LP_send sent %d instead of %d\n",n,sentbytes,ptr->msglen); + else 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,nonz; struct nn_pollfd pfd; @@ -875,7 +1039,7 @@ int32_t LP_reserved_msg(int32_t priority,char *base,char *rel,bits256 pubkey,cha { Reserved_msgs[priority][num_Reserved_msgs[priority]++] = msg; n = num_Reserved_msgs[priority]; - } else LP_broadcast_message(LP_mypubsock,base,rel,pubkey,msg); + } //else LP_broadcast_message(LP_mypubsock,base,rel,pubkey,msg); if ( num_Reserved_msgs[priority] > max_Reserved_msgs[priority] ) { max_Reserved_msgs[priority] = num_Reserved_msgs[priority]; @@ -886,10 +1050,13 @@ int32_t LP_reserved_msg(int32_t priority,char *base,char *rel,bits256 pubkey,cha return(n); } +extern int32_t bitcoind_RPC_inittime; + 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,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)); + bitcoind_RPC_inittime = 1; printf("%s %u\n",version,calc_crc32(0,version,(int32_t)strlen(version))); if ( LP_MAXPRICEINFOS > 256 ) { @@ -960,6 +1127,9 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu portable_mutex_init(&LP_nanorecvsmutex); portable_mutex_init(&LP_tradebotsmutex); portable_mutex_init(&LP_cJSONmutex); + portable_mutex_init(&LP_logmutex); + portable_mutex_init(&LP_statslogmutex); + portable_mutex_init(&LP_tradesmutex); myipaddr = clonestr("127.0.0.1"); #ifndef _WIN32 #ifndef FROM_JS @@ -1035,9 +1205,12 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu exit(-1); } 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 ) { @@ -1049,11 +1222,6 @@ 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 ) - { - printf("error launching utxosQ_loop for (%s)\n",myipaddr); - exit(-1); - } if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)stats_rpcloop,(void *)&myport) != 0 ) { printf("error launching stats rpcloop for port.%u\n",myport); @@ -1065,57 +1233,59 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu 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 port.%u\n",myport); + printf("error launching command_rpcloop 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 *)queue_loop,ctx) != 0 ) { - printf("error launching queue_loop 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 *)gc_loop,(void *)myipaddr) != 0 ) + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)gc_loop,ctx) != 0 ) { - printf("error launching gc_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,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(); + bitcoind_RPC_inittime = 0; while ( 1 ) { nonz = 0; @@ -1182,8 +1352,6 @@ 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); //LP_pubkeys_query(); @@ -1191,18 +1359,17 @@ void LP_fromjs_iter() //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); - if ( (retstr= basilisk_swapentry(0,0)) != 0 ) + if ( (retstr= basilisk_swapentry(0,0,0)) != 0 ) free(retstr); } } - LP_counter++; } #endif diff --git a/iguana/exchanges/LP_network.c b/iguana/exchanges/LP_network.c index d1b147bc8..e3755aae6 100644 --- a/iguana/exchanges/LP_network.c +++ b/iguana/exchanges/LP_network.c @@ -152,7 +152,7 @@ void _LP_sendqueueadd(uint32_t crc32,int32_t sock,uint8_t *msg,int32_t msglen,in ptr->crc32 = crc32; ptr->sock = sock; ptr->peerind = peerind; - ptr->msglen = (int32_t)(msglen + sizeof(bits256)); + ptr->msglen = (int32_t)(msglen + 0*sizeof(bits256)); memcpy(ptr->msg,msg,msglen); // sizeof(bits256) at the end all zeroes DL_APPEND(LP_Q,ptr); LP_Qenqueued++; @@ -265,122 +265,6 @@ int32_t LP_peerindsock(int32_t *peerindp) return(-1); } -void gc_loop(void *arg) -{ - uint32_t now; struct LP_address_utxo *up,*utmp; struct rpcrequest_info *req,*rtmp; int32_t flag = 0; - strcpy(LP_gcloop_stats.name,"gc_loop"); - LP_gcloop_stats.threshold = 11000.; - while ( 1 ) - { - flag = 0; - LP_millistats_update(&LP_gcloop_stats); - portable_mutex_lock(&LP_gcmutex); - DL_FOREACH_SAFE(LP_garbage_collector,req,rtmp) - { - DL_DELETE(LP_garbage_collector,req); - //printf("garbage collect ipbits.%x\n",req->ipbits); - free(req); - flag++; - } - now = (uint32_t)time(NULL); - DL_FOREACH_SAFE(LP_garbage_collector2,up,utmp) - { - if ( now > (uint32_t)up->spendheight+120 ) - { - DL_DELETE(LP_garbage_collector2,up); - //char str[65]; printf("garbage collect %s/v%d lag.%d\n",bits256_str(str,up->U.txid),up->U.vout,now-up->spendheight); - free(up); - } - flag++; - } - portable_mutex_unlock(&LP_gcmutex); - if ( 0 && flag != 0 ) - printf("gc_loop.%d\n",flag); - sleep(10); - } -} - -void queue_loop(void *arg) -{ - struct LP_queue *ptr,*tmp; int32_t sentbytes,nonz,flag,duplicate,n=0; - strcpy(queue_loop_stats.name,"queue_loop"); - queue_loop_stats.threshold = 1000.; - while ( 1 ) - { - LP_millistats_update(&queue_loop_stats); - //printf("LP_Q.%p next.%p prev.%p\n",LP_Q,LP_Q!=0?LP_Q->next:0,LP_Q!=0?LP_Q->prev:0); - n = nonz = flag = 0; - DL_FOREACH_SAFE(LP_Q,ptr,tmp) - { - n++; - flag = 0; - if ( ptr->sock >= 0 ) - { - if ( ptr->notready == 0 || (LP_rand() % ptr->notready) == 0 ) - { - if ( LP_sockcheck(ptr->sock) > 0 ) - { - bits256 magic; - magic = LP_calc_magic(ptr->msg,(int32_t)(ptr->msglen - sizeof(bits256))); - memcpy(&ptr->msg[ptr->msglen - sizeof(bits256)],&magic,sizeof(magic)); - if ( (sentbytes= nn_send(ptr->sock,ptr->msg,ptr->msglen,0)) != ptr->msglen ) - printf("%d LP_send sent %d instead of %d\n",n,sentbytes,ptr->msglen); - else flag++; - ptr->sock = -1; - if ( ptr->peerind > 0 ) - ptr->starttime = (uint32_t)time(NULL); - } - else - { - if ( ptr->notready++ > 1000 ) - flag = 1; - } - } - } - else if ( 0 && time(NULL) > ptr->starttime+13 ) - { - LP_crc32find(&duplicate,-1,ptr->crc32); - if ( duplicate > 0 ) - { - LP_Qfound++; - if ( (LP_Qfound % 100) == 0 ) - printf("found.%u Q.%d err.%d match.%d\n",ptr->crc32,LP_Qenqueued,LP_Qerrors,LP_Qfound); - flag++; - } - else if ( 0 ) // too much beyond duplicate filter when network is busy - { - printf("couldnt find.%u peerind.%d Q.%d err.%d match.%d\n",ptr->crc32,ptr->peerind,LP_Qenqueued,LP_Qerrors,LP_Qfound); - ptr->peerind++; - if ( (ptr->sock= LP_peerindsock(&ptr->peerind)) < 0 ) - { - printf("%d no more peers to try at peerind.%d %p Q_LP.%p\n",n,ptr->peerind,ptr,LP_Q); - flag++; - LP_Qerrors++; - } - } - } - if ( flag != 0 ) - { - nonz++; - portable_mutex_lock(&LP_networkmutex); - DL_DELETE(LP_Q,ptr); - portable_mutex_unlock(&LP_networkmutex); - free(ptr); - ptr = 0; - break; - } - } - if ( arg == 0 ) - break; - if ( nonz == 0 ) - { - if ( IAMLP == 0 ) - usleep(50000); - else usleep(10000); - } - } -} - void _LP_queuesend(uint32_t crc32,int32_t sock0,int32_t sock1,uint8_t *msg,int32_t msglen,int32_t needack) { int32_t maxind,peerind = 0; //sentbytes, @@ -573,7 +457,7 @@ 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 ) { diff --git a/iguana/exchanges/LP_ordermatch.c b/iguana/exchanges/LP_ordermatch.c index bc73ee840..dbf97f676 100644 --- a/iguana/exchanges/LP_ordermatch.c +++ b/iguana/exchanges/LP_ordermatch.c @@ -20,8 +20,8 @@ // struct LP_quoteinfo LP_Alicequery,LP_Alicereserved; double LP_Alicemaxprice; -bits256 LP_Alicedestpubkey; -uint32_t Alice_expiration; +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) @@ -32,7 +32,7 @@ double LP_bob_competition(int32_t *counterp,uint64_t aliceid,double price,int32_ { if ( Bob_competition[i].aliceid == aliceid ) { - if ( now > Bob_competition[i].starttime+LP_AUTOTRADE_TIMEOUT ) + if ( counter < 0 || now > Bob_competition[i].starttime+LP_AUTOTRADE_TIMEOUT ) { //printf("aliceid.%llu expired\n",(long long)aliceid); Bob_competition[i].bestprice = 0.; @@ -85,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; @@ -177,14 +160,11 @@ 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 ) @@ -281,7 +261,7 @@ int32_t LP_nearest_utxovalue(struct iguana_info *coin,char *coinaddr,struct LP_a 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 - targetval); if ( dist > 0 && up->U.height < bestheight ) { - if ( (double)dist/bestdist < sqrt(bestheight - up->U.height) ) + if ( (double)dist/bestdist < sqrt(((double)bestheight - up->U.height)/1000) ) { replacei = i; bestheight = up->U.height; @@ -321,7 +301,7 @@ int32_t LP_nearest_utxovalue(struct iguana_info *coin,char *coinaddr,struct LP_a } 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); + 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); } } @@ -329,7 +309,7 @@ int32_t LP_nearest_utxovalue(struct iguana_info *coin,char *coinaddr,struct LP_a return(mini); } -void LP_butxo_set(struct LP_utxoinfo *butxo,struct iguana_info *coin,struct LP_address_utxo *up,struct LP_address_utxo *up2,int64_t satoshis) +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) { butxo->pubkey = G.LP_mypub25519; safecopy(butxo->coin,coin->symbol,sizeof(butxo->coin)); @@ -337,11 +317,19 @@ void LP_butxo_set(struct LP_utxoinfo *butxo,struct iguana_info *coin,struct LP_a butxo->payment.txid = up->U.txid; butxo->payment.vout = up->U.vout; butxo->payment.value = up->U.value; - butxo->iambob = 1; - butxo->deposit.txid = up2->U.txid; - butxo->deposit.vout = up2->U.vout; - butxo->deposit.value = up2->U.value; - butxo->S.satoshis = satoshis; + if ( (butxo->iambob= iambob) != 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) @@ -359,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 ) { @@ -374,7 +362,7 @@ 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; } } @@ -388,10 +376,22 @@ uint64_t LP_basesatoshis(double relvolume,double price,uint64_t txfee,uint64_t d struct LP_utxoinfo *LP_address_myutxopair(struct LP_utxoinfo *butxo,int32_t iambob,struct LP_address_utxo **utxos,int32_t max,struct iguana_info *coin,char *coinaddr,uint64_t txfee,double relvolume,double price,uint64_t desttxfee) { - struct LP_address *ap; uint64_t targetval,targetval2; int32_t m,mini; struct LP_address_utxo *up,*up2; + 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)); - targetval = LP_basesatoshis(relvolume,price,txfee,desttxfee); - targetval2 = (targetval / 8) * 9 + 2*txfee; + 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 ) @@ -402,43 +402,49 @@ struct LP_utxoinfo *LP_address_myutxopair(struct LP_utxoinfo *butxo,int32_t iamb for (i=0; iU.value >= targetval ) printf("%.8f ",dstr(utxos[i]->U.value)); - printf("targetval %.8f vol %.8f price %.8f txfee %.8f %s %s\n",dstr(targetval),relvolume,price,dstr(txfee),coin->symbol,coinaddr); + printf("targetval %.8f vol %.8f price %.8f txfee %.8f %s %s\n",dstr(targetval),relvolume,price,dstr(fee),coin->symbol,coinaddr); } - mini = -1; - if ( targetval != 0 && (mini= LP_nearest_utxovalue(coin,coinaddr,utxos,m,targetval+txfee)) >= 0 ) + while ( 1 ) { - up = utxos[mini]; - utxos[mini] = 0; -//printf("found mini.%d %.8f for targetval %.8f -> targetval2 %.8f, ratio %.2f\n",mini,dstr(up->U.value),dstr(targetval),dstr(targetval2),(double)up->U.value/targetval); - if ( (double)up->U.value/targetval < LP_MINVOL-1 ) - + mini = -1; + if ( targetval != 0 && (mini= LP_nearest_utxovalue(coin,coinaddr,utxos,m,targetval+fee)) >= 0 ) { - if ( (mini= LP_nearest_utxovalue(coin,coinaddr,utxos,m,(targetval2+2*txfee) * 1.01)) >= 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 ( up != 0 && (up2= utxos[mini]) != 0 ) + 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 ( (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 ) + if ( up != 0 && (up2= utxos[mini]) != 0 ) { - utxo->S.satoshis = targetval; - char str[65],str2[65]; printf("butxo.%p targetval %.8f, found val %.8f %s | targetval2 %.8f val2 %.8f %s\n",utxo,dstr(targetval),dstr(up->U.value),bits256_str(str,utxo->payment.txid),dstr(targetval2),dstr(up2->U.value),bits256_str(str2,utxo->deposit.txid)); + LP_butxo_set(butxo,iambob,coin,up,up2,targetval); return(butxo); - }*/ - LP_butxo_set(butxo,coin,up,up2,targetval); - return(butxo); - } - } else printf("cant find targetval2 %.8f\n",dstr(targetval2)); - } else printf("failed ratio test %.8f\n",(double)up->U.value/targetval); - } else if ( targetval != 0 && mini >= 0 ) - printf("targetval %.8f mini.%d\n",dstr(targetval),mini); + } else printf("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,cJSON *argjson,char *base,char *rel,double price,struct LP_quoteinfo *qp) +int32_t LP_connectstartbob(void *ctx,int32_t pubsock,char *base,char *rel,double price,struct LP_quoteinfo *qp) { - 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); + 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(qp->srccoin)) == 0 ) { @@ -454,7 +460,7 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,cJSON *argjson,char *base,c printf("requestid.%u quoteid.%u is already in progres\n",qp->R.requestid,qp->R.quoteid); return(-1); } - if ( (swap= LP_swapinit(1,0,privkey,&qp->R,qp)) == 0 ) + if ( (swap= LP_swapinit(1,0,privkey,&qp->R,qp,LP_dynamictrust(qp->othercredits,qp->desthash,LP_kmdvalue(qp->destcoin,qp->destsatoshis)) > 0)) == 0 ) { printf("cant initialize swap\n"); return(-1); @@ -466,16 +472,25 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,cJSON *argjson,char *base,c //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); + 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)); - LP_reserved_msg(1,base,rel,qp->desthash,jprint(retjson,0)); - sleep(1); bits256 zero; memset(zero.bytes,0,sizeof(zero)); - LP_reserved_msg(1,base,rel,zero,jprint(retjson,0)); - free_json(retjson); + 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); @@ -492,12 +507,7 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,cJSON *argjson,char *base,c char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp,double maxprice,int32_t timeout,int32_t duration,uint32_t tradeid,bits256 destpubkey) { - struct LP_utxoinfo *aliceutxo; double price; - if ( (aliceutxo= LP_utxopairfind(0,qp->desttxid,qp->destvout,qp->feetxid,qp->feevout)) == 0 ) - { - char str[65],str2[65]; printf("dest.(%s)/v%d fee.(%s)/v%d\n",bits256_str(str,qp->desttxid),qp->destvout,bits256_str(str2,qp->feetxid),qp->feevout); - return(clonestr("{\"error\":\"cant find alice utxopair\"}")); - } + double price; price = 0.; memset(qp->txid.bytes,0,sizeof(qp->txid)); qp->txid2 = qp->txid; @@ -547,95 +557,79 @@ int32_t LP_alice_eligible(uint32_t quotetime) return(Alice_expiration == 0 || time(NULL) < Alice_expiration); } -void LP_reserved(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp) -{ - double price=0.,maxprice = LP_Alicemaxprice; - if ( LP_quotecmp(0,qp,&LP_Alicequery) == 0 ) - { - price = LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout); - if ( LP_pricevalid(price) > 0 && maxprice > SMALLVAL && price <= maxprice ) - { - qp->tradeid = LP_Alicequery.tradeid; - LP_Alicereserved = *qp; - LP_alicequery_clear(); - printf("send CONNECT\n"); - LP_query(ctx,myipaddr,mypubsock,"connect",qp); - } else printf("LP_reserved price %.8f vs maxprice %.8f\n",price,maxprice*1.005); - } else printf("probably a timeout, reject reserved due to not eligible.%d or mismatched quote price %.8f vs maxprice %.8f\n",LP_alice_eligible(qp->quotetime),price,maxprice); -} - -char *LP_connectedalice(cJSON *argjson) // alice +char *LP_connectedalice(struct LP_quoteinfo *qp,char *pairstr) // alice { - cJSON *retjson; double bid,ask,price,qprice; int32_t pairsock = -1; char *pairstr; int32_t DEXselector = 0; struct LP_utxoinfo *autxo,A,B,*butxo; struct LP_quoteinfo Q; struct basilisk_swap *swap; struct iguana_info *coin; - if ( LP_quoteparse(&Q,argjson) < 0 ) + 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 ) { LP_aliceid(Q.tradeid,Q.aliceid,"error0",0,0); clonestr("{\"error\":\"cant parse quote\"}"); - } - if ( bits256_cmp(Q.desthash,G.LP_mypub25519) != 0 ) + }*/ + if ( bits256_cmp(qp->desthash,G.LP_mypub25519) != 0 ) { - LP_aliceid(Q.tradeid,Q.aliceid,"error1",0,0); + LP_aliceid(qp->tradeid,qp->aliceid,"error1",0,0); return(clonestr("{\"result\",\"update stats\"}")); } - printf("CONNECTED.(%s) numpending.%d tradeid.%u requestid.%u quoteid.%u\n",jprint(argjson,0),G.LP_pendingswaps,Q.tradeid,Q.R.requestid,Q.R.quoteid); - LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-Q.txfee,Q.destcoin,Q.destsatoshis-Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector); - printf("calculated requestid.%u quoteid.%u\n",Q.R.requestid,Q.R.quoteid); - if ( LP_pendingswap(Q.R.requestid,Q.R.quoteid) > 0 ) + printf("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("requestid.%u quoteid.%u is already in progres\n",Q.R.requestid,Q.R.quoteid); + 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 ( LP_quotecmp(1,&Q,&LP_Alicereserved) == 0 ) + /*if ( LP_quotecmp(1,qp,&LP_Alicereserved) == 0 ) { printf("mismatched between reserved and connected\n"); - } + }*/ memset(&LP_Alicereserved,0,sizeof(LP_Alicereserved)); - LP_aliceid(Q.tradeid,Q.aliceid,"connected",Q.R.requestid,Q.R.quoteid); + 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(autxo,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(Q.desttxid,Q.vout); - LP_availableset(Q.feetxid,Q.feevout); - LP_aliceid(Q.tradeid,Q.aliceid,"error4",0,0); - printf("quote validate error %.0f\n",qprice); + LP_availableset(qp->desttxid,qp->vout); + LP_availableset(qp->feetxid,qp->feevout); + LP_aliceid(qp->tradeid,qp->aliceid,"error4",0,0); + printf("quote %s/%s validate error %.0f\n",qp->srccoin,qp->destcoin,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(Q.desttxid,Q.vout); - LP_availableset(Q.feetxid,Q.feevout); - LP_aliceid(Q.tradeid,Q.aliceid,"error5",0,0); + 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(Q.tradeid,Q.aliceid,"error6",0,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 ( (swap= LP_swapinit(0,0,Q.privkey,&Q.R,&Q)) == 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(Q.desttxid,Q.vout); - LP_availableset(Q.feetxid,Q.feevout); - LP_aliceid(Q.tradeid,Q.aliceid,"error7",Q.R.requestid,Q.R.quoteid); + 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= jstr(argjson,"pair")) == 0 || (pairsock= nn_socket(AF_SP,NN_PAIR)) < 0 ) + if ( pairstr == 0 || pairstr[0] == 0 || (pairsock= nn_socket(AF_SP,NN_PAIR)) < 0 ) { - LP_aliceid(Q.tradeid,Q.aliceid,"error8",Q.R.requestid,Q.R.quoteid); + 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 ) @@ -643,100 +637,51 @@ char *LP_connectedalice(cJSON *argjson) // alice //timeout = 1; //nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); //nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); - swap->tradeid = Q.tradeid; + swap->tradeid = qp->tradeid; swap->N.pair = pairsock; //autxo->S.swap = swap; //swap->utxo = autxo; - LP_aliceid(Q.tradeid,Q.aliceid,"started",Q.R.requestid,Q.R.quoteid); - printf("alice pairstr.(%s) pairsock.%d\n",pairstr,pairsock); + 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); + //jaddnum(retjson,"requestid",qp->R.requestid); + //jaddnum(retjson,"quoteid",qp->R.quoteid); } else { - LP_aliceid(Q.tradeid,Q.aliceid,"error9",Q.R.requestid,Q.R.quoteid); + LP_aliceid(qp->tradeid,qp->aliceid,"error9",qp->R.requestid,qp->R.quoteid); jaddstr(retjson,"error","couldnt aliceloop"); } } else { - LP_aliceid(Q.tradeid,Q.aliceid,"error10",Q.R.requestid,Q.R.quoteid); + 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(Q.desttxid,Q.vout); - LP_availableset(Q.feetxid,Q.feevout); + LP_availableset(qp->desttxid,qp->vout); + LP_availableset(qp->feetxid,qp->feevout); } return(jprint(retjson,1)); } else { - LP_availableset(Q.desttxid,Q.vout); - LP_availableset(Q.feetxid,Q.feevout); - LP_aliceid(Q.tradeid,Q.aliceid,"error11",0,0); - printf("no privkey found coin.%s %s taddr.%u\n",Q.destcoin,Q.destaddr,coin->taddr); + 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 i,v,numconfs,height,n=0; uint64_t value; bits256 txid; char buf[512]; cJSON *array,*item; uint32_t now; struct iguana_info *coin = LP_coinfind(symbol); - if ( coin != 0 )//&& (IAMLP != 0 || coin->inactive == 0) ) - { - if ( coin->electrum != 0 || LP_address_ismine(symbol,coinaddr) <= 0 ) - { - //printf("issue path electrum.%p\n",coin->electrum); - //if ( coin->electrum != 0 && (array= electrum_address_gethistory(symbol,coin->electrum,&array,coinaddr)) != 0 ) - // free_json(array); - n = LP_listunspent_issue(symbol,coinaddr,fullflag); - } - else - { - if ( strcmp(symbol,"BTC") == 0 ) - numconfs = 0; - else numconfs = 1; - //printf("my coin electrum.%p\n",coin->electrum); - sprintf(buf,"[%d, 99999999, [\"%s\"]]",numconfs,coinaddr); - if ( (array= bitcoin_json(coin,"listunspent",buf)) != 0 ) - { - if ( (n= cJSON_GetArraySize(array)) > 0 ) - { - now = (uint32_t)time(NULL); - for (i=0; iinactive:-1); - return(n); -} - -char *LP_bestfit(char *rel,double relvolume) -{ - struct LP_utxoinfo *autxo; - if ( relvolume <= 0. || LP_priceinfofind(rel) == 0 ) - return(clonestr("{\"error\":\"invalid parameter\"}")); - if ( (autxo= LP_utxo_bestfit(rel,SATOSHIDEN * relvolume)) == 0 ) - return(clonestr("{\"error\":\"cant find utxo that is big enough\"}")); - return(jprint(LP_utxojson(autxo),1)); -} - int32_t LP_aliceonly(char *symbol) { if ( strcmp(symbol,"GAME") == 0 ) @@ -746,13 +691,13 @@ int32_t LP_aliceonly(char *symbol) int32_t LP_validSPV(char *symbol,char *coinaddr,bits256 txid,int32_t vout) { - struct electrum_info *ep,*backupep; cJSON *txobj; struct LP_address_utxo *up; struct iguana_info *coin; struct LP_transaction *tx; + 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 ( (up= LP_address_utxofind(coin,coinaddr,txid,vout)) == 0 ) { - if ( (txobj= electrum_transaction(symbol,ep,&txobj,txid,coinaddr)) != 0 ) + if ( (txobj= electrum_transaction(&height,symbol,ep,&txobj,txid,coinaddr)) != 0 ) free_json(txobj); if ( (tx= LP_transactionfind(coin,txid)) != 0 ) { @@ -765,117 +710,518 @@ int32_t LP_validSPV(char *symbol,char *coinaddr,bits256 txid,int32_t vout) } 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 ) + if ( up->SPV < 0 ) return(-1); } } return(0); } +double LP_trades_alicevalidate(void *ctx,struct LP_quoteinfo *qp) +{ + 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); +} + +void LP_reserved(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp) +{ + double price=0.,maxprice = LP_Alicemaxprice; + //if ( LP_quotecmp(0,qp,&LP_Alicequery) == 0 ) + { + price = LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout); + if ( LP_pricevalid(price) > 0 && maxprice > SMALLVAL && price <= maxprice ) + { + qp->tradeid = LP_Alicequery.tradeid; + LP_Alicereserved = *qp; + LP_alicequery_clear(); + printf("send CONNECT\n"); + LP_query(ctx,myipaddr,mypubsock,"connect",qp); + } else printf("LP_reserved %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); +} + +double LP_trades_bobprice(double *bidp,double *askp,struct LP_quoteinfo *qp) +{ + 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 ) + { + //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 %s/%s validate error %.0f\n",qp->srccoin,qp->destcoin,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 ) + { + sleep(1); + LP_reserved_msg(1,qp->srccoin,qp->destcoin,qp->desthash,jprint(reqjson,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 ) + { + 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) + { + 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 ) + { + 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; + } + 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 ) + { + if ( tp->iambob == 0 ) + { + if ( funcid == LP_RESERVED ) + { + if ( tp->connectsent == 0 ) + flag = LP_trades_bestpricecheck(ctx,tp); + } + else if ( funcid == LP_CONNECTED && tp->connectsent != 0 && tp->negotiationdone == 0 ) // alice all done + { + flag = 1; + tp->negotiationdone = now; + LP_trades_gotconnected(ctx,&tp->Q,&tp->Qs[LP_CONNECTED],tp->pairstr); + } + } + else + { + 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 ( flag != 0 ) + { + tp->lastprocessed = (uint32_t)time(NULL); + nonz++; + } + } + } + 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 ) + { + if ( tp->iambob == 0 ) + { + 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); + } + } + } + if ( nonz == 0 ) + sleep(1); + } +} + +void LP_tradecommandQ(struct LP_quoteinfo *qp,char *pairstr,int32_t funcid) +{ + 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); +} + int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen) { - char *method,*msg,*retstr,str[65]; int32_t DEXselector = 0; uint64_t aliceid; cJSON *retjson; double qprice,range,bestprice,price,bid,ask; struct LP_utxoinfo A,B,*autxo,*butxo; struct iguana_info *coin; struct LP_address_utxo *utxos[1000]; struct LP_quoteinfo Q; int32_t r,counter,retval = -1,max=(int32_t)(sizeof(utxos)/sizeof(*utxos)); + 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) ) { - // LP_checksig LP_quoteparse(&Q,argjson); LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-Q.txfee,Q.destcoin,Q.destsatoshis-Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector); LP_tradecommand_log(argjson); - printf("(%-10u %10u) %12s aliceid.%22llu %5s/%-5s %12.8f -> %12.8f price %12.8f\n",Q.R.requestid,Q.R.quoteid,method,(long long)Q.aliceid,Q.srccoin,Q.destcoin,dstr(Q.satoshis),dstr(Q.destsatoshis),(double)Q.destsatoshis/Q.satoshis); + 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); + LP_autoprices_update(method,Q.srccoin,dstr(Q.satoshis),Q.destcoin,dstr(Q.destsatoshis)); retval = 1; - autxo = &A; - butxo = &B; - memset(autxo,0,sizeof(*autxo)); - memset(butxo,0,sizeof(*butxo)); - LP_abutxo_set(autxo,butxo,&Q); aliceid = j64bits(argjson,"aliceid"); qprice = jdouble(argjson,"price"); if ( strcmp(method,"reserved") == 0 ) { bestprice = LP_bob_competition(&counter,aliceid,qprice,1); //printf("%s lag %ld: aliceid.%llu price %.8f -> bestprice %.8f Alice max %.8f\n",jprint(argjson,0),Q.quotetime - (time(NULL)-20),(long long)aliceid,qprice,bestprice,LP_Alicemaxprice); - if ( LP_Alicemaxprice == 0. ) - return(retval); - if ( bits256_nonz(LP_Alicedestpubkey) != 0 ) - { - if (bits256_cmp(LP_Alicedestpubkey,Q.srchash) != 0 ) - { - printf("got reserved response from different node %s\n",bits256_str(str,Q.srchash)); - return(retval); - } else printf("got reserved response from destpubkey %s\n",bits256_str(str,Q.srchash)); - } - if ( bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 && Q.quotetime > time(NULL)-20 && LP_alice_eligible(Q.quotetime) > 0 ) + if ( 0 ) { - printf("alice %s received RESERVED.(%s)\n",bits256_str(str,G.LP_mypub25519),jprint(argjson,0)); - if ( (qprice= LP_quote_validate(autxo,butxo,&Q,0)) <= SMALLVAL ) - { - printf("reserved quote validate error %.0f\n",qprice); + if ( LP_Alicemaxprice == 0. ) return(retval); - } - if ( LP_validSPV(Q.srccoin,Q.coinaddr,Q.txid,Q.vout) < 0 ) + if ( bits256_nonz(LP_Alicedestpubkey) != 0 ) { - printf("%s src %s failed SPV check\n",Q.srccoin,bits256_str(str,Q.txid)); - return(retval); + if (bits256_cmp(LP_Alicedestpubkey,Q.srchash) != 0 ) + { + printf("got reserved response from different node %s\n",bits256_str(str,Q.srchash)); + return(retval); + } else printf("got reserved response from destpubkey %s\n",bits256_str(str,Q.srchash)); } - else if ( LP_validSPV(Q.srccoin,Q.coinaddr,Q.txid2,Q.vout2) < 0 ) + } + if ( bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 ) + { + if ( Qtrades == 0 ) { - printf("%s src2 %s failed SPV check\n",Q.srccoin,bits256_str(str,Q.txid2)); - return(retval); - } - LP_aliceid(Q.tradeid,Q.aliceid,"reserved",0,0); - if ( (retstr= LP_quotereceived(argjson)) != 0 ) - free(retstr); - LP_reserved(ctx,myipaddr,pubsock,&Q); + if ( Q.quotetime > time(NULL)-20 && LP_alice_eligible(Q.quotetime) > 0 ) + { + LP_trades_gotreserved(ctx,&Q,&Q2); + if ( LP_quotecmp(0,&Q,&LP_Alicequery) == 0 ) + LP_reserved(ctx,LP_myipaddr,LP_mypubsock,&Q); + } + } else LP_tradecommandQ(&Q,jstr(argjson,"pair"),LP_RESERVED); } - return(retval); } else if ( strcmp(method,"connected") == 0 ) { bestprice = LP_bob_competition(&counter,aliceid,qprice,1000); if ( bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 ) { - if ( (qprice= LP_quote_validate(autxo,butxo,&Q,0)) <= SMALLVAL ) - { - printf("quote validate error %.0f\n",qprice); - return(retval); - } - if ( LP_validSPV(Q.srccoin,Q.coinaddr,Q.txid,Q.vout) < 0 ) - { - printf("%s src %s failed SPV check\n",Q.srccoin,bits256_str(str,Q.txid)); - return(retval); - } - else if (LP_validSPV(Q.srccoin,Q.coinaddr,Q.txid2,Q.vout2) < 0 ) - { - printf("%s src2 %s failed SPV check\n",Q.srccoin,bits256_str(str,Q.txid2)); - return(retval); - } - //printf("alice %s received CONNECTED.(%s)\n",bits256_str(str,G.LP_mypub25519),jprint(argjson,0)); - if ( (retstr= LP_connectedalice(argjson)) != 0 ) - free(retstr); + //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); } - return(retval); } price = LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin); - if ( (coin= LP_coinfind(Q.srccoin)) == 0 || price <= SMALLVAL || ask <= SMALLVAL ) + if ( (coin= LP_coinfind(Q.srccoin)) == 0 || coin->inactive != 0 ) { - //printf("this node has no price for %s/%s\n",Q.srccoin,Q.destcoin); + //printf("%s is not active\n",Q.srccoin); return(retval); } - price = ask; - //printf("MYPRICE %s/%s %.8f vs qprice %.8f\n",Q.srccoin,Q.destcoin,price,qprice); - if ( LP_validSPV(Q.destcoin,Q.destaddr,Q.desttxid,Q.destvout) < 0 ) + if ( price <= SMALLVAL || ask <= SMALLVAL ) { - printf("%s dest %s failed SPV check\n",Q.destcoin,bits256_str(str,Q.desttxid)); - return(retval); - } - else if (LP_validSPV(Q.destcoin,Q.destaddr,Q.feetxid,Q.feevout) < 0 ) - { - printf("%s dexfee %s failed SPV check\n",Q.destcoin,bits256_str(str,Q.feetxid)); + //printf("this node has no price for %s/%s\n",Q.srccoin,Q.destcoin); return(retval); } if ( LP_aliceonly(Q.srccoin) > 0 ) @@ -885,230 +1231,32 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, } if ( strcmp(method,"request") == 0 ) { - char str[65]; - if ( bits256_nonz(Q.srchash) == 0 || bits256_cmp(Q.srchash,G.LP_mypub25519) == 0 ) - { - qprice = (double)Q.destsatoshis / Q.satoshis; - strcpy(Q.gui,G.gui); - strcpy(Q.coinaddr,coin->smartaddr); - strcpy(butxo->coinaddr,coin->smartaddr); - Q.srchash = G.LP_mypub25519; - memset(&Q.txid,0,sizeof(Q.txid)); - memset(&Q.txid2,0,sizeof(Q.txid2)); - Q.vout = Q.vout2 = -1; - } else return(retval); - if ( qprice > price ) - { - r = (LP_rand() % 100); - range = (qprice - price); - price += (r * range) / 100.; - bestprice = LP_bob_competition(&counter,aliceid,price,0); - printf(">>>>>>>>>>>>> price %.8f qprice %.8f r.%d range %.8f -> %.8f, bestprice %.8f counter.%d\n",ask,qprice,r,range,price,bestprice,counter); - if ( counter > 3 || price > bestprice ) // skip if late or bad price - return(retval); - } else return(retval); - LP_RTmetrics_update(Q.srccoin,Q.destcoin); - if ( LP_RTmetrics_blacklisted(Q.desthash) >= 0 ) - { - printf("request from blacklisted %s, ignore\n",bits256_str(str,Q.desthash)); - return(retval); - } - LP_address_utxo_reset(coin); - if ( (butxo= LP_address_myutxopair(butxo,1,utxos,max,LP_coinfind(Q.srccoin),Q.coinaddr,Q.txfee,dstr(Q.destsatoshis),price,Q.desttxfee)) != 0 ) - { - strcpy(Q.gui,G.gui); - strcpy(Q.coinaddr,coin->smartaddr); - Q.srchash = G.LP_mypub25519; - Q.txid = butxo->payment.txid; - Q.vout = butxo->payment.vout; - Q.txid2 = butxo->deposit.txid; - Q.vout2 = butxo->deposit.vout; - Q.satoshis = butxo->S.satoshis; - Q.quotetime = (uint32_t)time(NULL); - printf("found %.8f -> %.8f newprice %.8f vs ask %.8f += %.8f qprice %.8f\n",dstr(Q.satoshis),dstr(Q.destsatoshis),(double)Q.destsatoshis/Q.satoshis,ask,price,qprice); - } - else - { - printf("cant find utxopair aliceid.%llu %s/%s %.8f -> relvol %.8f\n",(long long)aliceid,Q.srccoin,Q.destcoin,dstr(LP_basesatoshis(dstr(Q.destsatoshis),price,Q.txfee,Q.desttxfee)),dstr(Q.destsatoshis)); - return(retval); - } + 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 ) { - if ( bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 || bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 ) - return(retval); - } - if ( strcmp(Q.coinaddr,coin->smartaddr) != 0 ) - { - printf("bob is patching Q.coinaddr %s mismatch != %s\n",Q.coinaddr,coin->smartaddr); - strcpy(Q.coinaddr,coin->smartaddr); - } - if ( butxo == 0 || bits256_nonz(butxo->payment.txid) == 0 || bits256_nonz(butxo->deposit.txid) == 0 || butxo->payment.vout < 0 || butxo->deposit.vout < 0 ) - { - char str[65],str2[65]; printf("couldnt find bob utxos for autxo %s/v%d %s/v%d %.8f -> %.8f\n",bits256_str(str,Q.txid),Q.vout,bits256_str(str2,Q.txid2),Q.vout2,dstr(Q.satoshis),dstr(Q.destsatoshis)); - return(retval); - } - if ( (qprice= LP_quote_validate(autxo,butxo,&Q,1)) <= SMALLVAL ) - { - printf("quote validate error %.0f\n",qprice); - return(-3); - } - if ( qprice < (ask - 0.00000001) * 0.998 ) - { - printf("(%.8f %.8f) quote price %.8f too low vs %.8f for %s/%s %.8f < %.8f\n",bid,ask,qprice,price,Q.srccoin,Q.destcoin,qprice,(ask - 0.00000001) * 0.998); - return(retval); - } - char *astr = jprint(argjson,0); - char str[65],str2[65]; printf("(%s/v%d %s/v%d) TRADECOMMAND.(%s)\n",bits256_str(str,Q.txid),Q.vout,bits256_str(str2,Q.txid2),Q.vout2,astr); - free(astr); - if ( strcmp(method,"request") == 0 ) // bob needs apayment + fee tx's - { - if ( LP_allocated(Q.txid,Q.vout) == 0 && LP_allocated(Q.txid2,Q.vout2) == 0 ) + LP_bob_competition(&counter,aliceid,qprice,1000); + if ( bits256_cmp(G.LP_mypub25519,Q.srchash) == 0 && bits256_cmp(G.LP_mypub25519,Q.desthash) != 0 ) { - retjson = LP_quotejson(&Q); - LP_unavailableset(Q.txid,Q.vout,Q.timestamp + LP_RESERVETIME,Q.desthash); - LP_unavailableset(Q.txid2,Q.vout2,Q.timestamp + LP_RESERVETIME,Q.desthash); - if ( Q.quotetime == 0 ) - Q.quotetime = (uint32_t)time(NULL); - jaddnum(retjson,"quotetime",Q.quotetime); - jaddnum(retjson,"pending",Q.timestamp + LP_RESERVETIME); - //jaddbits256(retjson,"desthash",Q.desthash); - jaddstr(retjson,"method","reserved"); - msg = jprint(retjson,0); - printf("return after queued RESERVED: set swappending.%u accept qprice %.8f, min %.8f\n(%s)\n",Q.timestamp + LP_RESERVETIME,qprice,ask,msg); - LP_reserved_msg(1,Q.srccoin,Q.destcoin,Q.desthash,clonestr(msg)); - sleep(1); - bits256 zero; - memset(zero.bytes,0,sizeof(zero)); - LP_reserved_msg(1,Q.srccoin,Q.destcoin,zero,msg); - free_json(retjson); - butxo->T.lasttime = (uint32_t)time(NULL); - return(retval); - } else printf("request processing selected ineligible utxos?\n"); - } - else if ( strcmp(method,"connect") == 0 ) // bob - { - retval = 4; - if ( LP_reservation_check(Q.txid,Q.vout,Q.desthash) == 0 && LP_reservation_check(Q.txid2,Q.vout2,Q.desthash) == 0 ) - { - LP_connectstartbob(ctx,pubsock,argjson,Q.srccoin,Q.destcoin,qprice,&Q); - return(retval); - } else printf("connect message from non-reserved (%s)\n",jprint(argjson,0)); - } - } - return(retval); -} - -#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_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 = 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); + 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); } - free_json(orderbook); } - free(obookstr); + 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); } -#endif 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; int64_t bestsatoshis=0,destsatoshis; struct iguana_info *basecoin,*relcoin; struct LP_utxoinfo *autxo,B; 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 ) @@ -1139,8 +1287,12 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel timeout = 1.5*LP_AUTOTRADE_TIMEOUT; } if ( time(NULL) < Alice_expiration ) - return(clonestr("{\"error\":\"only one pending request at a time\"}")); - else LP_alicequery_clear(); + { + 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 ) @@ -1148,27 +1300,28 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel else maxprice *= 1.001; memset(pubkeys,0,sizeof(pubkeys)); LP_txfees(&txfee,&desttxfee,base,rel); - destsatoshis = SATOSHIDEN * relvolume; + destsatoshis = SATOSHIDEN * relvolume + 2*desttxfee; + memset(&A,0,sizeof(A)); LP_address_utxo_reset(relcoin); - if ( (autxo= LP_utxo_bestfit(rel,destsatoshis + 2*desttxfee)) == 0 ) - return(clonestr("{\"error\":\"cant find alice utxo that is big enough\"}")); - //printf("bestfit selected alice (%.8f %.8f) for %.8f sats %.8f\n",dstr(autxo->payment.value),dstr(autxo->fee.value),dstr(destsatoshis),dstr(autxo->S.satoshis)); - if ( destsatoshis - desttxfee < autxo->S.satoshis ) + if ( (autxo= LP_address_myutxopair(&A,0,utxos,max,relcoin,relcoin->smartaddr,txfee,dstr(destsatoshis),maxprice,desttxfee)) == 0 ) + return(clonestr("{\"error\":\"cant find a deposit that is close enough in size. make another deposit that is just a bit larger than what you want to trade\"}")); + //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->S.satoshis = destsatoshis; - //printf("first path dest %.8f from %.8f\n",dstr(destsatoshis),dstr(autxo->S.satoshis)); + autxo->swap_satoshis = destsatoshis; + //printf("first path dest %.8f from %.8f\n",dstr(destsatoshis),dstr(autxo->swap_satoshis)); } - else if ( autxo->S.satoshis - desttxfee < destsatoshis ) + else if ( autxo->swap_satoshis - desttxfee < destsatoshis ) { - autxo->S.satoshis -= desttxfee; - destsatoshis = autxo->S.satoshis; - printf("second path dest %.8f from %.8f\n",dstr(destsatoshis),dstr(autxo->S.satoshis)); + 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\"}")); + return(clonestr("{\"error\":\"cant find a deposit that is close enough in size. make another deposit that is just a bit larger than what you want to trade\"}")); } bestsatoshis = 1.001 * LP_basesatoshis(dstr(destsatoshis),maxprice,txfee,desttxfee); memset(&B,0,sizeof(B)); @@ -1179,50 +1332,8 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel 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)); -#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 } diff --git a/iguana/exchanges/LP_peers.c b/iguana/exchanges/LP_peers.c index 4e5e9a231..593046706 100644 --- a/iguana/exchanges/LP_peers.c +++ b/iguana/exchanges/LP_peers.c @@ -212,8 +212,8 @@ void LP_peer_recv(char *ipaddr,int32_t ismine) if ( (peer= LP_peerfind((uint32_t)calc_ipbits(ipaddr),RPC_port)) != 0 ) { peer->numrecv++; - if ( ismine != 0 ) - peer->recvtime = (uint32_t)time(NULL); + //if ( ismine != 0 ) + peer->recvtime = (uint32_t)time(NULL); } } @@ -262,7 +262,7 @@ uint16_t LP_rarestpeer(char *destip) { HASH_ITER(hh,LP_peerinfos,peer,tmp) { - if ( iter == 0 && peer->recvtime < now-3600*24 ) + if ( strcmp(peer->ipaddr,LP_myipaddr) != 0 && iter == 0 && peer->recvtime < now-3600 ) continue; if ( peer->isLP != 0 ) { diff --git a/iguana/exchanges/LP_portfolio.c b/iguana/exchanges/LP_portfolio.c index 4004a8c41..7af4741d0 100644 --- a/iguana/exchanges/LP_portfolio.c +++ b/iguana/exchanges/LP_portfolio.c @@ -18,9 +18,53 @@ // marketmaker // +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 buymargin,sellmargin,factor,offset,lastbid,lastask; + cJSON *fundvalue; + uint32_t count; +} LP_autorefs[1024]; + +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 +92,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 +108,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 +120,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 +140,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 +245,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[65],refrel[65],base[65],rel[65]; -} LP_autorefs[100]; - /*int32_t LP_autofill(char *base,char *rel,double maxprice,double totalrelvolume) { struct LP_priceinfo *basepp,*relpp; @@ -219,64 +258,12 @@ 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,fixedprice; - //printf("autoprice.(%s %s) %s\n",base,rel,jprint(argjson,0)); - if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) - { - if ( jobj(argjson,"minprice") != 0 ) - minprice = jdouble(argjson,"minprice"); - else minprice = 0.; - margin = jdouble(argjson,"margin"); - offset = jdouble(argjson,"offset"); - factor = jdouble(argjson,"factor"); - fixedprice = jdouble(argjson,"fixed"); - basepp->fixedprices[relpp->ind] = fixedprice; - basepp->minprices[relpp->ind] = minprice; - basepp->margins[relpp->ind] = margin; - basepp->offsets[relpp->ind] = offset; - basepp->factors[relpp->ind] = factor; - if ( fixedprice > SMALLVAL || ((refbase= jstr(argjson,"refbase")) != 0 && (refrel= jstr(argjson,"refrel")) != 0) ) - { - if ( fixedprice > SMALLVAL ) - { - refbase = base; - refrel = rel; - } - for (i=0; imargins[relpp->ind]; - oppomargin = relpp->margins[basepp->ind]; + margin = basepp->sellmargins[relpp->ind]; + oppomargin = basepp->buymargins[relpp->ind]; if ( (fixedprice= basepp->fixedprices[relpp->ind]) > SMALLVAL ) { LP_mypriceset(&changed,relpp->symbol,basepp->symbol,fixedprice); @@ -291,7 +278,7 @@ void LP_autopriceset(void *ctx,int32_t dir,struct LP_priceinfo *basepp,struct LP if ( fabs(price) < SMALLVAL && refbase != 0 && refrel != 0 ) { price = LP_myprice(&bid,&ask,refbase,refrel); - //printf("%s/%s USE ref %s/%s %.8f factor %.8f offset %.8f margin %.8f\n",basepp->symbol,relpp->symbol,refbase,refrel,price,factor,offset,margin); + //printf("%s/%s USE ref %s/%s %.8f factor %.8f offset %.8f margin %.8f/%.8f\n",basepp->symbol,relpp->symbol,refbase,refrel,price,factor,offset,oppomargin,margin); } if ( LP_pricevalid(price) > 0 ) { @@ -309,8 +296,15 @@ void LP_autopriceset(void *ctx,int32_t dir,struct LP_priceinfo *basepp,struct LP else newprice = (price * (1. + margin)); if ( (minprice= basepp->minprices[relpp->ind]) == 0. || price >= minprice ) { + if ( ind >= 0 ) + { + if ( LP_autorefs[ind].lastask < SMALLVAL ) + LP_autorefs[ind].lastask = newprice; + else LP_autorefs[ind].lastask = (LP_autorefs[ind].lastask * 0.9) + (0.1 *newprice); + newprice = LP_autorefs[ind].lastask; + //printf("autopriceset %s/%s <- %.8f %.8f (%.8f %.8f)\n",basepp->symbol,relpp->symbol,price,newprice,LP_autorefs[ind].lastbid,LP_autorefs[ind].lastask); + } LP_mypriceset(&changed,relpp->symbol,basepp->symbol,newprice); - //printf("autoprice changed.%d %s/%s <- %.8f\n",changed,basepp->symbol,relpp->symbol,price); if ( changed != 0 || time(NULL) > lasttime+LP_ORDERBOOK_DURATION*.777) { lasttime = (uint32_t)time(NULL); @@ -397,8 +391,8 @@ double LP_pricesparse(void *ctx,int32_t trexflag,char *retstr,struct LP_priceinf //printf("have trex: iter.%d trexflag.%d %s %.8f %.8f\n",iter,trexflag,symbol,coinpp->bid[1],coinpp->ask[1]); continue; } - LP_autopriceset(ctx,1,coinpp,refpp,price,0,0); - LP_autopriceset(ctx,-1,refpp,coinpp,price,0,0); + LP_autopriceset(-1,ctx,1,coinpp,refpp,price,0,0); + LP_autopriceset(-1,ctx,-1,refpp,coinpp,price,0,0); } } } @@ -414,9 +408,49 @@ double LP_pricesparse(void *ctx,int32_t trexflag,char *retstr,struct LP_priceinf return(nxtkmd); } +double LP_autoprice_newprice(int32_t bidask,double price,double newprice) +{ + double gap; int32_t r; + if ( (bidask == 0 && newprice < price) || (bidask != 0 && newprice > price) ) + { + gap = fabs(newprice - price) * 2; + r = (rand() % 100); + if ( bidask == 0 ) + price -= (gap * r) / 100.; + else price += (gap * r) / 100.; + } + else if ( price > SMALLVAL ) + price = (price * 0.95) + (0.05 * newprice); + else price = newprice; + return(price); +} + +double LP_tickered_price(int32_t bidask,char *base,char *rel,double price,cJSON *tickerjson) +{ + int32_t i,n; cJSON *item; double basevol,relvol,itemprice; + //printf("%s %s/%s %.8f -> ",bidask == 0 ? "bid" : "ask",base,rel,price); + if ( (n= cJSON_GetArraySize(tickerjson)) > 0 ) + { + for (i=n-1; i>=0; i--) + { + // {"timestamp":1513235320,"KMD":860.45202538,"SUPERNET":20.00010000,"price":0.02324371} + item = jitem(tickerjson,i); + if ( (basevol= jdouble(item,base)) > SMALLVAL && (relvol= jdouble(item,rel)) > SMALLVAL ) + { + itemprice = (relvol / basevol); + //printf("%.8f ",itemprice); + price = LP_autoprice_newprice(bidask,price,itemprice); + } + } + } + //printf("-> %.8f\n",price); + return(price); +} + 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; + static cJSON *tickerjson; static uint32_t lasttime; + char *retstr,*base,*rel; cJSON *retjson,*bid,*ask,*fundjson,*argjson; uint64_t bidsatoshis,asksatoshis; int32_t i,changed; double bch_usd,bch_btc,nxtkmd,price,factor,offset,newprice,buymargin,sellmargin,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"); @@ -436,21 +470,21 @@ void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp) if ( (kmdpp= LP_priceinfofind("KMD")) != 0 ) { for (i=0; i<32; i++) - { + {break; if ( (fiatpp= LP_priceinfofind(CURRENCIES[i])) != 0 ) { if ( (retjson= LP_paxprice(CURRENCIES[i])) != 0 ) { //printf("(%s %.8f %.8f) ",CURRENCIES[i],jdouble(retjson,"price"),jdouble(retjson,"invprice")); price = jdouble(retjson,"price"); - LP_autopriceset(ctx,1,fiatpp,kmdpp,price,0,0); - LP_autopriceset(ctx,-1,kmdpp,fiatpp,price,0,0); + LP_autopriceset(-1,ctx,1,fiatpp,kmdpp,price,0,0); + LP_autopriceset(-1,ctx,-1,kmdpp,fiatpp,price,0,0); free_json(retjson); } } } } - if ( nxtkmd > SMALLVAL ) + if ( 0 && nxtkmd > SMALLVAL ) { for (i=0; i (%s) nxtkmd %.8f %.8f %.8f\n",assetids[i][1],assetids[i][0],jprint(retjson,0),nxtkmd,0.5*dstr(bidsatoshis + asksatoshis),price); free_json(retjson); } } } } + if ( time(NULL) > lasttime+60 ) + { + if ( tickerjson != 0 ) + free_json(tickerjson); + if ( (retstr= LP_ticker("","")) != 0 ) + { + tickerjson = cJSON_Parse(retstr); + free(retstr); + } + } + kmd_btc = LP_CMCbtcprice(&kmd_usd,"komodo"); + bch_btc = LP_CMCbtcprice(&bch_usd,"bitcoin-cash"); for (i=0; i SMALLVAL ) + { + if ( tickerjson != 0 && LP_autorefs[i].count == 0 ) + price = LP_tickered_price(0,base,rel,price,tickerjson); + newprice = (1. / price) * (1. + buymargin); + if ( LP_autorefs[i].lastbid < SMALLVAL ) + LP_autorefs[i].lastbid = newprice; + else LP_autorefs[i].lastbid = (LP_autorefs[i].lastbid * 0.9) + (0.1 *newprice); + newprice = LP_autorefs[i].lastbid; + 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 ) + { + if ( tickerjson != 0 && LP_autorefs[i].count == 0 ) + price = LP_tickered_price(1,base,rel,price,tickerjson); + newprice = (price * (1. + sellmargin)); + if ( LP_autorefs[i].lastask < SMALLVAL ) + LP_autorefs[i].lastask = newprice; + else LP_autorefs[i].lastask = (LP_autorefs[i].lastask * 0.9) + (0.1 *newprice); + newprice = LP_autorefs[i].lastask; + 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); + } + LP_autorefs[i].count++; + } + free_json(fundjson); + } + } + else if ( strcmp(LP_autorefs[i].refrel,"coinmarketcap") == 0 ) + { + //printf("%s/%s for %s/%s margin %.8f/%.8f\n",base,rel,LP_autorefs[i].refbase,LP_autorefs[i].refrel,buymargin,sellmargin); + if ( (price_btc= LP_CMCbtcprice(&price_usd,LP_autorefs[i].refbase)) > SMALLVAL ) + { + if ( strcmp(rel,"KMD") == 0 && kmd_btc > SMALLVAL ) + price = kmd_btc / price_btc; + else if ( strcmp(rel,"BCH") == 0 && bch_btc > SMALLVAL ) + price = bch_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. + buymargin)); + if ( LP_autorefs[i].lastbid < SMALLVAL ) + LP_autorefs[i].lastbid = newprice; + else LP_autorefs[i].lastbid = (LP_autorefs[i].lastbid * 0.9) + (0.1 *newprice); + newprice = LP_autorefs[i].lastbid; + LP_mypriceset(&changed,rel,base,newprice); + LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,rel,base,newprice); + //printf("price %.8f margin %.8f/%.8f newprice %.8f %.8f\n",price,buymargin,sellmargin,newprice,(1. / price) * (1. + buymargin)); + newprice = (1. / price) * (1. + sellmargin); + if ( LP_autorefs[i].lastask < SMALLVAL ) + LP_autorefs[i].lastask = newprice; + else LP_autorefs[i].lastask = (LP_autorefs[i].lastask * 0.9) + (0.1 *newprice); + newprice = LP_autorefs[i].lastask; + 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 (%.8f %.8f)\n",LP_autorefs[i].refbase,LP_autorefs[i].refrel,relpp->fixedprices[basepp->ind],basepp->fixedprices[relpp->ind],LP_autorefs[i].lastbid,LP_autorefs[i].lastask); + LP_autopriceset(i,ctx,1,basepp,relpp,0.,LP_autorefs[i].refbase,LP_autorefs[i].refrel); + } + } + } +} + +void LP_autoprices_update(char *method,char *base,double basevol,char *rel,double relvol) +{ + int32_t i; double price,newprice; + if ( basevol > 0. && relvol > 0. ) + { + price = relvol/basevol; + for (i=0; i 0 ) + { + printf("%s: autoprice ask update %s/%s %.8f vs myprice %.8f/%.8f -> %.8f\n",method,base,rel,price,LP_autorefs[i].lastbid,LP_autorefs[i].lastask,newprice); + LP_autorefs[i].lastask = newprice; + } // else printf("%s: autoprice ask skip update %s/%s %.8f vs myprice %.8f/%.8f -> %.8f\n",method,base,rel,price,LP_autorefs[i].lastbid,LP_autorefs[i].lastask,newprice); + } + else if ( strcmp(LP_autorefs[i].rel,base) == 0 && strcmp(rel,LP_autorefs[i].base) == 0 ) + { + newprice = (LP_autorefs[i].lastbid * 0.99) + (0.01 * price); + if ( LP_autorefs[i].lastbid > 0 ) + { + printf("%s: autoprice bid update %s/%s %.8f vs myprice %.8f/%.8f -> %.8f\n",method,base,rel,price,LP_autorefs[i].lastbid,LP_autorefs[i].lastask,newprice); + LP_autorefs[i].lastbid = newprice; + } // else printf("%s: autoprice bid skip update %s/%s %.8f vs myprice %.8f/%.8f -> %.8f\n",method,base,rel,price,LP_autorefs[i].lastbid,LP_autorefs[i].lastask,newprice); + } + } + } +} + +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 margin,minprice,buymargin,sellmargin,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.; + if ( (margin= jdouble(argjson,"margin")) == 0. ) + { + buymargin = jdouble(argjson,"buymargin"); + sellmargin = jdouble(argjson,"sellmargin"); + } + else { - //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); + buymargin = margin; + sellmargin = margin; } + offset = jdouble(argjson,"offset"); + factor = jdouble(argjson,"factor"); + fixedprice = jdouble(argjson,"fixed"); + basepp->fixedprices[relpp->ind] = fixedprice; + basepp->minprices[relpp->ind] = minprice; + basepp->buymargins[relpp->ind] = buymargin; + basepp->sellmargins[relpp->ind] = sellmargin; + 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; @@ -507,7 +754,8 @@ 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,1)) != 0 ) @@ -531,7 +779,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; @@ -553,8 +802,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[65],sellcoin[65]; }; - 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]; @@ -605,7 +852,7 @@ 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; strcpy(prices_loop_stats.name,"prices_loop"); - prices_loop_stats.threshold = 91000.; + prices_loop_stats.threshold = 191000.; while ( 1 ) { //printf("prices loop autoprices.%d autorefs.%d\n",LP_autoprices,num_LP_autorefs); diff --git a/iguana/exchanges/LP_prices.c b/iguana/exchanges/LP_prices.c index 7c91647aa..cf14f204f 100644 --- a/iguana/exchanges/LP_prices.c +++ b/iguana/exchanges/LP_prices.c @@ -18,24 +18,30 @@ // marketmaker // -struct LP_orderbookentry { bits256 pubkey; double price; uint64_t avesatoshis,maxsatoshis,depth; uint32_t timestamp; int32_t numutxos; char coinaddr[64]; }; +struct LP_orderbookentry +{ + bits256 pubkey; + double price; + int64_t avesatoshis,maxsatoshis,depth,dynamictrust; + uint32_t timestamp; + int32_t numutxos; + char coinaddr[64]; +}; struct LP_priceinfo { 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 buymargins[LP_MAXPRICEINFOS]; + double sellmargins[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; @@ -48,8 +54,23 @@ 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->buymargins,0,sizeof(pp->buymargins)); + memset(pp->sellmargins,0,sizeof(pp->sellmargins)); + 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_pubkeyinfo *pubp,uint32_t baseind,uint32_t relind) +float LP_pubkey_price(int32_t *numutxosp,int64_t *avesatoshisp,int64_t *maxsatoshisp,struct LP_pubkey_info *pubp,uint32_t baseind,uint32_t relind) { struct LP_pubkey_quote *pq,*tmp; int32_t scale; int64_t scale64; *numutxosp = 0; @@ -75,7 +96,7 @@ float LP_pubkey_price(int32_t *numutxosp,int64_t *avesatoshisp,int64_t *maxsatos return(0); } -void LP_pubkey_update(struct LP_pubkeyinfo *pubp,uint32_t baseind,uint32_t relind,float price,int64_t balance,char *utxocoin,int32_t numutxos,int64_t minutxo,int64_t maxutxo) +void LP_pubkey_update(struct LP_pubkey_info *pubp,uint32_t baseind,uint32_t relind,float price,int64_t balance,char *utxocoin,int32_t numutxos,int64_t minutxo,int64_t maxutxo) { struct LP_pubkey_quote *pq,*tmp; int64_t aveutxo,scale64,ave64,max64; int32_t scale; DL_FOREACH_SAFE(pubp->quotes,pq,tmp) @@ -91,7 +112,9 @@ void LP_pubkey_update(struct LP_pubkeyinfo *pubp,uint32_t baseind,uint32_t relin 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 ) { @@ -114,10 +137,13 @@ void LP_pubkey_update(struct LP_pubkeyinfo *pubp,uint32_t baseind,uint32_t relin max64 = (1LL << 32) - 1; pq->aveutxo = (uint32_t)ave64; pq->maxutxo = (uint32_t)max64; - //printf("price %.8f base.%s rel.%s utxocoin.%s balance %.8f numutxos.%u %u scale64 = %llu, ave %llu, ave32 %u (%llu) max32 %u (%llu)\n",price,LP_priceinfos[baseind].symbol,LP_priceinfos[relind].symbol,utxocoin,dstr(balance),numutxos,pq->numutxos,(long long)scale64,(long long)aveutxo,pq->aveutxo,(long long)pq->aveutxo * scale64,pq->maxutxo,(long long)pq->maxutxo * scale64); - //int64_t avesatoshis,maxsatoshis; - //price = LP_pubkey_price(&numutxos,&avesatoshis,&maxsatoshis,pubp,baseind,relind); - //printf("checkprice %.8f numutxos.%d ave %.8f max %.8f\n",price,numutxos,dstr(avesatoshis),dstr(maxsatoshis)); + 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)); + } } } @@ -214,9 +240,9 @@ struct LP_cacheinfo *LP_cachefind(char *base,char *rel,bits256 txid,int32_t vout return(ptr); } -struct LP_pubkeyinfo *LP_pubkey_rmd160find(uint8_t rmd160[20]) +struct LP_pubkey_info *LP_pubkey_rmd160find(uint8_t rmd160[20]) { - struct LP_pubkeyinfo *pubp=0,*tmp; + struct LP_pubkey_info *pubp=0,*tmp; portable_mutex_lock(&LP_pubkeymutex); HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) { @@ -230,7 +256,7 @@ struct LP_pubkeyinfo *LP_pubkey_rmd160find(uint8_t rmd160[20]) struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr) { - uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkeyinfo *pubp; + uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkey_info *pubp; HASH_FIND(hh,coin->addresses,coinaddr,strlen(coinaddr),ap); if ( ap != 0 && bits256_nonz(ap->pubkey) == 0 ) { @@ -246,7 +272,7 @@ struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr) struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr) { - uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkeyinfo *pubp; + uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkey_info *pubp; ap = calloc(1,sizeof(*ap)); safecopy(ap->coinaddr,coinaddr,sizeof(ap->coinaddr)); bitcoin_addr2rmd160(coin->taddr,&addrtype,rmd160,coinaddr); @@ -260,18 +286,18 @@ struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr) return(ap); } -struct LP_pubkeyinfo *LP_pubkeyfind(bits256 pubkey) +struct LP_pubkey_info *LP_pubkeyfind(bits256 pubkey) { - struct LP_pubkeyinfo *pubp=0; + struct LP_pubkey_info *pubp=0; portable_mutex_lock(&LP_pubkeymutex); HASH_FIND(hh,LP_pubkeyinfos,&pubkey,sizeof(pubkey),pubp); portable_mutex_unlock(&LP_pubkeymutex); return(pubp); } -struct LP_pubkeyinfo *LP_pubkeyadd(bits256 pubkey) +struct LP_pubkey_info *LP_pubkeyadd(bits256 pubkey) { - char str[65]; struct LP_pubkeyinfo *pubp=0; + char str[65]; struct LP_pubkey_info *pubp=0; portable_mutex_lock(&LP_pubkeymutex); HASH_FIND(hh,LP_pubkeyinfos,&pubkey,sizeof(pubkey),pubp); if ( pubp == 0 ) @@ -294,7 +320,7 @@ struct LP_pubkeyinfo *LP_pubkeyadd(bits256 pubkey) int32_t LP_pubkey_istrusted(bits256 pubkey) { - struct LP_pubkeyinfo *pubp; + struct LP_pubkey_info *pubp; if ( (pubp= LP_pubkeyadd(pubkey)) != 0 ) return(pubp->istrusted != 0); return(0); @@ -302,7 +328,7 @@ int32_t LP_pubkey_istrusted(bits256 pubkey) char *LP_pubkey_trustset(bits256 pubkey,uint32_t trustval) { - struct LP_pubkeyinfo *pubp; + struct LP_pubkey_info *pubp; if ( (pubp= LP_pubkeyadd(pubkey)) != 0 ) { pubp->istrusted = trustval; @@ -313,7 +339,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 ) @@ -322,10 +348,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; @@ -343,7 +369,7 @@ uint64_t LP_unspents_metric(struct iguana_info *coin,char *coinaddr) return(metric); } -cJSON *LP_pubkeyjson(struct LP_pubkeyinfo *pubp) +cJSON *LP_pubkeyjson(struct LP_pubkey_info *pubp) { int32_t baseid,relid,numutxos; int64_t avesatoshis,maxsatoshis; char *base,hexstr[67],hexstr2[67],sigstr[256]; double price; cJSON *item,*array,*obj; obj = cJSON_CreateObject(); @@ -380,7 +406,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)); @@ -388,76 +414,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 ) - { - 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; @@ -465,14 +421,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); @@ -486,10 +442,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; } } } @@ -555,13 +511,26 @@ 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; + if ( price == 0. ) + { + relpp->minprices[basepp->ind] = 0.; + relpp->fixedprices[basepp->ind] = 0.; + relpp->buymargins[basepp->ind] = 0.; + relpp->sellmargins[basepp->ind] = 0.; + relpp->offsets[basepp->ind] = 0.; + relpp->factors[basepp->ind] = 0.; + } + /*else if ( basepp->myprices[relpp->ind] > SMALLVAL ) + { + price = (basepp->myprices[relpp->ind] * 0.9) + (0.1 * price); + }*/ basepp->myprices[relpp->ind] = price; // ask //printf("LP_mypriceset base.%s rel.%s <- price %.8f\n",base,rel,price); //relpp->myprices[basepp->ind] = (1. / price); // bid @@ -583,7 +552,9 @@ double LP_price(char *base,char *rel) if ( (basepp= LP_priceinfoptr(&relind,base,rel)) != 0 ) { if ( (price= basepp->myprices[relind]) == 0. ) + { price = basepp->relvals[relind]; + } } return(price); } @@ -750,11 +721,12 @@ cJSON *LP_orderbookjson(char *symbol,struct LP_orderbookentry *op) jaddnum(item,"depth",dstr(op->depth)*0.8); jaddbits256(item,"pubkey",op->pubkey); jaddnum(item,"age",time(NULL)-op->timestamp); + jaddnum(item,"zcredits",dstr(op->dynamictrust)); } return(item); } -struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,double price,int32_t numutxos,uint64_t avesatoshis,uint64_t maxsatoshis,bits256 pubkey,uint32_t timestamp,uint64_t balance) +struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,double price,int32_t numutxos,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 ) @@ -767,13 +739,14 @@ struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,d op->pubkey = pubkey; op->timestamp = timestamp; op->depth = balance; + op->dynamictrust = dynamictrust; } return(op); } void LP_pubkeys_query() { - uint8_t zeroes[20]; bits256 zero; cJSON *reqjson; struct LP_pubkeyinfo *pubp=0,*tmp; + uint8_t zeroes[20]; bits256 zero; cJSON *reqjson; struct LP_pubkey_info *pubp=0,*tmp; memset(zero.bytes,0,sizeof(zero)); memset(zeroes,0,sizeof(zeroes)); HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) @@ -792,7 +765,7 @@ void LP_pubkeys_query() int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *rel,struct LP_orderbookentry *(**arrayp),int32_t num,int32_t cachednum,int32_t duration) { - char coinaddr[64]; uint8_t zeroes[20]; struct LP_pubkeyinfo *pubp=0,*tmp; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; struct LP_address *ap; struct iguana_info *basecoin; uint32_t oldest; double price; int32_t baseid,relid,n; int64_t maxsatoshis,balance,avesatoshis; + char coinaddr[64]; uint8_t zeroes[20]; struct LP_pubkey_info *pubp=0,*tmp; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; struct LP_address *ap; struct iguana_info *basecoin; uint32_t oldest; double price; int32_t baseid,relid,n; int64_t maxsatoshis,balance,avesatoshis; if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 ) baseid = basepp->ind; else return(num); @@ -827,7 +800,7 @@ int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char * } //printf("%s/%s %s n.%d ap->n.%d %.8f\n",base,rel,coinaddr,n,ap->n,dstr(ap->total)); } - if ( (op= LP_orderbookentry(coinaddr,base,rel,polarity > 0 ? price : 1./price,n,avesatoshis,maxsatoshis,pubp->pubkey,pubp->timestamp,balance)) != 0 ) + if ( (op= LP_orderbookentry(coinaddr,base,rel,polarity > 0 ? price : 1./price,n,avesatoshis,maxsatoshis,pubp->pubkey,pubp->timestamp,balance,pubp->dynamictrust)) != 0 ) { *arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1)); (*arrayp)[num++] = op; @@ -840,7 +813,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 ) @@ -887,20 +860,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 < 3 && bids[i]->numutxos == 0 ) { //printf("bid ping %s %s\n",rel,bids[i]->coinaddr); LP_address(relcoin,bids[i]->coinaddr); - if ( 0 && relcoin->electrum == 0 ) + /*if ( 0 && relcoin->electrum == 0 ) { LP_listunspent_issue(rel,bids[i]->coinaddr,0); //else if ( (tmpjson= LP_listunspent(rel,bids[i]->coinaddr)) != 0 ) // free_json(tmpjson); LP_listunspent_query(rel,bids[i]->coinaddr); - } + }*/ n++; } + 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; } @@ -908,23 +887,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 < 3 && asks[i]->numutxos == 0 ) { //printf("ask ping %s %s\n",base,asks[i]->coinaddr); LP_address(basecoin,asks[i]->coinaddr); - if ( 0 && basecoin->electrum == 0 ) + /*if ( 0 && basecoin->electrum == 0 ) { LP_listunspent_issue(base,asks[i]->coinaddr,0); //else if ( (tmpjson= LP_listunspent(base,asks[i]->coinaddr)) != 0 ) // free_json(tmpjson); LP_listunspent_query(base,asks[i]->coinaddr); - } + }*/ n++; } + 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; } @@ -932,6 +918,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); @@ -942,41 +929,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); @@ -1001,7 +979,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 ) @@ -1110,9 +1088,9 @@ 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,char *utxocoin,int32_t numrelutxos,int64_t balance,int64_t minutxo,int64_t maxutxo) +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 ) { @@ -1146,6 +1124,8 @@ void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price,char *u { 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); LP_pubkey_update(pubp,basepp->ind,relpp->ind,price,balance,utxocoin,numrelutxos,minutxo,maxutxo); //pubp->depthinfo[basepp->ind][relpp->ind] = LP_depthinfo_compact(); @@ -1162,3 +1142,105 @@ void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price,char *u // 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..644fdb022 --- /dev/null +++ b/iguana/exchanges/LP_privkey.c @@ -0,0 +1,575 @@ + +/****************************************************************************** + * 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,i %s -> %s %s %s\n",wifstr,bits256_str(str,privkey),cmpstr,bits256_str(str2,cmpkey),cmpstr2); + if ( bits256_cmp(privkey,cmpkey) == 0 ) + return(1); + } + return(0); +} + +bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguana_info *coin,char *passphrase,char *wifstr) +{ + //static uint32_t counter; + bits256 privkey,userpub,zero,userpass,checkkey,tmpkey; char tmpstr[128]; cJSON *retjson; uint8_t tmptype; int32_t notarized; uint64_t nxtaddr; + if ( (wifstr == 0 || wifstr[0] == 0) && LP_wifstr_valid(passphrase) > 0 ) + { + wifstr = passphrase; + passphrase = 0; + } + if ( passphrase != 0 && passphrase[0] != 0 ) + { + calc_NXTaddr(G.LP_NXTaddr,userpub.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); + conv_NXTpassword(privkey.bytes,pubkeyp->bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); + privkey.bytes[0] &= 248, privkey.bytes[31] &= 127, privkey.bytes[31] |= 64; + //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)); + bitcoin_priv2wif(coin->wiftaddr,tmpstr,privkey,coin->wiftype); + bitcoin_wif2priv(coin->wiftaddr,&tmptype,&checkkey,tmpstr); + if ( bits256_cmp(privkey,checkkey) != 0 ) + { + char str[65],str2[65]; printf("mismatched privkeys from wif conversion: %s -> %s -> %s\n",bits256_str(str,privkey),tmpstr,bits256_str(str2,checkkey)); + exit(1); + } + } + else + { + bitcoin_wif2priv(coin->wiftaddr,&tmptype,&privkey,wifstr); + bitcoin_priv2wif(coin->wiftaddr,tmpstr,privkey,tmptype); + if ( strcmp(tmpstr,wifstr) != 0 ) + { + printf("error reproducing the wifstr, likely edge case like non-supported uncompressed pubkey\n"); + exit(1); + } + tmpkey = privkey; + nxtaddr = conv_NXTpassword(tmpkey.bytes,pubkeyp->bytes,0,0); + RS_encode(G.LP_NXTaddr,nxtaddr); + } + 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 ( 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 -> (%s), abort session\n",coin->symbol,coin->smartaddr,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)); + vcalc_sha256(0,G.LP_passhash.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); + 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); +} + +void LP_privkey_tests() +{ + char wifstr[64],str[65],str2[65]; bits256 privkey,checkkey; int32_t i; uint8_t tmptype; + for (i=0; i<200000000; i++) + { + privkey = rand256(0); + bitcoin_priv2wif(0,wifstr,privkey,0xff); + bitcoin_wif2priv(0,&tmptype,&checkkey,wifstr); + if ( bits256_cmp(privkey,checkkey) != 0 ) + { + printf("i.%d: %s vs %s\n",i,bits256_str(str,privkey),bits256_str(str2,checkkey)); + exit(-1); + } + if ( (i % 1000000) == 0 ) + fprintf(stderr,"%.1f%% ",100.*(double)i/200000000); + } + printf("%d privkeys checked\n",i); +} + + +// from https://github.com/owencm/C-Steganography-Framework +#include "../../crypto777/jpeg/cdjpeg.h" // Common decls for compressing and decompressing jpegs + +int32_t LP_jpg_process(int32_t *capacityp,char *inputfname,char *outputfname,uint8_t *decoded,uint8_t *data,int32_t required,int32_t power2,char *passphrase) +{ + struct jpeg_decompress_struct inputinfo; + struct jpeg_compress_struct outputinfo; + struct jpeg_error_mgr jerr; + jvirt_barray_ptr *coef_arrays; + JDIMENSION i,compnum,rownum,blocknum; + JBLOCKARRAY coef_buffers[MAX_COMPONENTS]; + JBLOCKARRAY row_ptrs[MAX_COMPONENTS]; + FILE *input_file,*output_file; int32_t val,modified,emit,totalrows,limit; + if ( power2 < 0 || power2 > 16 ) + power2 = 4; + limit = 1; + while ( power2 > 0 ) + { + limit <<= 1; + power2--; + } + if ((input_file = fopen(inputfname, READ_BINARY)) == NULL) { + fprintf(stderr, "Can't open %s\n", inputfname); + exit(EXIT_FAILURE); + } + // Initialize the JPEG compression and decompression objects with default error handling + inputinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&inputinfo); + // Specify data source for decompression and recompression + jpeg_stdio_src(&inputinfo, input_file); + (void) jpeg_read_header(&inputinfo, TRUE); + for (compnum=0; compnummem->alloc_barray)((j_common_ptr)&inputinfo,JPOOL_IMAGE,inputinfo.comp_info[compnum].width_in_blocks,inputinfo.comp_info[compnum].height_in_blocks); + coef_arrays = jpeg_read_coefficients(&inputinfo); + // Copy DCT coeffs to a new array + int num_components = inputinfo.num_components; + size_t block_row_size[num_components]; + int width_in_blocks[num_components]; + int height_in_blocks[num_components]; + *capacityp = modified = emit = totalrows = 0; + if ( decoded != 0 ) + memset(decoded,0,required/8+1); + for (compnum=0; compnummem->access_virt_barray)((j_common_ptr)&inputinfo,coef_arrays[compnum],rownum,(JDIMENSION)1,FALSE); + for (blocknum=0; blocknum power2 ) + { + if ( decoded != 0 && (val & 1) != 0 && *capacityp < required ) + decoded[*capacityp >> 3] |= (1 << (*capacityp & 7)); + (*capacityp)++; + } + coef_buffers[compnum][rownum][blocknum][i] = val; + } + } + } + } + printf("capacity %d required.%d\n",*capacityp,required); + if ( *capacityp > required && outputfname != 0 && outputfname[0] != 0 ) + { + if ((output_file = fopen(outputfname, WRITE_BINARY)) == NULL) { + fprintf(stderr, "Can't open %s\n", outputfname); + exit(EXIT_FAILURE); + } + outputinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&outputinfo); + jpeg_stdio_dest(&outputinfo, output_file); + jpeg_copy_critical_parameters(&inputinfo,&outputinfo); + // Print out or modify DCT coefficients + for (compnum=0; compnum power2 ) + { + val &= ~1; + if ( (data[emit >> 3] & (1 << (emit&7))) != 0 ) + val |= 1; + emit++; + } + coef_buffers[compnum][rownum][blocknum][i] = val; + //printf("%i,", coef_buffers[compnum][rownum][blocknum][i]); + } + } + } + } + //printf("\n\n"); + + /* Output the new DCT coeffs to a JPEG file */ + modified = 0; + for (compnum=0; compnummem->access_virt_barray)((j_common_ptr)&outputinfo,coef_arrays[compnum],rownum,(JDIMENSION)1,TRUE); + if ( memcmp(row_ptrs[compnum][0][0],coef_buffers[compnum][rownum][0],block_row_size[compnum]) != 0 ) + { + memcpy(row_ptrs[compnum][0][0],coef_buffers[compnum][rownum][0],block_row_size[compnum]); + modified++; + } + totalrows++; + } + } + // Write to the output file + jpeg_write_coefficients(&outputinfo, coef_arrays); + // Finish compression and release memory + jpeg_finish_compress(&outputinfo); + jpeg_destroy_compress(&outputinfo); + fclose(output_file); + } + jpeg_finish_decompress(&inputinfo); + jpeg_destroy_decompress(&inputinfo); + fclose(input_file); + if ( modified != 0 ) + { + printf("New DCT coefficients successfully written to %s, capacity %d modifiedrows.%d/%d emit.%d\n",outputfname,*capacityp,modified,totalrows,emit); + } + return(modified); +} + +char *LP_jpg(char *srcfile,char *destfile,int32_t power2,char *passphrase,char *datastr,int32_t required) +{ + cJSON *retjson; int32_t len=0,modified,capacity; char *decodedstr; uint8_t *data=0,*decoded=0; + if ( srcfile != 0 && srcfile[0] != 0 ) + { + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + if ( datastr != 0 && datastr[0] != 0 ) + { + if ( (len= is_hexstr(datastr,0)) > 0 ) + { + len >>= 1; + data = calloc(1,len); + decode_hex(data,len,datastr); + required = len * 8; + } + } + if ( required > 0 ) + decoded = calloc(1,len); + modified = LP_jpg_process(&capacity,srcfile,destfile,decoded,data,required,power2,passphrase); + jaddnum(retjson,"modifiedrows",modified); + if ( modified != 0 ) + jaddstr(retjson,"outputfile",destfile); + jaddnum(retjson,"power2",power2); + jaddnum(retjson,"capacity",capacity); + jaddnum(retjson,"required",required); + if ( decoded != 0 ) + { + decodedstr = calloc(1,len*2+1); + init_hexbytes_noT(decodedstr,decoded,len); + jaddstr(retjson,"decoded",decodedstr); + free(decodedstr); + free(decoded); + } + if ( data != 0 ) + free(data); + return(jprint(retjson,1)); + } else return(clonestr("{\"error\":\"no source file error\"}")); +} + + + + diff --git a/iguana/exchanges/LP_remember.c b/iguana/exchanges/LP_remember.c index f5ea3229a..22daf14ad 100644 --- a/iguana/exchanges/LP_remember.c +++ b/iguana/exchanges/LP_remember.c @@ -243,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 ) @@ -253,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; isentflags[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(); @@ -506,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)); @@ -637,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); @@ -670,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 +714,8 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap) if ( (fileobj= cJSON_Parse(fstr)) != 0 ) { rswap->finishtime = juint(fileobj,"finishtime"); - rswap->origfinishedflag = rswap->finishedflag = 1; + 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.(%u %u) %llu files BOB.(%s) Alice.(%s) src.(%s) dest.(%s)\n",rswap.requestid,rswap.quoteid,(long long)rswap.aliceid,rswap.bobcoin,rswap.alicecoin,rswap.src,rswap.dest); - return(cJSON_Parse("{\"error\":\"mismatched bob/alice vs src/dest coins??\"}")); + //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,20 +1191,24 @@ 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; 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); @@ -1149,11 +1218,41 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti //LP_broadcast_message(LP_mypubsock,rswap.src,rswap.dest,zero,itemstr); fclose(fp); } + } else item = LP_swap_json(&rswap); + for (i=0; itxfee,"satinder",coin->symbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,ctx,priv1,0,redeemscript,redeemlen,userdata,len,utxotxid,0,0,pubkey33,0,expiration,&satoshis,0,0,paymentaddr,1,coin->zcash)) != 0 ) + { + char str[65]; printf("satinder %s signedtx.(%s)\n",bits256_str(str,signedtxid),signedtx); + } else printf("error with satinder tx\n"); +} + +char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid,int32_t forceflag,int32_t pendingonly) { uint64_t ridqids[4096],ridqid; char fname[512]; FILE *fp; cJSON *item,*retjson,*array,*totalsobj; uint32_t r,q,quoteid,requestid; int64_t KMDtotals[LP_MAXPRICEINFOS],BTCtotals[LP_MAXPRICEINFOS],Btotal,Ktotal; int32_t i,j,count=0; portable_mutex_lock(&LP_swaplistmutex); @@ -1166,7 +1265,7 @@ char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid) if ( origrequestid != 0 && origquoteid != 0 ) { //printf("orig req.%u q.%u\n",origrequestid,origquoteid); - if ( (item= basilisk_remember(KMDtotals,BTCtotals,origrequestid,origquoteid)) != 0 ) + if ( (item= basilisk_remember(KMDtotals,BTCtotals,origrequestid,origquoteid,forceflag,0)) != 0 ) jaddi(array,item); //printf("got.(%s)\n",jprint(item,0)); } @@ -1180,19 +1279,22 @@ char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid) while ( fread(&requestid,1,sizeof(requestid),fp) == sizeof(requestid) && fread("eid,1,sizeof(quoteid),fp) == sizeof(quoteid) ) { flag = 0; - 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 ) @@ -1205,7 +1307,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); } } @@ -1234,23 +1336,16 @@ 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) { cJSON *item; int64_t KMDtotals[LP_MAXPRICEINFOS],BTCtotals[LP_MAXPRICEINFOS]; memset(KMDtotals,0,sizeof(KMDtotals)); memset(BTCtotals,0,sizeof(BTCtotals)); - if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid)) != 0 ) + if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid,forceflag,0)) != 0 ) return(jprint(item,1)); else return(clonestr("{\"error\":\"cant find requestid-quoteid\"}")); } @@ -1260,7 +1355,10 @@ extern uint32_t Alice_expiration; char *LP_recent_swaps(int32_t limit) { - char fname[512]; long fsize,offset; FILE *fp; int32_t i=0; uint32_t requestid,quoteid; cJSON *array,*item,*retjson; + char fname[512],*retstr,*base,*rel,*statusstr; long fsize,offset; FILE *fp; int32_t baseind,relind,i=0; uint32_t requestid,quoteid; cJSON *array,*item,*retjson,*subitem,*swapjson; int64_t KMDtotals[LP_MAXPRICEINFOS],BTCtotals[LP_MAXPRICEINFOS]; double srcamount,destamount,netamounts[LP_MAXPRICEINFOS]; + memset(KMDtotals,0,sizeof(KMDtotals)); + memset(BTCtotals,0,sizeof(BTCtotals)); + memset(netamounts,0,sizeof(netamounts)); if ( limit <= 0 ) limit = 3; sprintf(fname,"%s/SWAPS/list",GLOBAL_DBDIR), OS_compatible_path(fname); @@ -1282,6 +1380,36 @@ char *LP_recent_swaps(int32_t limit) item = cJSON_CreateArray(); jaddinum(item,requestid); jaddinum(item,quoteid); + if ( (retstr= basilisk_swapentry(requestid,quoteid,0)) != 0 ) + { + if ( (swapjson= cJSON_Parse(retstr)) != 0 ) + { + base = jstr(swapjson,"bob"); + rel = jstr(swapjson,"alice"); + statusstr = jstr(swapjson,"status"); + baseind = relind = -1; + if ( base != 0 && rel != 0 && statusstr != 0 && strcmp(statusstr,"finished") == 0 && (baseind= LP_priceinfoind(base)) >= 0 && (relind= LP_priceinfoind(rel)) >= 0 ) + { + srcamount = jdouble(swapjson,"srcamount"); + destamount = jdouble(swapjson,"destamount"); + if ( jint(swapjson,"iambob") != 0 ) + srcamount = -srcamount; + else destamount = -destamount; + if ( srcamount != 0. && destamount != 0. ) + { + netamounts[baseind] += srcamount; + netamounts[relind] += destamount; + subitem = cJSON_CreateObject(); + jaddnum(subitem,base,srcamount); + jaddnum(subitem,rel,destamount); + jaddnum(subitem,"price",-destamount/srcamount); + jaddi(item,subitem); + } + } else printf("base.%p rel.%p statusstr.%p baseind.%d relind.%d\n",base,rel,statusstr,baseind,relind); + free_json(swapjson); + } else printf("error parsing.(%s)\n",retstr); + free(retstr); + } jaddi(array,item); } else break; } else break; @@ -1291,6 +1419,17 @@ 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) ) - { - printf("issue.(%s)\n",url); - 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 ) @@ -77,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 ) { @@ -99,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\"}"); @@ -118,236 +86,14 @@ 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" }, -}; - -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 - { - strcpy(lowerstr,assetname); - tolowercase(lowerstr); - sprintf(line,"fiat/%s sendtoaddress %s %.8f # txnum.%llu",lowerstr,validaddress,dstr(satoshis),(long long)txnum); - } - printf("%s\n",line); -} - -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 ) - { - char validaddress[64]; int32_t z,n; - n = (int32_t)strlen(msgstr); - for (z=0; z= 34 ) - strncpy(validaddress,&msgstr[z],34); - if ( strlen(validaddress) == 34 || strlen(validaddress) == 33 ) - { - //printf("%-4d: (%34s) <- %13.5f %10s tx.%llu past_marker.%d\n",i,validaddress,dstr(qty * mult),assetname,(long long)txnum,past_marker); - if ( past_marker == 0 ) - { - LP_sendtoaddress_line(validaddress,assetname,(qty * mult),txnum); - } - } else printf("%-4d: (%34s) <- %13.5f %10s tx.%llu\n",i,msgstr!=0?msgstr:jprint(item,0),dstr(qty * mult),assetname,(long long)txnum); - } - if ( msgjson != 0 ) - free_json(msgjson); - if ( decjson != 0 ) - free_json(decjson); - } - if ( txnum == txnum_marker2 ) - break; - } - } - //free_json(retjson); - } - free(retstr); - } - printf("\nTotal redeemed\n"); - for (i=0; iheight; - if ( coin->electrum == 0 && time(NULL) > coin->heighttime+60 ) + if ( coin->electrum == 0 && time(NULL) > coin->heighttime+60 && coin->userpass[0] != 0 ) { if ( strcmp(coin->symbol,"BTC") == 0 ) method = "getblockchaininfo"; @@ -356,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); @@ -388,7 +141,7 @@ uint64_t LP_RTsmartbalance(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 ) @@ -398,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) @@ -410,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\"}")); @@ -429,9 +182,10 @@ cJSON *LP_gettx(char *symbol,bits256 txid) } else { - if ( (retjson= electrum_transaction(symbol,coin->electrum,&retjson,txid,0)) != 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\"}")); } } @@ -439,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); @@ -447,23 +201,6 @@ uint32_t LP_locktime(char *symbol,bits256 txid) return(locktime); } -/*uint32_t LP_txtime(char *symbol,bits256 txid) -{ - struct LP_transaction *tx; struct iguana_info *coin; int32_t timestamp=0,height = 0; - char str[65]; printf("LP_txtime (%s %s)\n",symbol,bits256_str(str,txid)); - if ( (timestamp= LP_locktime(symbol,txid)) != 0 ) - return(timestamp); - if ( (coin= LP_coinfind(symbol)) != 0 ) - { - if ( (tx= LP_transactionfind(coin,txid)) != 0 ) - { - height = tx->height; - timestamp = LP_heighttime(symbol,height); - } - } - return(height); -}*/ - cJSON *LP_gettxout_json(bits256 txid,int32_t vout,int32_t height,char *coinaddr,uint64_t value) { cJSON *retjson,*addresses,*sobj; @@ -485,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 ) @@ -507,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)) != 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)); @@ -522,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 ) @@ -549,17 +287,6 @@ cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout) } } -/*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; @@ -574,7 +301,12 @@ cJSON *LP_validateaddress(char *symbol,char *address) jaddstr(retjson,"address",address); bitcoin_addr2rmd160(coin->taddr,&addrtype,rmd160,address); bitcoin_address(checkaddr,coin->taddr,addrtype,rmd160,20); - jadd(retjson,"isvalid",strcmp(address,checkaddr)==0? cJSON_CreateTrue() : cJSON_CreateFalse()); + if ( addrtype != coin->pubtype && addrtype != coin->p2shtype ) + { + jadd(retjson,"isvalid",cJSON_CreateFalse()); + return(retjson); + } + jadd(retjson,"isvalid",strcmp(address,checkaddr)==0 ? cJSON_CreateTrue() : cJSON_CreateFalse()); if ( addrtype == coin->pubtype ) { strcpy(script,"76a914"); @@ -585,8 +317,8 @@ cJSON *LP_validateaddress(char *symbol,char *address) jaddstr(retjson,"scriptPubKey",script); } bitcoin_address(coinaddr,coin->taddr,coin->pubtype,G.LP_myrmd160,20); - jadd(retjson,"ismine",strcmp(address,coin->smartaddr) == 0 ? cJSON_CreateTrue() : cJSON_CreateFalse()); - jadd(retjson,"iswatchonly",cJSON_CreateFalse()); + jadd(retjson,"ismine",strcmp(coinaddr,coin->smartaddr) == 0 ? cJSON_CreateTrue() : cJSON_CreateFalse()); + jadd(retjson,"iswatchonly",cJSON_CreateTrue()); jadd(retjson,"isscript",addrtype == coin->p2shtype ? cJSON_CreateTrue() : cJSON_CreateFalse()); return(retjson); } @@ -599,12 +331,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)); @@ -615,6 +347,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; @@ -633,38 +383,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)); +} + +cJSON *LP_listreceivedbyaddress(char *symbol,char *coinaddr) +{ + 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)); } -int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag) +int64_t LP_listunspent_parseitem(struct iguana_info *coin,bits256 *txidp,int32_t *voutp,int32_t *heightp,cJSON *item) { - struct iguana_info *coin; int32_t n = 0; cJSON *retjson=0; char *retstr=0; + 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)); @@ -672,21 +494,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); - coin->numutxos = cJSON_GetArraySize(retjson); - //printf("SELF_LISTUNSPENT.(%s %s)\n",symbol,coinaddr); - } - else if ( IAMLP == 0 ) - { - //printf("LP_listunspent_query.(%s %s)\n",symbol,coinaddr); - LP_listunspent_query(coin->symbol,coin->smartaddr); - } + if ( 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 } @@ -701,39 +516,6 @@ int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag) return(n); } -cJSON *LP_importprivkey(char *symbol,char *wifstr,char *label,int32_t flag) -{ - static void *ctx; - char buf[512],address[64]; cJSON *retjson; struct iguana_info *coin; int32_t doneflag = 0; - if ( symbol == 0 || symbol[0] == 0 ) - return(cJSON_Parse("{\"error\":\"null symbol\"}")); - coin = LP_coinfind(symbol); - if ( coin == 0 ) - return(cJSON_Parse("{\"error\":\"no coin\"}")); - if ( coin->electrum != 0 ) - return(cJSON_Parse("{\"result\":\"electrum should have local wallet\"}")); - if ( ctx == 0 ) - ctx = bitcoin_ctx(); - bitcoin_wif2addr(ctx,coin->wiftaddr,coin->taddr,coin->pubtype,address,wifstr); - if ( (retjson= LP_validateaddress(symbol,address)) != 0 ) - { - if ( jobj(retjson,"ismine") != 0 && is_cJSON_True(jobj(retjson,"ismine")) != 0 ) - { - doneflag = 1; - //printf("%s already ismine\n",address); - } - //printf("%s\n",jprint(retjson,0)); - free_json(retjson); - } - if ( doneflag == 0 ) - { - if ( coin->noimportprivkey_flag != 0 ) - sprintf(buf,"[\"%s\"]",wifstr); - else sprintf(buf,"\"%s\", \"%s\", %s",wifstr,label,flag < 0 ? "false" : "true"); - return(bitcoin_json(coin,"importprivkey",buf)); - } else return(cJSON_Parse("{\"result\":\"success\"}")); -} - int32_t LP_importaddress(char *symbol,char *address) { char buf[1024],*retstr; cJSON *validatejson; int32_t isvalid=0,doneflag = 0; struct iguana_info *coin; @@ -745,10 +527,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 @@ -776,6 +558,45 @@ int32_t LP_importaddress(char *symbol,char *address) } } +cJSON *LP_importprivkey(char *symbol,char *wifstr,char *label,int32_t flag) +{ + static void *ctx; + char buf[512],address[64]; cJSON *retjson; struct iguana_info *coin; int32_t doneflag = 0; + if ( symbol == 0 || symbol[0] == 0 ) + return(cJSON_Parse("{\"error\":\"null symbol\"}")); + coin = LP_coinfind(symbol); + if ( coin == 0 ) + return(cJSON_Parse("{\"error\":\"no coin\"}")); + if ( coin->electrum != 0 ) + return(cJSON_Parse("{\"result\":\"electrum should have local wallet\"}")); + if ( ctx == 0 ) + ctx = bitcoin_ctx(); + bitcoin_wif2addr(ctx,coin->wiftaddr,coin->taddr,coin->pubtype,address,wifstr); +#ifdef LP_DONT_IMPORTPRIVKEY + bitcoin_wif2addr(ctx,coin->wiftaddr,coin->taddr,coin->pubtype,address,wifstr); + if ( LP_importaddress(symbol,address) < 0 ) + return(cJSON_Parse("{\"error\":\"couldnt import\"}")); + else return(cJSON_Parse("{\"result\":\"success\"}")); +#endif + if ( (retjson= LP_validateaddress(symbol,address)) != 0 ) + { + if ( jobj(retjson,"ismine") != 0 && is_cJSON_True(jobj(retjson,"ismine")) != 0 ) + { + doneflag = 1; + //printf("%s already ismine\n",address); + } + //printf("%s\n",jprint(retjson,0)); + free_json(retjson); + } + if ( doneflag == 0 ) + { + if ( coin->noimportprivkey_flag != 0 ) + sprintf(buf,"[\"%s\"]",wifstr); + else sprintf(buf,"\"%s\", \"%s\", %s",wifstr,label,flag < 0 ? "false" : "true"); + return(bitcoin_json(coin,"importprivkey",buf)); + } else return(cJSON_Parse("{\"result\":\"success\"}")); +} + double _LP_getestimatedrate(struct iguana_info *coin) { char buf[512],*retstr=0; int32_t numblocks; cJSON *errjson,*retjson; double rate = 0.00000020; @@ -805,9 +626,9 @@ 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; @@ -998,17 +819,19 @@ bits256 LP_getbestblockhash(struct iguana_info *coin) char *LP_blockhashstr(char *symbol,int32_t height) { - cJSON *array; char *paramstr,*retstr; struct iguana_info *coin; + char params[64],*retstr; struct iguana_info *coin; //cJSON *array; if ( symbol == 0 || symbol[0] == 0 ) return(0); coin = LP_coinfind(symbol); if ( coin == 0 || coin->electrum != 0 ) return(0); - array = cJSON_CreateArray(); - jaddinum(array,height); - paramstr = jprint(array,1); - retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"getblockhash",paramstr); - free(paramstr); + //array = cJSON_CreateArray(); + //jaddinum(array,height); + //paramstr = jprint(array,1); + sprintf(params,"[%d]",height); + retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"getblockhash",params); + //free(paramstr); + //printf("blockhashstr.(%s)\n",retstr); return(retstr); } @@ -1158,10 +981,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 ) { @@ -1173,14 +997,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); @@ -1214,20 +1038,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; @@ -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,7 +466,8 @@ 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)); if ( (n= cJSON_GetArraySize(array)) > 0 ) @@ -482,12 +485,12 @@ int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int } free(array); } - LP_listunspent_issue(coin->symbol,coinaddr,1); + LP_listunspent_issue(coin->symbol,coinaddr,1,txid,zero); struct LP_address_utxo *up; if ( (up= LP_address_utxofind(coin,coinaddr,txid,vout)) != 0 ) { char str[65]; printf("address_utxofind found confirmed %s %s %s ht.%d vs %d\n",symbol,coinaddr,bits256_str(str,txid),up->U.height,coin->height); - if ( coin->electrum != 0 && (array= electrum_address_gethistory(symbol,coin->electrum,&array,coinaddr)) != 0 ) + if ( coin->electrum != 0 && (array= electrum_address_gethistory(symbol,coin->electrum,&array,coinaddr,txid)) != 0 ) free_json(array); if ( coin->height >= up->U.height ) numconfirms = (coin->height - up->U.height + 1); @@ -512,7 +515,7 @@ int32_t LP_mempool_vinscan(bits256 *spendtxidp,int32_t *spendvinp,char *symbol,c return(-1); if ( time(NULL) > coin->lastmempool+LP_MEMPOOL_TIMEINCR ) { - if ( (array= LP_getmempool(symbol,coinaddr)) != 0 ) + if ( (array= LP_getmempool(symbol,coinaddr,searchtxid,searchtxid2)) != 0 ) { free_json(array); coin->lastmempool = (uint32_t)time(NULL); diff --git a/iguana/exchanges/LP_secp.c b/iguana/exchanges/LP_secp.c index 9c7032e23..516e2be75 100644 --- a/iguana/exchanges/LP_secp.c +++ b/iguana/exchanges/LP_secp.c @@ -86,21 +86,28 @@ bits256 bitcoin_pub256(void *ctx,bits256 *privkeyp,uint8_t odd_even) int32_t bitcoin_sign(void *ctx,char *symbol,uint8_t *sig,bits256 txhash2,bits256 privkey,int32_t recoverflag) { int32_t fCompressed = 1; - secp256k1_ecdsa_signature SIG; secp256k1_ecdsa_recoverable_signature rSIG; bits256 extra_entropy,seed; int32_t recid,retval = -1; size_t siglen = 72; secp256k1_pubkey SECPUB,CHECKPUB; + secp256k1_ecdsa_signature SIG; void *funcp; secp256k1_ecdsa_recoverable_signature rSIG; bits256 extra_entropy,seed; uint8_t *entropy; int32_t recid,retval = -1; size_t siglen = 72; secp256k1_pubkey SECPUB,CHECKPUB; seed = rand256(0); extra_entropy = rand256(0); SECP_ENSURE_CTX { + funcp = secp256k1_nonce_function_rfc6979; if ( secp256k1_ec_seckey_verify(ctx,privkey.bytes) == 0 ) { //printf("bitcoin_sign illegal privkey\n"); return(-1); } + if ( strcmp(symbol,"BCH") == 0 || strcmp(symbol,"BTG") == 0 ) + { + char str[65]; printf("BCH/BTG deterministic signature %s\n",bits256_str(str,txhash2)); + funcp = 0; + entropy = 0; + } else entropy = extra_entropy.bytes; if ( secp256k1_context_randomize(ctx,seed.bytes) != 0 ) { if ( recoverflag != 0 ) { - if ( secp256k1_ecdsa_sign_recoverable(ctx,&rSIG,txhash2.bytes,privkey.bytes,secp256k1_nonce_function_rfc6979,extra_entropy.bytes) != 0 ) + if ( secp256k1_ecdsa_sign_recoverable(ctx,&rSIG,txhash2.bytes,privkey.bytes,funcp,entropy) != 0 ) { recid = -1; secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx,sig+1,&recid,&rSIG); @@ -125,7 +132,7 @@ int32_t bitcoin_sign(void *ctx,char *symbol,uint8_t *sig,bits256 txhash2,bits256 } else { - if ( secp256k1_ecdsa_sign(ctx,&SIG,txhash2.bytes,privkey.bytes,secp256k1_nonce_function_rfc6979,extra_entropy.bytes) != 0 ) + if ( secp256k1_ecdsa_sign(ctx,&SIG,txhash2.bytes,privkey.bytes,funcp,entropy) != 0 ) { if ( secp256k1_ecdsa_signature_serialize_der(ctx,sig,&siglen,&SIG) != 0 ) retval = (int32_t)siglen; diff --git a/iguana/exchanges/LP_signatures.c b/iguana/exchanges/LP_signatures.c index 6e99495cb..becbccef7 100644 --- a/iguana/exchanges/LP_signatures.c +++ b/iguana/exchanges/LP_signatures.c @@ -194,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\"}")); } @@ -276,7 +276,7 @@ bits256 LP_utxos_sighash(uint32_t timestamp,uint8_t *pubsecp,bits256 pubkey,bits int32_t LP_utxos_sigcheck(uint32_t timestamp,char *sigstr,char *pubsecpstr,bits256 pubkey,bits256 utxoshash) { - static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash; char str[65]; struct LP_pubkeyinfo *pubp; + static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash; char str[65]; struct LP_pubkey_info *pubp; if ( ctx == 0 ) ctx = bitcoin_ctx(); pubp = LP_pubkeyfind(pubkey); @@ -357,66 +357,9 @@ return; } } -queue_t utxosQ; -struct LP_utxos_qitem { struct queueitem DL; cJSON *argjson; }; - -char *LP_postutxos_recv(cJSON *argjson) -{ - struct LP_utxos_qitem *uitem; struct iguana_info *coin; char *coinaddr,*symbol; bits256 utxoshash,pubkey; cJSON *obj; struct LP_pubkeyinfo *pubp; -printf("LP_postutxos_recv deprecated\n"); - pubkey = jbits256(argjson,"pubkey"); - pubp = LP_pubkeyfind(pubkey); - if ( pubp != 0 && pubp->numerrors > LP_MAXPUBKEY_ERRORS ) - return(clonestr("{\"error\":\"blacklisted\"}")); - if ( (coinaddr= jstr(argjson,"coinaddr")) != 0 && (symbol= jstr(argjson,"coin")) != 0 && (coin= LP_coinfind(symbol)) != 0 ) - { - if ( strcmp(coinaddr,coin->smartaddr) == 0 ) - { - //printf("ignore my utxo from external source %s %s\n",symbol,coinaddr); - return(clonestr("{\"result\":\"success\"}")); - } - } - if ( (obj= jobj(argjson,"utxos")) != 0 ) - { - utxoshash = LP_utxoshash_calc(obj); - //char str[65]; //printf("got utxoshash %s\n",bits256_str(str,utxoshash)); - if ( LP_utxos_sigcheck(juint(argjson,"timestamp"),jstr(argjson,"sig"),jstr(argjson,"pubsecp"),pubkey,utxoshash) == 0 ) - { - uitem = calloc(1,sizeof(*uitem)); - uitem->argjson = jduplicate(argjson); - queue_enqueue("utxosQ",&utxosQ,&uitem->DL); - return(clonestr("{\"result\":\"success\"}")); - } //else printf("valid utxos sig %s\n",bits256_str(str,pubp->pubkey)); - } - return(clonestr("{\"error\":\"sig failure\"}")); -} - -int32_t LP_utxosQ_process() -{ - struct LP_utxos_qitem *uitem; int32_t n; char *symbol,*coinaddr; struct LP_address *ap; struct iguana_info *coin; cJSON *array; - if ( (uitem= queue_dequeue(&utxosQ)) != 0 ) - { - //printf("LP_utxosQ_process.(%s)\n",jprint(uitem->argjson,0)); - if ( (coinaddr= jstr(uitem->argjson,"coinaddr")) != 0 && (symbol= jstr(uitem->argjson,"coin")) != 0 && (coin= LP_coinfind(symbol)) != 0 ) // addsig - { - if ( coin->electrum == 0 || (ap= LP_addressfind(coin,coinaddr)) != 0 ) - { - if ( (array= jarray(&n,uitem->argjson,"utxos")) != 0 ) - LP_unspents_array(coin,coinaddr,array); - } - else if ( (array= electrum_address_listunspent(symbol,coin->electrum,&array,coinaddr,1)) != 0 ) - free_json(array); - } - free_json(uitem->argjson); - free(uitem); - return(1); - } - return(0); -} - int32_t LP_price_sigcheck(uint32_t timestamp,char *sigstr,char *pubsecpstr,bits256 pubkey,char *base,char *rel,uint64_t price64) { - static void *ctx; int32_t retval=-1; uint8_t pub33[33],pubsecp[33],sig[65]; bits256 sighash; struct LP_pubkeyinfo *pubp; + 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); @@ -451,10 +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; struct LP_address *ap; char pubsecpstr[67]; uint32_t numutxos,timestamp; uint64_t price64,balance,minsize,maxsize; bits256 zero; cJSON *reqjson; + 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); @@ -468,17 +411,16 @@ 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 ( (ap= LP_address(basecoin,basecoin->smartaddr)) != 0 ) + 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 ) { - if ( (numutxos= LP_address_minmax(&balance,&minsize,&maxsize,ap)) != 0 ) - { - //printf("%s numutxos.%d balance %.8f min %.8f max %.8f\n",base,numutxos,dstr(balance),dstr(minsize),dstr(maxsize)); - jaddstr(reqjson,"utxocoin",base); - jaddnum(reqjson,"n",numutxos); - jaddnum(reqjson,"bal",dstr(balance)); - jaddnum(reqjson,"min",dstr(minsize)); - jaddnum(reqjson,"max",dstr(maxsize)); - } + //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(0,base,rel,zero,jprint(reqjson,1)); @@ -497,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,jstr(argjson,"utxocoin"),jint(argjson,"n"),jdouble(argjson,"bal")*SATOSHIDEN,jdouble(argjson,"min")*SATOSHIDEN,jdouble(argjson,"max")*SATOSHIDEN); + //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\"}")); @@ -521,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) ) @@ -603,7 +551,7 @@ void LP_notify_pubkeys(void *ctx,int32_t pubsock) char *LP_notify_recv(cJSON *argjson) { - bits256 pub; struct LP_pubkeyinfo *pubp; char *ipaddr; + bits256 pub; struct LP_pubkey_info *pubp; char *ipaddr; pub = jbits256(argjson,"pub"); if ( bits256_nonz(pub) != 0 ) { @@ -695,13 +643,13 @@ void LP_listunspent_query(char *symbol,char *coinaddr) 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; + cJSON *reqjson; bits256 zero; char *msg; struct iguana_info *coin; int32_t flag = 0; if ( strcmp(method,"request") == 0 ) { if ( LP_allocated(qp->desttxid,qp->destvout) == 0 && LP_allocated(qp->feetxid,qp->feevout) == 0 ) { - LP_unavailableset(qp->desttxid,qp->destvout,qp->timestamp+LP_AUTOTRADE_TIMEOUT,qp->srchash); - LP_unavailableset(qp->feetxid,qp->feevout,qp->timestamp+LP_AUTOTRADE_TIMEOUT,qp->srchash); + 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 { @@ -714,17 +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); printf("QUERY.(%s)\n",msg); - memset(&zero,0,sizeof(zero)); - portable_mutex_lock(&LP_reservedmutex); - if ( num_Reserved_msgs[1] < sizeof(Reserved_msgs[1])/sizeof(*Reserved_msgs[1])-2 ) - Reserved_msgs[1][num_Reserved_msgs[1]++] = msg; - if ( num_Reserved_msgs[0] < sizeof(Reserved_msgs[0])/sizeof(*Reserved_msgs[0])-2 ) - Reserved_msgs[0][num_Reserved_msgs[0]++] = msg2; - //LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,zero,msg2); - portable_mutex_unlock(&LP_reservedmutex); + //if ( bits256_nonz(qp->srchash) == 0 || strcmp(method,"request") != 0 ) + { + 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 f1a895b38..4544ed0dc 100644 --- a/iguana/exchanges/LP_socket.c +++ b/iguana/exchanges/LP_socket.c @@ -283,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 ) @@ -317,10 +317,13 @@ 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 ) { @@ -401,6 +404,8 @@ int32_t electrum_kickstart(struct electrum_info *ep) 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 @@ -440,7 +445,7 @@ 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); @@ -518,7 +523,7 @@ cJSON *electrum_address_subscribe(char *symbol,struct electrum_info *ep,cJSON ** 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); @@ -530,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); @@ -553,27 +558,27 @@ 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; char *retstr; struct LP_address *ap; struct iguana_info *coin; int32_t updatedflag,height,usecache=1; if ( (coin= LP_coinfind(symbol)) == 0 ) @@ -589,7 +594,7 @@ 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+30 ) + else if ( G.LP_pendingswaps != 0 && time(NULL) > ap->unspenttime+13 ) usecache = 0; } if ( usecache == 0 || electrumflag > 1 ) @@ -601,17 +606,14 @@ cJSON *electrum_address_listunspent(char *symbol,struct electrum_info *ep,cJSON if ( 0 && electrumflag > 1 ) printf("%s.%d u.%u/%d t.%ld %s LISTUNSPENT.(%d)\n",coin->symbol,height,ap->unspenttime,ap->unspentheight,time(NULL),addr,(int32_t)strlen(jprint(retjson,0))); updatedflag = 0; - if ( electrum_process_array(coin,ep,addr,retjson,electrumflag) != 0 ) + if ( electrum_process_array(coin,ep,addr,retjson,electrumflag,txid,txid2) != 0 ) { //LP_postutxos(coin->symbol,addr); updatedflag = 1; } - if ( strcmp(addr,coin->smartaddr) == 0 ) - { - retstr = jprint(retjson,0); - LP_unspents_cache(coin->symbol,coin->smartaddr,retstr,1); - free(retstr); - } + retstr = jprint(retjson,0); + LP_unspents_cache(coin->symbol,addr,retstr,1); + free(retstr); if ( ap != 0 ) { ap->unspenttime = (uint32_t)time(NULL); @@ -627,7 +629,7 @@ cJSON *electrum_address_listunspent(char *symbol,struct electrum_info *ep,cJSON } if ( retjson == 0 ) { - if ( strcmp(addr,coin->smartaddr) == 0 && (retstr= LP_unspents_filestr(symbol,coin->smartaddr)) != 0 ) + if ( (retstr= LP_unspents_filestr(symbol,addr)) != 0 ) { retjson = cJSON_Parse(retstr); free(retstr); @@ -734,7 +736,7 @@ cJSON *_electrum_transaction(char *symbol,struct electrum_info *ep,cJSON **retjs 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); } @@ -742,27 +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,char *SPVcheck) +cJSON *electrum_transaction(int32_t *heightp,char *symbol,struct electrum_info *ep,cJSON **retjsonp,bits256 txid,char *SPVcheck) { - cJSON *retjson,*array; struct LP_transaction *tx; struct iguana_info *coin; + 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 ( ep != 0 && coin != 0 && SPVcheck != 0 && SPVcheck[0] != 0 && (tx= LP_transactionfind(coin,txid)) != 0 ) + if ( (tx= LP_transactionfind(coin,txid)) != 0 && ep != 0 && coin != 0 && SPVcheck != 0 && SPVcheck[0] != 0 ) { if ( tx->height <= 0 ) { - if ( (array= electrum_address_listunspent(symbol,ep,&array,SPVcheck,2)) != 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 ) - tx->SPV = LP_merkleproof(coin,SPVcheck,ep,txid,tx->height); + { + 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); @@ -779,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)); @@ -804,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)) != 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)); @@ -898,7 +908,7 @@ int32_t LP_recvfunc(struct electrum_info *ep,char *str,int32_t len) ep->lasttime = (uint32_t)time(NULL); if ( (strjson= cJSON_Parse(str)) != 0 ) { - //printf("%s RECV.(%ld) id.%d\n",ep->symbol,strlen(str),jint(strjson,"id")); + //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 ) @@ -972,7 +982,7 @@ 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; 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; electrum_initial_requests(ep); @@ -1004,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); @@ -1041,13 +1078,33 @@ void LP_dedicatedloop(void *arg) cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port) { - struct electrum_info *ep; int32_t kickval,already; cJSON *retjson; + 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(cJSON_Parse("{\"result\":\"success\",\"status\":\"electrum mode disabled, now in native coin mode\"}")); + return(retjson); } retjson = cJSON_CreateObject(); jaddstr(retjson,"ipaddr",ipaddr); @@ -1075,6 +1132,13 @@ cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port) LP_cacheptrs_init(coin); coin->loadedcache = (uint32_t)time(NULL); } + if ( 0 && strcmp(coin->symbol,"ZEC") == 0 ) + { + void for_satinder(); + sleep(3); + for_satinder(); + getchar(); + } } } else diff --git a/iguana/exchanges/LP_statemachine.c b/iguana/exchanges/LP_statemachine.c index 54d9ddc95..e62279232 100644 --- a/iguana/exchanges/LP_statemachine.c +++ b/iguana/exchanges/LP_statemachine.c @@ -17,7 +17,801 @@ // LP_statemachine.c // marketmaker // +char DEX_baseaddr[64],DEX_reladdr[64]; +struct mmpending_order +{ + double price,volume; + int32_t dir; + uint32_t pending,completed,canceled,cancelstarted,reported; + cJSON *errorjson; + char exchange[16],base[65],rel[65],orderid[64]; +} *Pending_orders; +int32_t Num_Pending; + +#define IGUANA_URL "http://127.0.0.1:7778" + +/*char CURRENCIES[][8] = { "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", // major currencies + "CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", // end of currencies + };*/ +double PAXPRICES[sizeof(CURRENCIES)/sizeof(*CURRENCIES)]; +uint32_t PAXACTIVE; + + +char *DEX_swapstatus() +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"getswaplist\"}"); + return(bitcoind_RPC(0,"InstantDEX",url,0,"getswaplist",postdata,0)); +} + +char *DEX_amlp(char *blocktrail) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"amlp\",\"blocktrail\":\"%s\"}",blocktrail); + return(bitcoind_RPC(0,"tradebot",url,0,"amlp",postdata,0)); +} + +char *DEX_openorders(char *exchange) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"openorders\",\"exchange\":\"%s\"}",exchange); + return(bitcoind_RPC(0,"InstantDEX",url,0,"openorders",postdata,0)); +} + +char *DEX_tradehistory(char *exchange) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"tradehistory\",\"exchange\":\"%s\"}",exchange); + return(bitcoind_RPC(0,"InstantDEX",url,0,"tradehistory",postdata,0)); +} + +char *DEX_orderstatus(char *exchange,char *orderid) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"orderstatus\",\"exchange\":\"%s\",\"orderid\":\"%s\"}",exchange,orderid); + return(bitcoind_RPC(0,"InstantDEX",url,0,"orderstatus",postdata,0)); +} + +char *DEX_cancelorder(char *exchange,char *orderid) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"cancelorder\",\"exchange\":\"%s\",\"orderid\":\"%s\"}",exchange,orderid); + return(bitcoind_RPC(0,"InstantDEX",url,0,"cancelorder",postdata,0)); +} + +char *DEX_balance(char *exchange,char *base,char *coinaddr) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + if ( strcmp(exchange,"DEX") == 0 ) + { + sprintf(postdata,"{\"agent\":\"dex\",\"method\":\"getbalance\",\"address\":\"%s\",\"symbol\":\"%s\"}",coinaddr,base); + return(bitcoind_RPC(0,"dex",url,0,"getbalance",postdata,0)); + } + else + { + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"balance\",\"exchange\":\"%s\",\"base\":\"%s\"}",exchange,base); + return(bitcoind_RPC(0,"InstantDEX",url,0,"balance",postdata,0)); + } +} + +char *DEX_apikeypair(char *exchange,char *apikey,char *apisecret) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"apikeypair\",\"exchange\":\"%s\",\"apikey\":\"%s\",\"apisecret\":\"%s\"}",exchange,apikey,apisecret); + return(bitcoind_RPC(0,"InstantDEX",url,0,"apikeypair",postdata,0)); +} + +char *DEX_setuserid(char *exchange,char *userid,char *tradepassword) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"setuserid\",\"exchange\":\"%s\",\"userid\":\"%s\",\"tradepassword\":\"%s\"}",exchange,userid,tradepassword); + return(bitcoind_RPC(0,"InstantDEX",url,0,"setuserid",postdata,0)); +} + +char *DEX_trade(char *exchange,char *base,char *rel,int32_t dir,double price,double volume) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"%s\",\"exchange\":\"%s\",\"base\":\"%s\",\"rel\":\"%s\",\"price\":%.8f,\"volume\":%.8f,\"dotrade\":1}",dir>0?"buy":"sell",exchange,base,rel,price,volume); + //printf("DEX_trade.(%s)\n",postdata); + return(bitcoind_RPC(0,"InstantDEX",url,0,dir>0?"buy":"sell",postdata,0)); +} + +char *DEX_withdraw(char *exchange,char *base,char *destaddr,double amount) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"withdraw\",\"exchange\":\"%s\",\"destaddr\":\"%s\",\"amount\":%.8f}",exchange,destaddr,amount); + return(bitcoind_RPC(0,"InstantDEX",url,0,"withdraw",postdata,0)); +} + +char *iguana_walletpassphrase(char *passphrase,int32_t timeout) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/coin=KMD&agent=bitcoinrpc&method=walletpassphrase?",IGUANA_URL); + sprintf(postdata,"[\"%s\", %d]",passphrase,timeout); + return(bitcoind_RPC(0,"",url,0,"walletpassphrase",postdata,0)); +} + +/*char *iguana_listunspent(char *coin,char *coinaddr) + { + char url[512],postdata[1024]; + sprintf(url,"%s/coin=%s&agent=bitcoinrpc&method=listunspent?",IGUANA_URL,coin); + sprintf(postdata,"[\"%s\"]",coinaddr); + return(bitcoind_RPC(0,"",url,0,"listunspent",postdata)); + }*/ + +/*char *issue_LP_intro(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers) + { + char url[512]; + sprintf(url,"http://%s:%u/api/stats/intro?ipaddr=%s&port=%u&numpeers=%d",destip,destport,ipaddr,port,numpeers); + printf("(%s)\n",url); + return(issue_curl(url)); + }*/ + +// +// http://127.0.0.1:7779/api/stats/getpeers + +char *DEX_listunspent(char *coin,char *coinaddr) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"dex\",\"method\":\"listunspent\",\"address\":\"%s\",\"symbol\":\"%s\",\"timeout\":60000}",coinaddr,coin); + return(bitcoind_RPC(0,"dex",url,0,"listunspent",postdata,0)); +} + +bits256 iguana_wif2privkey(char *wifstr) +{ + char url[512],postdata[1024],*retstr,*privstr; bits256 privkey; cJSON *retjson; + memset(privkey.bytes,0,sizeof(privkey)); + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"SuperNET\",\"method\":\"wif2priv\",\"wif\":\"%s\"}",wifstr); + if ( (retstr= bitcoind_RPC(0,"SuperNET",url,0,"wif2priv",postdata,0)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( (privstr= jstr(retjson,"privkey")) != 0 ) + { + if ( strlen(privstr) == 64 ) + decode_hex(privkey.bytes,32,privstr); + } + free_json(retjson); + } + free(retstr); + } + return(privkey); +} + +double bittrex_balance(char *base,char *coinaddr) +{ + char *retstr; cJSON *retjson; double balance = 0.; + if ( (retstr= DEX_balance("bittrex",base,coinaddr)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + balance = jdouble(retjson,"balance"); + free_json(retjson); + } + free(retstr); + } + return(balance); +} + +double dex_balance(char *base,char *coinaddr) +{ + char *retstr; cJSON *retjson; double balance = 0.; + if ( (retstr= DEX_balance("DEX",base,coinaddr)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + balance = jdouble(retjson,"balance"); + free_json(retjson); + } + free(retstr); + } + return(balance); +} + +int32_t komodo_baseid(char *base) +{ + int32_t i; + for (i=0; i 0 ) + { + for (i=0; i SMALLVAL && (name= jstr(item,"name")) != 0 && strncmp(name,"USD/",4) == 0 ) + { + if ( (baseid= komodo_baseid(name+4)) >= 0 && baseid < 32 ) + { + if ( ((1LL << baseid) & mask) == 0 ) + { + _marketmaker_fiatupdate(baseid,price); + mask |= (1LL << baseid); + } else if ( fabs(price*PAXPRICES[0] - PAXPRICES[baseid]) > SMALLVAL ) + printf("DUPLICATE PRICE? %s %.8f vs %.8f\n",name+4,price*PAXPRICES[0],PAXPRICES[baseid]); + } + } + } + } + } + printf("pax mask.%x\n",(uint32_t)mask); + return((uint32_t)mask); +} + +void marketmaker_cancel(struct mmpending_order *ptr) +{ + char *retstr; cJSON *retjson; + if ( ptr->pending != 0 && ptr->cancelstarted == 0 ) + { + ptr->cancelstarted = (uint32_t)time(NULL); + if ( (retstr= DEX_cancelorder(ptr->exchange,ptr->orderid)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + printf("cancel %s (%s/%s) %.8f vol %.8f dir.%d -> (%s)\n",ptr->exchange,ptr->base,ptr->rel,ptr->price,ptr->volume,ptr->dir,jprint(retjson,0)); + free_json(retjson); + ptr->pending = 0; + ptr->canceled = (uint32_t)time(NULL); + } + free(retstr); + } + } +} + +void marketmaker_queue(char *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *retjson) +{ + struct mmpending_order *ptr; char *orderid; + //DEX_trade.({"success":true,"message":"","result":{"uuid":"d5faa9e4-660d-436f-a257-2c6a40442d8c"},"tag":"11271578410079391025"} + if ( is_cJSON_True(jobj(retjson,"success")) != 0 && jobj(retjson,"result") != 0 ) + retjson = jobj(retjson,"result"); + printf("QUEUE.%s %s/%s dir.%d %.8f %.6f (%s)\n",exchange,base,rel,dir,price,volume,jprint(retjson,0)); + Pending_orders = realloc(Pending_orders,(1 + Num_Pending) * sizeof(*Pending_orders)); + ptr = &Pending_orders[Num_Pending++]; + memset(ptr,0,sizeof(*ptr)); + ptr->price = price; + ptr->volume = volume; + ptr->dir = dir; + ptr->pending = (uint32_t)time(NULL); + strcpy(ptr->exchange,exchange); + strcpy(ptr->base,base); + strcpy(ptr->rel,rel); + if ( (orderid= jstr(retjson,"OrderUuid")) != 0 || (orderid= jstr(retjson,"uuid")) != 0 ) + strcpy(ptr->orderid,orderid); + else strcpy(ptr->orderid,"0"); +} + +void marketmaker_pendingupdate(char *exchange,char *base,char *rel) +{ + char *retstr; cJSON *retjson,*obj; int32_t i; struct mmpending_order *ptr; + for (i=0; iexchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 ) + continue; + if ( ptr->completed == 0 && (retstr= DEX_orderstatus(exchange,ptr->orderid)) != 0 ) + { + //printf("%s status.(%s)\n",ptr->orderid,retstr); + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + obj = jobj(retjson,"result"); + if ( is_cJSON_Array(obj) != 0 ) + obj = jitem(retjson,0); + if ( jdouble(obj,"QuantityRemaining") == 0. || is_cJSON_True(jobj(obj,"IsOpen")) == 0 ) + { + //{"Uuid":null,"OrderUuid":"e7b0789c-0c4e-413b-a768-3d5734d9cbe5","Exchange":"BTC-KMD","OrderType":"LIMIT_SELL","Quantity":877.77700000,"QuantityRemaining":462.50512234,"Limit":0.00011770,"CommissionPaid":0.00012219,"Price":0.04887750,"PricePerUnit":0.00011769,"Opened":"2017-02-20T13:16:22.29","Closed":null,"CancelInitiated":false,"ImmediateOrCancel":false,"IsConditional":false,"Condition":"NONE","ConditionTarget":null} printf("uuid.(%s) finished.(%s)\n",ptr->orderid,jprint(retjson,0)); + ptr->completed = (uint32_t)time(NULL); + ptr->pending = 0; + } + free_json(retjson); + } + free(retstr); + } + } +} + +void marketmaker_pendinginit(char *exchange,char *base,char *rel) +{ + 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 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + //printf("%s\n",jprint(retjson,0)); + if ( is_cJSON_True(jobj(retjson,"success")) != 0 && (array= jarray(&n,retjson,"result")) != 0 ) + { + for (i=0; iexchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 ) + continue; + if ( strcmp(ptr->orderid,orderid) == 0 ) + { + ptr->pending = (uint32_t)time(NULL); + ptr->completed = 0; + printf("%s pending\n",orderid); + break; + } + } + if ( j == Num_Pending ) + { + if ( jstr(item,"OrderType") != 0 ) + { + if ( strcmp(jstr(item,"OrderType"),"LIMIT_BUY") == 0 ) + dir = 1; + else if ( strcmp(jstr(item,"OrderType"),"LIMIT_SELL") == 0 ) + dir = -1; + else dir = 0; + if ( dir != 0 ) + marketmaker_queue(exchange,base,rel,dir,jdouble(item,"Limit"),jdouble(item,"QuantityRemaining"),item); + else printf("no dir (%s) (%s)\n",jprint(item,0),jstr(item,"OrderType")); + } + } + } + } + } + free_json(retjson); + } + free(retstr); + } +} + +double marketmaker_filled(char *exchange,char *base,char *rel,double *buyvolp,double *sellvolp,double *pendingbidsp,double *pendingasksp) +{ + double pricesum = 0.,volsum = 0.; struct mmpending_order *ptr; int32_t i; + *pendingbidsp = *pendingasksp = 0.; + for (i=0; iexchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 ) + continue; + if ( ptr->completed != 0 ) + { + if ( ptr->reported == 0 ) + { + if ( ptr->dir > 0 ) + (*buyvolp) += ptr->volume; + else if ( ptr->dir < 0 ) + (*sellvolp) += ptr->volume; + pricesum += ptr->volume * ptr->price; + volsum += ptr->volume; + ptr->reported = (uint32_t)time(NULL); + printf("REPORT dir.%d vol %.8f\n",ptr->dir,ptr->volume); + } + } + else if ( ptr->pending != 0 ) // alternative is error or cancelled + { + if ( ptr->dir > 0 ) + (*pendingbidsp) += ptr->volume; + else if ( ptr->dir < 0 ) + (*pendingasksp) += ptr->volume; + } + } + if ( volsum != 0. ) + pricesum /= volsum; + return(pricesum); +} + +int32_t marketmaker_prune(char *exchange,char *base,char *rel,int32_t polarity,double bid,double ask,double separation) +{ + int32_t i,n = 0; struct mmpending_order *ptr; + for (i=0; iexchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 ) + continue; + if ( ptr->pending != 0 && ptr->cancelstarted == 0 ) + { + if ( polarity != 0 ) + { + if ( ((ptr->dir*polarity > 0 && ptr->price < bid-separation) || (ptr->dir*polarity < 0 && ptr->price > ask+separation)) ) + { + printf("polarity.%d dir.%d price.%f bid.%f ask.%f\n",polarity,ptr->dir,ptr->price,bid,ask); + marketmaker_cancel(ptr), n++; + } + } + /*else + {,*prunebid=0,*pruneask=0; double lowbid=0.,highask=0. + if ( ptr->dir > 0 && (lowbid == 0. || ptr->price < lowbid) ) + { + lowbid = ptr->price; + prunebid = ptr; + } + else if ( ptr->dir < 0 && (highask == 0. || ptr->price > highask) ) + { + highask = ptr->price; + pruneask = ptr; + } + }*/ + } + } + /*if ( polarity == 0 ) + { + if ( prunebid != 0 && fabs(prunebid->price - bid) > separation ) + marketmaker_cancel(prunebid), n++; + if ( pruneask != 0 && fabs(pruneask->price - ask) > separation ) + marketmaker_cancel(pruneask), n++; + }*/ + return(n); +} + +void marketmaker_volumeset(double *bidincrp,double *askincrp,double incr,double buyvol,double pendingbids,double sellvol,double pendingasks,double maxexposure) +{ + *bidincrp = *askincrp = incr; + //if ( pendingbids >= pendingasks+maxexposure ) + // *bidincrp = 0.; + //else if ( pendingasks >= pendingbids+maxexposure ) + // *askincrp = 0.; + if ( *bidincrp > 0. && pendingbids + *bidincrp > maxexposure ) + *bidincrp = (maxexposure - *bidincrp); + if ( *askincrp > 0. && pendingasks + *askincrp > maxexposure ) + *askincrp = (maxexposure - *askincrp); + if ( *bidincrp < 0. ) + *bidincrp = 0.; + if ( *askincrp < 0. ) + *askincrp = 0.; +} + +int32_t marketmaker_spread(char *exchange,char *base,char *rel,double bid,double bidvol,double ask,double askvol,double separation) +{ + int32_t nearflags[2],i,n = 0; struct mmpending_order *ptr; cJSON *retjson,*vals; char *retstr,postdata[1024],url[128]; double vol,spread_ratio; + memset(nearflags,0,sizeof(nearflags)); + if ( strcmp("DEX",exchange) != 0 ) + { + for (i=0; iexchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 ) + continue; + if ( ptr->pending != 0 && ptr->cancelstarted == 0 ) + { + if ( bid > SMALLVAL && bidvol > SMALLVAL && ptr->dir > 0 && fabs(bid - ptr->price) < separation ) + { + //printf("bid %.8f near %.8f\n",bid,ptr->price); + nearflags[0]++; + } + if ( ask > SMALLVAL && askvol > SMALLVAL && ptr->dir < 0 && fabs(ask - ptr->price) < separation ) + { + //printf("%.8f near %.8f\n",ask,ptr->price); + nearflags[1]++; + } + } + } + } + //printf("spread.%s (%.8f %.6f) (%.8f %.6f)\n",exchange,bid,bidvol,ask,askvol); + if ( bid > SMALLVAL && bidvol > SMALLVAL && nearflags[0] == 0 ) + { + if ( strcmp("DEX",exchange) == 0 && strcmp(base,"KMD") == 0 && strcmp(rel,"BTC") == 0 ) + { + if ( ask > SMALLVAL && askvol > SMALLVAL ) + { + /*li.profit = jdouble(vals,"profit"); + li.refprice = jdouble(vals,"refprice"); + li.bid = jdouble(vals,"bid"); + li.ask = jdouble(vals,"ask"); + if ( (li.minvol= jdouble(vals,"minvol")) <= 0. ) + li.minvol = (strcmp("BTC",base) == 0) ? 0.0001 : 0.001; + if ( (li.maxvol= jdouble(vals,"maxvol")) < li.minvol ) + li.maxvol = li.minvol;*/ + //curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"MVP\",\"vals\":{\"rel\":\"USD\",\"bid\":0.09,\"ask\":0.11,\"maxvol\":100}}" + vals = cJSON_CreateObject(); + jaddstr(vals,"rel","BTC"); + jaddnum(vals,"bid",bid); + jaddnum(vals,"ask",ask); + vol = bidvol > askvol ? askvol : bidvol; + jaddnum(vals,"maxvol",vol); + jaddnum(vals,"minvol",vol*0.1 > 100 ? 100 : vol * 0.1); + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"%s\",\"vals\":%s}",base,jprint(vals,1)); + //printf("(%s)\n",postdata); + if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata,0)) != 0 ) + { + //printf("(%s) -> (%s)\n",postdata,retstr); + free(retstr); + } + spread_ratio = .5 * ((ask - bid) / (bid + ask)); + for (i=0; i SMALLVAL ) + { + vals = cJSON_CreateObject(); + jaddstr(vals,"rel",CURRENCIES[i]); + jaddnum(vals,"bid",PAXPRICES[i] * (1. - spread_ratio)); + jaddnum(vals,"ask",PAXPRICES[i] * (1. + spread_ratio)); + jaddnum(vals,"maxvol",vol * PAXPRICES[i]); + jaddnum(vals,"minvol",MAX(1,(int32_t)(vol * 0.01 * PAXPRICES[i]))); + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"%s\",\"vals\":%s}","KMD",jprint(vals,1)); + if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata,0)) != 0 ) + { + //printf("(%s) -> (%s)\n",postdata,retstr); + free(retstr); + } + } + //break; + } + } else printf("unsupported ask only for DEX %s/%s\n",base,rel); + } + else if ( (retstr= DEX_trade(exchange,base,rel,1,bid,bidvol)) != 0 ) + { + //printf("DEX_trade.(%s)\n",retstr); + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + marketmaker_queue(exchange,base,rel,1,bid,bidvol,retjson); + free_json(retjson); + } + free(retstr); + } //else printf("skip bid %s %.8f vol %f\n",exchange,bid,bidvol); + } + if ( ask > SMALLVAL && askvol > SMALLVAL && nearflags[1] == 0 && strcmp("DEX",exchange) != 0 ) + { + if ( (retstr= DEX_trade(exchange,base,rel,-1,ask,askvol)) != 0 ) + { + //printf("DEX_trade.(%s)\n",retstr); + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + marketmaker_queue(exchange,base,rel,-1,ask,askvol,retjson); + free_json(retjson); + } + free(retstr); + } + } //else printf("skip ask %s %.8f vol %f\n",exchange,bid,bidvol); + return(n); +} +double marketmaker_updateprice(char *name,char *base,char *rel,double theoretical,double *incrp) +{ + static uint32_t counter; + cJSON *fiatjson; double USD_average=0.,usdprice=0.,CMC_average=0.,avebid=0.,aveask=0.,val,changes[3],highbid=0.,lowask=0.; + if ( (val= get_theoretical(&avebid,&aveask,&highbid,&lowask,&CMC_average,changes,name,base,rel,&USD_average)) != 0. ) + { + if ( theoretical == 0. ) + { + theoretical = val; + if ( *incrp > 2 ) + { + *incrp = (int32_t)*incrp; + *incrp += 0.777; + } + } else theoretical = (theoretical + val) * 0.5; + if ( (counter++ % 12) == 0 ) + { + if ( USD_average > SMALLVAL && CMC_average > SMALLVAL && theoretical > SMALLVAL ) + { + usdprice = USD_average * (theoretical / CMC_average); + printf("USD %.4f <- (%.6f * (%.8f / %.8f))\n",usdprice,USD_average,theoretical,CMC_average); + PAXPRICES[0] = usdprice; + if ( (fiatjson= yahoo_allcurrencies()) != 0 ) + { + marketmaker_fiatupdate(fiatjson); + free_json(fiatjson); + } + } + } + LP_priceupdate(base,rel,theoretical,avebid,aveask,highbid,lowask,PAXPRICES); + } + return(theoretical); +} + +void marketmaker(double minask,double maxbid,char *baseaddr,char *reladdr,double start_BASE,double start_REL,double profitmargin,double maxexposure,double ratioincr,char *exchange,char *name,char *base,char *rel) +{ + char *retstr; double bid,ask,start_DEXbase,start_DEXrel,DEX_base = 0.,DEX_rel = 0.,balance_base=0.,balance_rel=0.,mmbid,mmask,aveprice,incr,pendingbids,pendingasks,buyvol,sellvol,bidincr,askincr,filledprice,avebid=0.,aveask=0.,highbid=0.,lowask=0.,theoretical = 0.; uint32_t lasttime = 0; + incr = maxexposure * ratioincr; + buyvol = sellvol = 0.; + start_DEXbase = dex_balance(base,baseaddr); + start_DEXrel = dex_balance(rel,reladdr); + while ( 1 ) + { + if ( time(NULL) > lasttime+60 ) + { + if ( (theoretical= marketmaker_updateprice(name,base,rel,theoretical,&incr)) != 0. ) + { + if ( lasttime == 0 ) + maxexposure /= theoretical; + } + if ( strcmp(exchange,"bittrex") == 0 ) + { + balance_base = bittrex_balance(base,""); + balance_rel = bittrex_balance(rel,""); + DEX_base = dex_balance(base,baseaddr); + DEX_rel = dex_balance(rel,reladdr); + } else printf("add support for %s balance\n",exchange); + lasttime = (uint32_t)time(NULL); + } + marketmaker_pendingupdate(exchange,base,rel); + if ( theoretical > SMALLVAL && avebid > SMALLVAL && aveask > SMALLVAL ) + { + aveprice = (avebid + aveask) * 0.5; + // if order is filled, theoretical <- filled (theoretical + price)/2 + if ( (filledprice= marketmaker_filled(exchange,base,rel,&buyvol,&sellvol,&pendingbids,&pendingasks)) != 0. ) + theoretical = (theoretical + filledprice) * 0.5; + buyvol = sellvol = 0; + if ( (balance_base + DEX_base) < (start_BASE + start_DEXbase) ) + sellvol += ((start_BASE + start_DEXbase) - (balance_base + DEX_base)); + else buyvol += ((balance_base + DEX_base) - (start_BASE + start_DEXbase)); + if ( (balance_rel + DEX_rel) < (start_REL + start_DEXrel) ) + buyvol += ((start_REL + start_DEXrel) - (balance_rel + DEX_rel)) / theoretical; + else sellvol += ((balance_rel + DEX_rel) - (start_REL + start_DEXrel)) / theoretical; + mmbid = theoretical - theoretical*profitmargin; + mmask = theoretical + theoretical*profitmargin; + // if any existing order exceeds double margin distance, cancel + marketmaker_prune(exchange,base,rel,1,mmbid - theoretical*profitmargin,mmask + theoretical*profitmargin,0.); + // if new prices crosses existing order, cancel old order first + marketmaker_prune(exchange,base,rel,-1,mmbid,mmask,0.); + //printf("(%.8f %.8f) ",mmbid,mmask); + if ( (1) ) + { + if ( mmbid >= lowask || (maxbid > SMALLVAL && mmbid > maxbid) ) //mmbid < highbid || + { + printf("clear mmbid %.8f lowask %.8f maxbid %.8f\n",mmbid,lowask,maxbid); + mmbid = 0.; + } + if ( mmask <= highbid || (minask > SMALLVAL && mmask < minask) ) // mmask > lowask || + mmask = 0.; + } + marketmaker_volumeset(&bidincr,&askincr,incr,buyvol,pendingbids,sellvol,pendingasks,maxexposure); + printf("AVE.(%.8f %.8f) hbla %.8f %.8f bid %.8f ask %.8f theory %.8f buys.(%.6f %.6f) sells.(%.6f %.6f) incr.(%.6f %.6f) balances.(%.8f + %.8f, %.8f + %.8f) test %f\n",avebid,aveask,highbid,lowask,mmbid,mmask,theoretical,buyvol,pendingbids,sellvol,pendingasks,bidincr,askincr,balance_base,DEX_base,balance_rel,DEX_rel,(aveask - avebid)/aveprice); + if ( (retstr= DEX_swapstatus()) != 0 ) + printf("%s\n",retstr), free(retstr); + printf("%s %s %s, %s %s %s\n",base,DEX_baseaddr,DEX_balance("DEX",base,DEX_baseaddr),rel,DEX_reladdr,DEX_balance("DEX",rel,DEX_reladdr)); + if ( (aveask - avebid)/aveprice > profitmargin ) + bid = highbid * (1 - profitmargin), ask = lowask * (1 + profitmargin); + else bid = avebid - profitmargin*aveprice, ask = avebid + profitmargin*aveprice; + marketmaker_spread("DEX",base,rel,bid,incr,ask,incr,profitmargin*aveprice*0.5); + if ( (pendingbids + buyvol) > (pendingasks + sellvol) && (pendingbids + buyvol) > bidincr ) + { + bidincr *= ((double)(pendingasks + sellvol) / ((pendingbids + buyvol) + (pendingasks + sellvol))); + printf("bidincr %f buy.(%f + %f) sell.(%f + %f)\n",bidincr,pendingbids,buyvol,pendingasks,sellvol); + if ( bidincr < 0.1*incr ) + bidincr = 0.1*incr; + if ( bidincr > 1. ) + bidincr = (int32_t)bidincr + 0.777; + } + if ( (pendingbids + buyvol) < (pendingasks + sellvol) && (pendingasks + sellvol) > askincr ) + { + askincr *= (double)(pendingbids + buyvol) / ((pendingbids + buyvol) + (pendingasks + sellvol)); + if ( askincr < 0.1*incr ) + askincr = 0.1*incr; + if ( askincr > 1. ) + askincr = (int32_t)askincr + 0.777; + } + //printf("mmbid %.8f %.6f, mmask %.8f %.6f\n",mmbid,bidincr,mmask,askincr); + marketmaker_spread(exchange,base,rel,mmbid,bidincr,mmask,askincr,profitmargin*aveprice*0.5); + sleep(60); + } + } +} +profitmargin = jdouble(retjson,"profitmargin"); +minask = jdouble(retjson,"minask"); +maxbid = jdouble(retjson,"maxbid"); +maxexposure = jdouble(retjson,"maxexposure"); +incrratio = jdouble(retjson,"lotratio"); +start_base = jdouble(retjson,"start_base"); +start_rel = jdouble(retjson,"start_rel"); +apikey = jstr(retjson,"apikey"); +apisecret = jstr(retjson,"apisecret"); +base = jstr(retjson,"base"); +name = jstr(retjson,"name"); +rel = jstr(retjson,"rel"); +blocktrail = jstr(retjson,"blocktrail"); +exchange = jstr(retjson,"exchange"); +//PAXACTIVE = juint(retjson,"paxactive"); +if ( profitmargin < 0. || maxexposure <= 0. || incrratio <= 0. || apikey == 0 || apisecret == 0 || base == 0 || name == 0 || rel == 0 || exchange == 0 || blocktrail == 0 ) +{ + printf("illegal parameter (%s)\n",jprint(retjson,0)); + exit(-1); +} +if ( (retstr= iguana_walletpassphrase(passphrase,999999)) != 0 ) +{ + printf("(%s/%s) login.(%s)\n",base,rel,retstr); + if ( (loginjson= cJSON_Parse(retstr)) != 0 ) + { + if ( PAXACTIVE != 0 ) + { + for (i=0; i<32; i++) + { + if ( ((1<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]; @@ -479,7 +1338,56 @@ void issue_LP_listunspent(char *destip,uint16_t destport,char *symbol,char *coin 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; @@ -1797,6 +2705,91 @@ int32_t bitcoin_coinptrs(bits256 pubkey,struct iguana_info **bobcoinp,struct igu 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); +} + +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; @@ -1850,6 +2843,14 @@ int32_t bitcoin_coinptrs(bits256 pubkey,struct iguana_info **bobcoinp,struct igu } } 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; @@ -1905,12 +2906,177 @@ int32_t bitcoin_coinptrs(bits256 pubkey,struct iguana_info **bobcoinp,struct igu LP_utxoadd(0,-1,Q.destcoin,Q.desttxid,Q.destvout,Q.destvalue,Q.feetxid,Q.feevout,Q.feevalu,"",Q.destaddr,Q.desthash,0.); }*/ -/*struct LP_utxoinfo *utxo,*tmp; - HASH_ITER(hh,LP_utxoinfos[1],utxo,tmp) +/*struct LP_utxoinfo *utxo,*tmp; + HASH_ITER(hh,LP_utxoinfos[1],utxo,tmp) + { + 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 ( LP_ismine(utxo) > 0 && strcmp(utxo->coin,base) == 0 ) - LP_priceping(LP_mypubsock,utxo,rel,price * LP_profitratio); + 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 ) @@ -2345,6 +3511,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; @@ -2432,68 +3619,528 @@ void LP_utxo_spentcheck(int32_t pubsock,struct LP_utxoinfo *utxo) LP_spentnotify(utxo,1); } } -} - -int32_t LP_peer_utxosquery(struct LP_peerinfo *mypeer,uint16_t myport,int32_t pubsock,struct LP_peerinfo *peer,uint32_t now,int32_t interval,int32_t maxentries) -{ - int32_t lastn,n = -1; - if ( peer->lastutxos < now-interval ) +} + +int32_t LP_peer_utxosquery(struct LP_peerinfo *mypeer,uint16_t myport,int32_t pubsock,struct LP_peerinfo *peer,uint32_t now,int32_t interval,int32_t maxentries) +{ + int32_t lastn,n = -1; + if ( peer->lastutxos < now-interval ) + { + //lastn = peer->numutxos - mypeer->numutxos + LP_PROPAGATION_SLACK; + //if ( lastn < LP_PROPAGATION_SLACK * 2 ) + lastn = LP_PROPAGATION_SLACK * 2; + if ( mypeer == 0 || strcmp(peer->ipaddr,mypeer->ipaddr) != 0 ) + { + peer->lastutxos = now; + //printf("query utxos from %s\n",peer->ipaddr); + n = LP_utxosquery(mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,maxentries); + } + } //else printf("LP_peer_utxosquery skip.(%s) %u\n",peer->ipaddr,peer->lastutxos); + return(n); +} +bestitem = LP_quotejson(qp); +if ( LP_pricevalid(price) > 0 ) +{ + if ( price <= maxprice ) + { + LP_query(ctx,myipaddr,mypubsock,"connect",qp); + //price = LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout); + LP_requestinit(&qp->R,qp->srchash,qp->desthash,qp->srccoin,qp->satoshis-2*qp->txfee,qp->destcoin,qp->destsatoshis-2*qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector); + while ( time(NULL) < expiration ) + { + if ( aliceutxo->S.swap != 0 ) + break; + sleep(3); + } + jaddnum(bestitem,"quotedprice",price); + jaddnum(bestitem,"maxprice",maxprice); + if ( (swap= aliceutxo->S.swap) == 0 ) + { + if ( (pubp= LP_pubkeyadd(qp->srchash)) != 0 ) + pubp->numerrors++; + jaddstr(bestitem,"status","couldnt establish connection"); + } + else + { + jaddstr(bestitem,"status","connected"); + jaddnum(bestitem,"requestid",swap->I.req.requestid); + jaddnum(bestitem,"quoteid",swap->I.req.quoteid); + printf("Alice r.%u qp->%u\n",swap->I.req.requestid,swap->I.req.quoteid); + } + } + else + { + jaddnum(bestitem,"quotedprice",price); + jaddnum(bestitem,"maxprice",maxprice); + jaddstr(bestitem,"status","too expensive"); + } +} +else +{ + printf("invalid price %.8f\n",price); + jaddnum(bestitem,"maxprice",maxprice); + jaddstr(bestitem,"status","no response to request"); +} +uint32_t LP_allocated(bits256 txid,int32_t vout) +{ + struct LP_utxoinfo *utxo; + if ( (utxo= _LP_utxofind(0,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + { + //char str[65]; printf("%s/v%d not available\n",bits256_str(str,txid),vout); + return(utxo); + } + if ( (utxo= _LP_utxo2find(0,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + { + //char str[65]; printf("%s/v%d not available2\n",bits256_str(str,txid),vout); + return(utxo); + } + if ( (utxo= _LP_utxofind(1,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + { + //char str[65]; printf("%s/v%d not available\n",bits256_str(str,txid),vout); + return(utxo); + } + if ( (utxo= _LP_utxo2find(1,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + { + //char str[65]; printf("%s/v%d not available2\n",bits256_str(str,txid),vout); + return(utxo); + } + return(0); +} + +int32_t LP_isavailable(struct LP_utxoinfo *utxo) +{ + if ( time(NULL) > utxo->T.swappending ) + utxo->T.swappending = 0; + if ( utxo != 0 && utxo->T.swappending == 0 && utxo->S.swap == 0 ) + return(1); + else return(0); +} + +int32_t LP_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 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 ) { - //lastn = peer->numutxos - mypeer->numutxos + LP_PROPAGATION_SLACK; - //if ( lastn < LP_PROPAGATION_SLACK * 2 ) - lastn = LP_PROPAGATION_SLACK * 2; - if ( mypeer == 0 || strcmp(peer->ipaddr,mypeer->ipaddr) != 0 ) + if ( LP_ismine(utxo) > 0 ) { - peer->lastutxos = now; - //printf("query utxos from %s\n",peer->ipaddr); - n = LP_utxosquery(mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,maxentries); + //LP_utxo_clientpublish(utxo); + if ( LP_mypeer != 0 ) + utxo->T.lasttime = (uint32_t)time(NULL); } - } //else printf("LP_peer_utxosquery skip.(%s) %u\n",peer->ipaddr,peer->lastutxos); - return(n); + } + return(utxo); } -bestitem = LP_quotejson(qp); -if ( LP_pricevalid(price) > 0 ) + +int32_t _LP_utxos_remove(bits256 txid,int32_t vout) { - if ( price <= maxprice ) + struct LP_utxoinfo *utxo,*utxo2; int32_t retval = 0,iambob = 1; + utxo = utxo2 = 0; + if ( (utxo= _LP_utxofind(iambob,txid,vout)) != 0 ) { - LP_query(ctx,myipaddr,mypubsock,"connect",qp); - //price = LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout); - LP_requestinit(&qp->R,qp->srchash,qp->desthash,qp->srccoin,qp->satoshis-2*qp->txfee,qp->destcoin,qp->destsatoshis-2*qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector); - while ( time(NULL) < expiration ) - { - if ( aliceutxo->S.swap != 0 ) - break; - sleep(3); - } - jaddnum(bestitem,"quotedprice",price); - jaddnum(bestitem,"maxprice",maxprice); - if ( (swap= aliceutxo->S.swap) == 0 ) - { - if ( (pubp= LP_pubkeyadd(qp->srchash)) != 0 ) - pubp->numerrors++; - jaddstr(bestitem,"status","couldnt establish connection"); - } + if ( LP_isavailable(utxo) == 0 ) + retval = -1; else { - jaddstr(bestitem,"status","connected"); - jaddnum(bestitem,"requestid",swap->I.req.requestid); - jaddnum(bestitem,"quoteid",swap->I.req.quoteid); - printf("Alice r.%u qp->%u\n",swap->I.req.requestid,swap->I.req.quoteid); + 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 + else if ( (utxo2= _LP_utxo2find(iambob,txid,vout)) != 0 ) { - jaddnum(bestitem,"quotedprice",price); - jaddnum(bestitem,"maxprice",maxprice); - jaddstr(bestitem,"status","too expensive"); + if ( LP_isavailable(utxo2) == 0 ) + retval = -1; + else _LP_utxo2_delete(iambob,utxo2); } + return(retval); } -else + +int32_t LP_utxos_remove(bits256 txid,int32_t vout) { - printf("invalid price %.8f\n",price); - jaddnum(bestitem,"maxprice",maxprice); - jaddstr(bestitem,"status","no response to request"); + 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 ) @@ -2503,6 +4150,90 @@ else } 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); @@ -2749,6 +4480,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; isymbol,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 ) @@ -3059,6 +4894,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 40569f027..ec7380e17 100644 --- a/iguana/exchanges/LP_stats.c +++ b/iguana/exchanges/LP_stats.c @@ -20,28 +20,81 @@ #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; -uint32_t LP_atomic_locktime(char *base,char *rel) +void LP_dPoW_request(struct iguana_info *coin) { - if ( strcmp(base,"BTC") != 0 && strcmp(rel,"BTC") != 0 ) - return(INSTANTDEX_LOCKTIME); - else return(INSTANTDEX_LOCKTIME * 10); + 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)); } -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_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) { @@ -97,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 { @@ -111,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); @@ -130,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)); } @@ -180,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 ) { @@ -189,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); @@ -208,7 +281,7 @@ int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSO } else { - if ( requestid == sp->Q.R.requestid && quoteid == sp->Q.R.quoteid ) + if ( 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); } @@ -219,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)); @@ -242,25 +445,36 @@ 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 ) { HASH_ITER(hh,LP_swapstats,sp,tmp) { + static uint32_t counter; if ( sp->Q.R.requestid == requestid && sp->Q.R.quoteid == quoteid ) { sp->methodind = methodind; if ( LP_swapstats_update(sp,&Q,lineobj) == 0 ) + { flag = 1; - else printf("error after delayed match\n"); - break; + break; + } + if ( counter++ < 10 ) + 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 ) @@ -290,6 +504,9 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj) destvout = jint(lineobj,"destvout"); feetxid = jbits256(lineobj,"feetxid"); feevout = jint(lineobj,"feevout"); + if ( (statusstr= jstr(lineobj,"status")) != 0 && strcmp(statusstr,"finished") == 0 ) + RTflag = 0; + else RTflag = 1; qprice = ((double)destsatoshis / (satoshis - txfee)); //printf("%s/v%d %s/v%d\n",bits256_str(str,desttxid),destvout,bits256_str(str2,feetxid),feevout); aliceid = LP_aliceid_calc(desttxid,destvout,feetxid,feevout); @@ -305,17 +522,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 ) { @@ -330,11 +538,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 && refbase[0] != 0 && strcmp(refbase,sp->Q.srccoin) != 0 && strcmp(refbase,sp->Q.destcoin) != 0 ) + dispflag = 0; + if ( refrel != 0 && refrel[0] != 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)); @@ -342,45 +733,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+LP_atomic_locktime(sp->Q.srccoin,sp->Q.destcoin)*2 ) - sp->expired = (uint32_t)time(NULL); - dispflag = 0; - if ( starttime == 0 && endtime == 0 ) - dispflag = 1; - else if ( starttime > time(NULL) && endtime == starttime && sp->finished == 0 && sp->expired == 0 ) - dispflag = 1; - else if ( sp->Q.timestamp >= starttime && sp->Q.timestamp <= endtime ) - dispflag = 1; - if ( dispflag != 0 ) - { - dispflag = 0; - if ( refgui == 0 || refgui[0] == 0 || strcmp(refgui,sp->bobgui) == 0 || strcmp(refgui,sp->alicegui) == 0 ) - { - if ( bits256_nonz(refpubkey) == 0 || bits256_cmp(refpubkey,sp->Q.srchash) == 0 || bits256_cmp(refpubkey,sp->Q.desthash) == 0 ) - dispflag = 1; - } + if ( 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=0; i--) + { + item = jitem(swapsjson,i); + retitem = cJSON_CreateObject(); + if ( (base= jstr(item,"base")) != 0 && (rel= jstr(item,"rel")) != 0 && (basevol= jdouble(item,"basevol")) > SMALLVAL ) + { + relvol = jdouble(item,"relvol"); + jaddnum(retitem,"timestamp",juint(item,"timestamp")); + jaddnum(retitem,base,basevol); + jaddnum(retitem,rel,relvol); + jaddnum(retitem,"price",relvol/basevol); + } + jaddi(retjson,retitem); + } + } + free_json(logjson); + return(jprint(retjson,1)); + } else return(clonestr("{\"error\":\"couldnt get logjson\"}")); +} + +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 30329c864..b1f41a753 100644 --- a/iguana/exchanges/LP_swap.c +++ b/iguana/exchanges/LP_swap.c @@ -109,6 +109,13 @@ */ +uint32_t LP_atomic_locktime(char *base,char *rel) +{ + if ( strcmp(base,"BTC") != 0 && strcmp(rel,"BTC") != 0 ) + return(INSTANTDEX_LOCKTIME); + else return(INSTANTDEX_LOCKTIME * 10); +} + void basilisk_rawtx_purge(struct basilisk_rawtx *rawtx) { if ( rawtx->vins != 0 ) @@ -119,24 +126,27 @@ void basilisk_rawtx_purge(struct basilisk_rawtx *rawtx) void basilisk_swap_finished(struct basilisk_swap *swap) { - int32_t i; - /*if ( swap->utxo != 0 && swap->sentflag == 0 ) + /*int32_t i; + if ( swap->utxo != 0 && swap->sentflag == 0 ) { LP_availableset(swap->utxo); swap->utxo = 0; //LP_butxo_swapfields_set(swap->utxo); - }*/ - if ( swap->I.iambob != 0 ) - { - LP_availableset(swap->bobdeposit.utxotxid,swap->bobdeposit.utxovout); - LP_availableset(swap->bobpayment.utxotxid,swap->bobpayment.utxovout); } - else + swap->I.finished = (uint32_t)time(NULL);*/ + if ( swap->I.finished == 0 ) { - LP_availableset(swap->alicepayment.utxotxid,swap->alicepayment.utxovout); - LP_availableset(swap->myfee.utxotxid,swap->myfee.utxovout); + if ( swap->I.iambob != 0 ) + { + LP_availableset(swap->bobdeposit.utxotxid,swap->bobdeposit.utxovout); + LP_availableset(swap->bobpayment.utxotxid,swap->bobpayment.utxovout); + } + else + { + LP_availableset(swap->alicepayment.utxotxid,swap->alicepayment.utxovout); + LP_availableset(swap->myfee.utxotxid,swap->myfee.utxovout); + } } - swap->I.finished = (uint32_t)time(NULL); // save to permanent storage basilisk_rawtx_purge(&swap->bobdeposit); basilisk_rawtx_purge(&swap->bobpayment); @@ -149,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; } @@ -240,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); @@ -634,7 +644,7 @@ 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(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 ) + 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; @@ -732,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; } @@ -762,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); @@ -781,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"); @@ -810,9 +823,9 @@ void LP_bobloop(void *_swap) printf("error bobscripts payment\n"); else { - if ( strcmp(swap->I.alicestr,"BTC") == 0 ) + /*if ( strcmp(swap->I.alicestr,"BTC") == 0 ) m = 0; - else m = swap->I.aliceconfirms; + else*/ m = swap->I.aliceconfirms; while ( (n= LP_numconfirms(swap->I.alicestr,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,1)) < m ) // sync with alice { LP_swap_critical = (uint32_t)time(NULL); @@ -824,21 +837,22 @@ void LP_bobloop(void *_swap) 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_swap_endcritical = (uint32_t)time(NULL); - LP_swapwait(swap->I.req.requestid,swap->I.req.quoteid,LP_atomic_locktime(swap->I.bobstr,swap->I.alicestr)*2,30); + 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) @@ -851,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"); @@ -867,53 +881,60 @@ void LP_aliceloop(void *_swap) 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->I.alicestr,"BTC") == 0 ) + /*if ( strcmp(swap->I.bobstr,"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 ) + else*/ m = swap->I.bobconfirms; + while ( (n= LP_numconfirms(swap->I.bobstr,swap->bobdeposit.I.destaddr,swap->bobdeposit.I.signedtxid,0,1)) < m ) { 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)); + 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; - 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"); + if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0) == 0 ) + printf("error sending alicepayment\n"); else { - 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 ) + /*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 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)); + 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->I.alicestr,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 wait for alicespend %s numconfs.%d %s %s\n",n,swap->alicespend.I.destaddr,swap->I.aliceconfirms,swap->I.bobstr,bits256_str(str,swap->alicespend.I.signedtxid)); - sleep(LP_SWAPSTEP_TIMEOUT); - }*/ - if ( swap->N.pair >= 0 ) - nn_close(swap->N.pair), swap->N.pair = -1; - LP_swapwait(swap->I.req.requestid,swap->I.req.quoteid,LP_atomic_locktime(swap->I.bobstr,swap->I.alicestr)*2,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); G.LP_pendingswaps--; } @@ -1029,7 +1050,7 @@ void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx * } else printf("%s vouttype.%d destaddr.(%s)\n",name,rawtx->I.vouttype,rawtx->I.destaddr); } -struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 pubkey25519,struct basilisk_swap *swap,int32_t optionduration,uint32_t statebits,struct LP_quoteinfo *qp) +struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 pubkey25519,struct basilisk_swap *swap,int32_t optionduration,uint32_t statebits,struct LP_quoteinfo *qp,int32_t dynamictrust) { //FILE *fp; char fname[512]; uint8_t *alicepub33=0,*bobpub33=0; int32_t jumblrflag=-2,x = -1; struct iguana_info *bobcoin,*alicecoin; @@ -1076,7 +1097,7 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 swap->I.bobinsurance = LP_MIN_TXFEE; if ( (swap->I.aliceinsurance= (swap->I.alicesatoshis / INSTANTDEX_INSURANCEDIV)) < LP_MIN_TXFEE ) swap->I.aliceinsurance = LP_MIN_TXFEE; - 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 ) @@ -1089,14 +1110,18 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 swap->I.iambob = 0; swap->I.otherhash = swap->I.req.desthash; swap->I.aliceistrusted = 1; - swap->I.otheristrusted = swap->I.bobistrusted = LP_pubkey_istrusted(swap->I.req.srchash); + if ( dynamictrust == 0 && LP_pubkey_istrusted(swap->I.req.srchash) != 0 ) + dynamictrust = 1; + swap->I.otheristrusted = swap->I.bobistrusted = dynamictrust; } else { swap->I.iambob = 1; swap->I.otherhash = swap->I.req.srchash; swap->I.bobistrusted = 1; - swap->I.otheristrusted = swap->I.aliceistrusted = LP_pubkey_istrusted(swap->I.req.desthash); + if ( dynamictrust == 0 && LP_pubkey_istrusted(swap->I.req.desthash) != 0 ) + dynamictrust = 1; + swap->I.otheristrusted = swap->I.aliceistrusted = dynamictrust; } if ( bits256_nonz(privkey) == 0 || (x= instantdex_pubkeyargs(swap,2 + INSTANTDEX_DECKSIZE,privkey,swap->I.orderhash,0x02+swap->I.iambob)) != 2 + INSTANTDEX_DECKSIZE ) { @@ -1105,12 +1130,12 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 } if ( strcmp("BTC",swap->I.bobstr) == 0 ) { - swap->I.bobconfirms = (1 + sqrt(dstr(swap->I.bobsatoshis) * .1)); + swap->I.bobconfirms = 1;//(1 + sqrt(dstr(swap->I.bobsatoshis) * .1)); swap->I.aliceconfirms = BASILISK_DEFAULT_NUMCONFIRMS; } else if ( strcmp("BTC",swap->I.alicestr) == 0 ) { - swap->I.aliceconfirms = (1 + sqrt(dstr(swap->I.alicesatoshis) * .1)); + swap->I.aliceconfirms = 1;//(1 + sqrt(dstr(swap->I.alicesatoshis) * .1)); swap->I.bobconfirms = BASILISK_DEFAULT_NUMCONFIRMS; } else @@ -1151,20 +1176,20 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 } swap->myfee.I.locktime = swap->I.started + 1; swap->otherfee.I.locktime = swap->I.started + 1; - basilisk_rawtx_setparms("bobdeposit",swap->I.req.quoteid,&swap->bobdeposit,bobcoin,swap->I.bobconfirms,0,LP_DEPOSITSATOSHIS(swap->I.bobsatoshis) + bobcoin->txfee,4,0,jumblrflag); + basilisk_rawtx_setparms("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,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,bobcoin,swap->I.bobconfirms,0,swap->I.bobsatoshis + bobcoin->txfee,3,0,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,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,alicecoin,swap->I.aliceconfirms,0,swap->I.alicesatoshis + alicecoin->txfee,2,0,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,alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,alicepub33,jumblrflag); @@ -1186,7 +1211,7 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 return(swap); } -struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp) +struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp,int32_t dynamictrust) { struct basilisk_swap *swap; bits256 pubkey25519; uint8_t pubkey33[33]; swap = calloc(1,sizeof(*swap)); @@ -1205,7 +1230,7 @@ struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 swap->persistent_privkey = privkey; memcpy(swap->persistent_pubkey33,pubkey33,33); calc_rmd160_sha256(swap->changermd160,pubkey33,33); - if ( bitcoin_swapinit(privkey,pubkey33,pubkey25519,swap,optionduration,!iambob,qp) == 0 ) + if ( bitcoin_swapinit(privkey,pubkey33,pubkey25519,swap,optionduration,!iambob,qp,dynamictrust) == 0 ) { printf("error doing swapinit\n"); free(swap); diff --git a/iguana/exchanges/LP_tradebots.c b/iguana/exchanges/LP_tradebots.c index d4a2fdfd5..39526c2be 100644 --- a/iguana/exchanges/LP_tradebots.c +++ b/iguana/exchanges/LP_tradebots.c @@ -40,10 +40,19 @@ struct LP_tradebot 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)) != 0 ) + if ( (swapstr= basilisk_swapentry(tp->requestid,tp->quoteid,1)) != 0 ) { flag = 0; if ( (swapjson= cJSON_Parse(swapstr)) != 0 ) @@ -195,7 +204,7 @@ cJSON *LP_tradebot_json(struct LP_tradebot *bot) jadd(json,"trades",array); if ( bot->basesum > SMALLVAL && bot->relsum > SMALLVAL && bot->completed > 0 ) { - jaddnum(json,"completed",bot->completed); + jadd(json,"complete",bot->completed!=0?jtrue():jfalse()); jaddnum(json,"percentage",100. * (bot->relsum / bot->totalrelvolume)); if ( bot->dispdir > 0 ) { @@ -413,11 +422,12 @@ void LP_tradebot_finished(uint32_t tradeid,uint32_t requestid,uint32_t quoteid) void LP_tradebots_timeslice(void *ctx) { static uint32_t lastnumfinished = 0; - struct iguana_info *relcoin; struct LP_tradebot *bot,*tmp; + 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); + 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 ) @@ -455,12 +465,12 @@ char *LP_tradebot_statuslist(void *ctx,int32_t pubsock,cJSON *argjson) char *LP_tradebot_buy(int32_t dispdir,char *base,char *rel,double maxprice,double relvolume) { - struct LP_tradebot *bot; char *retstr; double shortfall; int32_t i,n; cJSON *array,*item,*retjson; uint64_t sum,txfee,txfees,balance=0,abalance=0; struct iguana_info *basecoin,*relcoin; + 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 ( (array= LP_inventory(rel)) != 0 ) { if ( (n= cJSON_GetArraySize(array)) > 0 && is_cJSON_Array(array) != 0 ) { @@ -471,7 +481,7 @@ char *LP_tradebot_buy(int32_t dispdir,char *base,char *rel,double maxprice,doubl } } free_json(array); - } + }*/ if ( (retstr= LP_orderbook(base,rel,0)) != 0 ) free(retstr); txfee = LP_txfeecalc(relcoin,0,0); @@ -481,8 +491,8 @@ char *LP_tradebot_buy(int32_t dispdir,char *base,char *rel,double maxprice,doubl else balance = LP_RTsmartbalance(relcoin); sum = (SATOSHIDEN*relvolume+2*dstr(txfees)) + 3 * ((SATOSHIDEN*relvolume+2*dstr(txfees))/777); printf("%s inventory balance %.8f, relvolume %.8f + txfees %.8f, utxobal %.8f sum %.8f\n",rel,dstr(abalance),relvolume,dstr(txfees),dstr(balance),dstr(sum)); - if ( (abalance < SATOSHIDEN*relvolume + txfees) || ((balance-abalance) < (uint64_t)(SATOSHIDEN*relvolume)/777 + txfees) ) - //if ( dstr(abalance) < relvolume && balance > sum+2*txfee ) + //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"); @@ -493,7 +503,7 @@ char *LP_tradebot_buy(int32_t dispdir,char *base,char *rel,double maxprice,doubl jaddnum(retjson,"txfees",dstr(txfees)); shortfall = (relvolume + dstr(txfees)) - dstr(balance); jaddnum(retjson,"shortfall",shortfall); - if ( balance > sum+2*txfee ) + /*if ( balance > sum+2*txfee ) { char *withdrawstr; cJSON *outputjson,*withdrawjson,*outputs,*item; outputjson = cJSON_CreateObject(); @@ -518,7 +528,7 @@ char *LP_tradebot_buy(int32_t dispdir,char *base,char *rel,double maxprice,doubl 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); diff --git a/iguana/exchanges/LP_transaction.c b/iguana/exchanges/LP_transaction.c index d61940855..cf0286ff8 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 ) @@ -397,29 +397,26 @@ int32_t iguana_vininfo_create(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uin int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *signedtxidp,char **signedtx,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxlen,struct vin_info *V,uint32_t sighash,int32_t signtx,int32_t suppress_pubkeys,int32_t zcash) { - bits256 sigtxid; uint8_t *sig,*script; struct vin_info *vp; char vpnstr[64]; int32_t scriptlen,complete=0,j,vini=0,flag=0,siglen,numvouts,numsigs; + bits256 sigtxid; int64_t spendamount; uint8_t *sig,*script; struct vin_info *vp; char vpnstr[64]; int32_t scriptlen,complete=0,j,vini=0,flag=0,siglen,numvouts,numsigs; numvouts = msgtx->tx_out; vpnstr[0] = 0; *signedtx = 0; memset(signedtxidp,0,sizeof(*signedtxidp)); +//printf("bitcoin_verifyvins numvins.%d numvouts.%d signtx.%d privkey.%d M.%d N.%d\n",msgtx->tx_in,numvouts,signtx,bits256_nonz(V[0].signers[0].privkey),V[0].M,V[0].N); 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); + spendamount = LP_outpoint_amount(symbol,msgtx->vins[vini].prev_hash,msgtx->vins[vini].prev_vout); + sigtxid = bitcoin_sigtxid(symbol,taddr,pubtype,p2shtype,isPoS,height,serialized,maxlen,msgtx,vini,script,scriptlen,spendamount,sighash,vpnstr,suppress_pubkeys,zcash); if ( bits256_nonz(sigtxid) != 0 ) { vp = &V[vini]; @@ -439,7 +436,7 @@ int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype, int32_t i; for (i=0; isigners[j].pubkey[i]); // s2 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1; printf(" SIGNEDTX.[%02x] siglen.%d priv.%s\n",sig[siglen-1],siglen,bits256_str(str,vp->signers[j].privkey));*/ @@ -447,6 +444,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 ) @@ -465,17 +463,18 @@ 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);*/ } } if ( numsigs >= vp->M ) complete = 1; - } + } else if ( signtx != 0 ) + printf("bitcoin_verifyvins cant without privkey\n"); } 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); @@ -491,7 +490,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[LP_MAXVINS],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 ) @@ -503,7 +502,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"); @@ -512,7 +511,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)); @@ -540,7 +539,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_ 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 ) { @@ -599,7 +598,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 ) @@ -621,7 +621,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_ char *iguana_validaterawtx(void *ctx,struct iguana_info *coin,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,char *rawtx,int32_t mempool,int32_t suppress_pubkeys,int32_t zcash) { - bits256 signedtxid; struct iguana_msgvin vin; cJSON *log,*vins,*vouts,*txobj,*retjson; char *signedtx; int32_t plen,height,finalized = 1,i,len,maxsize,numinputs,numoutputs,complete; struct vin_info *V; uint8_t *serialized,*serialized2; uint32_t sigsize,pubkeysize,p2shsize,suffixlen; int64_t inputsum,outputsum; struct iguana_msgvout vout; + 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; @@ -637,12 +637,11 @@ char *iguana_validaterawtx(void *ctx,struct iguana_info *coin,struct iguana_msgt if ( (strlen(rawtx) & 1) != 0 ) return(clonestr("{\"error\":\"rawtx hex has odd length\"}")); memset(msgtx,0,sizeof(*msgtx)); - if ( (txobj= bitcoin_hex2json(taddr,pubtype,p2shtype,isPoS,height,&msgtx->txid,msgtx,rawtx,extraspace,extralen,0,0,suppress_pubkeys,zcash)) != 0 ) + 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); - V = calloc(numinputs,sizeof(*V)); if ( (vouts= jarray(&numoutputs,txobj,"vout")) > 0 ) { for (i=0; i 0 ) { + V = calloc(numinputs,sizeof(*V)); len = 0; for (i=0; ilock_time = 0; + V[i].amount = 2746715; + strcpy(V[i].coinaddr,"19Cq6MBaD8LY7trqs99ypqKAms3GcLs6J9"); + V[i].suppress_pubkeys = 0; + decode_hex(msgtx->vins[i].prev_hash.bytes,32,"b19ce2c564f7dc57b3f95593e2b287c72d388e86de12dc562d9f8a6bea65b310"); + msgtx->vins[i].prev_vout = 1; + msgtx->vins[i].sequence = 0xffffffff; + sobj = cJSON_CreateObject(); + jaddstr(sobj,"hex","76a91459fdba29ea85c65ad90f6d38f7a6646476b26b1688ac"); + jadd(item,"scriptPubKey",sobj); + printf("match special txid B\n"); + V[i].signers[0].privkey = G.LP_privkey; + } msgtx->vins[i].spendscript = V[i].spendscript; - if ( (msgtx->vins[i].spendlen= V[i].spendlen) == 35 ) + msgtx->vins[i].spendlen = V[i].spendlen; + if ( (sobj= jobj(item,"scriptSig")) != 0 ) { - if ( (plen= bitcoin_pubkeylen(msgtx->vins[i].spendscript+1)) > 0 ) + if ( (scriptsig= jstr(sobj,"hex")) != 0 ) { - memcpy(V[i].signers[0].pubkey,msgtx->vins[i].spendscript+1,plen); - V[i].suppress_pubkeys = 1; + 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); + } } } - V[i].hashtype = iguana_vinscriptparse(taddr,pubtype,p2shtype,&V[i],&sigsize,&pubkeysize,&p2shsize,&suffixlen,msgtx->vins[i].vinscript,msgtx->vins[i].scriptlen); - if ( (V[i].signers[0].siglen= sigsize) > 0 ) - memcpy(V[i].signers[0].sig,msgtx->vins[i].vinscript+1,sigsize); - V[i].userdatalen = suffixlen; - memcpy(V[i].spendscript,msgtx->vins[i].spendscript,msgtx->vins[i].spendlen); - V[i].spendlen = msgtx->vins[i].spendlen; + inputsum += V[i].amount; if ( msgtx->vins[i].sequence < IGUANA_SEQUENCEID_FINAL ) finalized = 0; - if ( V[i].M == 0 ) - V[i].M = 1; - if ( V[i].N < V[i].M ) - V[i].N = V[i].M; - printf("V %dof%d %.8f (%s) spendscript.[%d] scriptlen.%d\n",V[i].M,V[i].N,dstr(V[i].amount),V[i].coinaddr,V[i].spendlen,V[i].spendlen); } - complete = bitcoin_verifyvins(ctx,symbol,taddr,pubtype,p2shtype,isPoS,height,&signedtxid,&signedtx,msgtx,serialized2,maxsize,V,SIGHASH_ALL,1,V->suppress_pubkeys,LP_IS_BITCOINCASH); + 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; - log = cJSON_CreateArray(); + /*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); - jaddnum(retjson,"complete",complete); - free(serialized), free(serialized2); + 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)); } @@ -706,9 +735,9 @@ char *iguana_validaterawtx(void *ctx,struct iguana_info *coin,struct iguana_msgt return(jprint(retjson,1)); } -void test_validate(char *signedtx) +void test_validate(struct iguana_info *coin,char *signedtx) { - char *retstr; uint8_t extraspace[8192]; int32_t mempool=0; struct iguana_msgtx msgtx; struct iguana_info *coin = LP_coinfind("BTC"); + char *retstr; uint8_t extraspace[8192]; int32_t mempool=0; struct iguana_msgtx msgtx; retstr = iguana_validaterawtx(bitcoin_ctx(),coin,&msgtx,extraspace,sizeof(extraspace),signedtx,mempool,0,coin->zcash); printf("validate test.(%s)\n",retstr); } @@ -730,7 +759,7 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch if ( (coin= LP_coinfind(symbol)) != 0 ) { #ifndef BASILISK_DISABLESENDTX - if ( (txobj= LP_gettx(symbol,utxotxid)) != 0 ) + if ( (txobj= LP_gettx(symbol,utxotxid,0)) != 0 ) { if ( (vouts= jarray(&n,txobj,"vout")) != 0 && utxovout < n ) { @@ -806,7 +835,7 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch V[0].ignore_cltverr = ignore_cltverr; if ( redeemlen != 0 ) memcpy(V[0].p2shscript,redeemscript,redeemlen), V[0].p2shlen = redeemlen; - txobj = bitcoin_txcreate(symbol,isPoS,locktime,1,timestamp); + txobj = bitcoin_txcreate(symbol,isPoS,locktime,coin->txversion,timestamp); vins = cJSON_CreateArray(); item = cJSON_CreateObject(); if ( userdata != 0 && userdatalen > 0 ) @@ -908,19 +937,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) @@ -938,8 +981,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; @@ -1082,20 +1127,21 @@ int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_ if ( LP_validSPV(coin->symbol,coin->smartaddr,up->U.txid,up->U.vout) < 0 ) continue; } - + if ( 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 ( 0 && (interest= LP_komodo_interest(up->U.txid,up->U.value)) > 0 ) + if ( (interest= LP_komodo_interest(up->U.txid,up->U.value)) > 0 ) { interestsum += interest; char str[65]; printf("%s/%d %.8f interest %.8f -> sum %.8f\n",bits256_str(str,up->U.txid),up->U.vout,dstr(up->U.value),dstr(interest),dstr(interestsum)); } } - //printf("numunspents.%d vini.%d value %.8f, total %.8f remains %.8f interest %.8f sum %.8f %s/v%d\n",numunspents,n,dstr(up->U.value),dstr(total),dstr(remains),dstr(interest),dstr(interestsum),bits256_str(str,up->U.txid),up->U.vout); + printf("numunspents.%d vini.%d value %.8f, total %.8f remains %.8f interest %.8f sum %.8f %s/v%d\n",numunspents,n,dstr(up->U.value),dstr(total),dstr(remains),dstr(interest),dstr(interestsum),bits256_str(str,up->U.txid),up->U.vout); vp = &V[n++]; vp->N = vp->M = 1; vp->signers[0].privkey = privkey; @@ -1104,10 +1150,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)); - LP_unavailableset(up->U.txid,up->U.vout,(uint32_t)time(NULL)+600,G.LP_mypub25519); + LP_unavailableset(up->U.txid,up->U.vout,(uint32_t)time(NULL)+LP_RESERVETIME,G.LP_mypub25519); if ( remains <= 0 && i >= numpre-1 ) break; - if ( numunspents < 0 ) + if ( numunspents < 0 || n >= LP_MAXVINS ) { printf("total %.8f not enough for amount %.8f\n",dstr(total),dstr(amount)); return(0); @@ -1120,16 +1166,16 @@ int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_info *coin,struct vin_info *V,int32_t max,bits256 privkey,cJSON *outputs,cJSON *vins,cJSON *privkeys,int64_t txfee,bits256 utxotxid,int32_t utxovout,uint32_t locktime) { static void *ctx; - cJSON *txobj,*item; uint8_t addrtype,rmd160[20],script[64],spendscript[256]; char *coinaddr,*rawtxbytes; bits256 txid; uint32_t timestamp; int64_t change=0,adjust=0,total,value,amount = 0; int32_t i,dustcombine,scriptlen,spendlen,suppress_pubkeys,ignore_cltverr,numvouts=0,numvins=0,numutxos=0; struct LP_address_utxo *utxos[LP_MAXVINS]; struct LP_address *ap; + 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); @@ -1148,7 +1194,7 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf { if ( LP_address_isvalid(coin->symbol,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 ) @@ -1165,15 +1211,13 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf return(0); } } - //if ( bits256_nonz(utxotxid) == 0 ) + if ( (ap= LP_address(coin,coin->smartaddr)) == 0 ) { - if ( (ap= LP_address_utxo_reset(coin)) == 0 ) - return(0); + printf("LP_createrawtransaction LP_address null?\n"); + return(0); } - //else if ( (ap= LP_address(coin,coin->smartaddr)) == 0 ) - // return(0); memset(utxos,0,sizeof(utxos)); - if ( (numutxos= LP_address_utxo_ptrs(coin,0,utxos,max,ap,coin->smartaddr)) <= 0 ) + if ( (numutxos= LP_address_utxo_ptrs(coin,0,utxos,(int32_t)(sizeof(utxos)/sizeof(*utxos)),ap,coin->smartaddr)) <= 0 ) { if ( bits256_nonz(utxotxid) == 0 ) { @@ -1199,14 +1243,9 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf timestamp = (uint32_t)time(NULL); if ( locktime == 0 && strcmp("KMD",coin->symbol) == 0 ) locktime = timestamp - 777; - txobj = bitcoin_txcreate(coin->symbol,coin->isPoS,locktime,1,timestamp); + txobj = bitcoin_txcreate(coin->symbol,coin->isPoS,locktime,coin->txversion,timestamp); jdelete(txobj,"vin"); jadd(txobj,"vin",jduplicate(vins)); - if ( change < 6000 ) - { - adjust = change / numvouts; - change = 0; - } printf("change %.8f = total %.8f - amount %.8f, adjust %.8f numvouts.%d\n",dstr(change),dstr(total),dstr(amount),dstr(adjust),numvouts); for (i=0; itaddr,&addrtype,rmd160,coinaddr); if ( addrtype == coin->pubtype ) spendlen = bitcoin_standardspend(spendscript,0,rmd160); else spendlen = bitcoin_p2shspend(spendscript,0,rmd160); + 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,utxovout,autofee,completed=0,maxV,numvins,numvouts,datalen,suppress_pubkeys; bits256 privkey; char changeaddr[64],vinaddr[64],str[65],*signedtx=0,*rawtx=0; struct vin_info *V; uint32_t locktime; cJSON *retjson,*outputs,*vins=0,*txobj=0,*privkeys=0; struct iguana_msgtx msgtx; bits256 utxotxid,signedtxid; uint64_t txfee,newtxfee=10000; + 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 ) @@ -1271,9 +1324,16 @@ char *LP_withdraw(struct iguana_info *coin,cJSON *argjson) 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); + 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; @@ -1286,25 +1346,44 @@ char *LP_withdraw(struct iguana_info *coin,cJSON *argjson) printf("incomplete signing withdraw (%s)\n",jprint(vins,0)); if ( signedtx != 0 ) free(signedtx), signedtx = 0; - } else printf("LP_withdraw %s -> %s\n",jprint(argjson,0),bits256_str(str,signedtxid)); + } else printf("LP_withdraw.%s %s -> %s\n",coin->symbol,jprint(argjson,0),bits256_str(str,signedtxid)); 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; iI.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 ) @@ -1350,7 +1430,7 @@ int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pub 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); @@ -1475,7 +1555,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); @@ -1486,7 +1566,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 ) { @@ -1558,25 +1638,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; itaddr,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 ) @@ -1954,7 +2065,7 @@ int32_t LP_verify_otherfee(struct basilisk_swap *swap,uint8_t *data,int32_t data diff = swap->otherfee.I.locktime - (swap->I.started+1); if ( diff < 0 ) diff = -diff; - if ( diff < 10 ) + 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); diff --git a/iguana/exchanges/LP_utxo.c b/iguana/exchanges/LP_utxo.c index 8ea1d2db5..675acc57c 100644 --- a/iguana/exchanges/LP_utxo.c +++ b/iguana/exchanges/LP_utxo.c @@ -41,18 +41,19 @@ struct LP_inuse_info *_LP_inuse_find(bits256 txid,int32_t vout) int32_t _LP_inuse_delete(bits256 txid,int32_t vout) { - struct LP_inuse_info *lp; int32_t ind; + struct LP_inuse_info *lp; int32_t ind; char str[65]; if ( (lp= _LP_inuse_find(txid,vout)) != 0 ) { ind = lp->ind; - *lp = LP_inuse[--LP_numinuse]; + 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; indotherpub = otherpub; - if ( expiration > lp->expiration || expiration == 0 ) + //if ( expiration > lp->expiration || expiration == 0 ) lp->expiration = expiration; } + char str[65]; printf("set inuse until %u lag.%d for %s/v%d\n",expiration,(int32_t)(expiration-(uint32_t)time(NULL)),bits256_str(str,txid),vout); return(lp); } else printf("_LP_inuse_add [%d] overflow\n",LP_numinuse); return(0); @@ -151,13 +153,34 @@ void LP_availableset(bits256 txid,int32_t vout) portable_mutex_unlock(&LP_inusemutex); } -int32_t LP_isavailable(struct LP_utxoinfo *utxo) +int32_t LP_maxvalue(uint64_t *values,int32_t n) { - 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 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) @@ -237,24 +260,29 @@ 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); } @@ -263,7 +291,6 @@ int32_t LP_address_utxo_ptrs(struct iguana_info *coin,int32_t iambob,struct LP_a struct LP_address_utxo *up,*tmp; struct LP_transaction *tx; cJSON *txout; int32_t n = 0; if ( strcmp(ap->coinaddr,coinaddr) != 0 ) printf("UNEXPECTED coinaddr mismatch (%s) != (%s)\n",ap->coinaddr,coinaddr); - //LP_listunspent_issue(coin->symbol,coin->smartaddr,2); //portable_mutex_lock(&LP_utxomutex); DL_FOREACH_SAFE(ap->utxos,up,tmp) { @@ -309,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\n"); + } //else printf("LP_allocated skip %u\n",LP_allocated(up->U.txid,up->U.vout)); } else { @@ -418,15 +445,17 @@ int32_t LP_address_utxoadd(uint32_t timestamp,char *debug,struct iguana_info *co struct LP_address *LP_address_utxo_reset(struct iguana_info *coin) { - struct LP_address *ap; struct LP_address_utxo *up,*tmp; int32_t i,n,vout,height; cJSON *array,*item; int64_t value; bits256 txid; uint32_t now; + 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); - LP_listunspent_issue(coin->symbol,coin->smartaddr,2); + //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)) != 0 ) + if ( (array= LP_listunspent(coin->symbol,coin->smartaddr,zero,zero)) != 0 ) { DL_FOREACH_SAFE(ap->utxos,up,tmp) { @@ -442,29 +471,26 @@ struct LP_address *LP_address_utxo_reset(struct iguana_info *coin) if ( (n= cJSON_GetArraySize(array)) > 0 ) { char str[65]; - for (i=0; ielectrum != 0 ) - { - txid = jbits256(item,"tx_hash"); - vout = juint(item,"tx_pos"); - value = j64bits(item,"value"); - height = jint(item,"height"); - } - else - { - txid = jbits256(item,"txid"); - vout = juint(item,"vout"); - value = LP_value_extract(item,0); - height = LP_txheight(coin,txid); - } + value = LP_listunspent_parseitem(coin,&txid,&vout,&height,item); + if ( (txobj= LP_gettxout(coin->symbol,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",n); + //printf("added %d from listunspents\n",m); } free_json(array); } @@ -473,13 +499,13 @@ struct LP_address *LP_address_utxo_reset(struct iguana_info *coin) 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",""); } @@ -555,10 +581,11 @@ 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,*item; int32_t i,n; uint64_t balance = 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 ( (array= LP_listunspent(coin->symbol,coinaddr)) != 0 ) + if ( (array= LP_listunspent(coin->symbol,coinaddr,zero,zero)) != 0 ) { if ( (n= cJSON_GetArraySize(array)) > 0 ) { @@ -573,32 +600,98 @@ cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electr } else { - if ( strcmp(coin->smartaddr,coinaddr) == 0 ) - balance = LP_unspents_load(coin->symbol,coinaddr); - else + if ( strcmp(coin->smartaddr,coinaddr) != 0 ) { - if ( (array= LP_address_utxos(coin,coinaddr,1)) != 0 ) - { - if ( (n= cJSON_GetArraySize(array)) > 0 ) - { - for (i=0; isymbol,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 taddr,addrtype,rmd160[20]; uint64_t balance,KMDvalue,sum = 0; cJSON *array,*item,*retjson; + if ( coinaddr != 0 && coinaddr[0] == 't' && (coinaddr[1] == '1' || coinaddr[1] == '3') ) + taddr = 1; + else taddr = 0; + 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 ) + strcpy(address,coin->smartaddr); + else + { + bitcoin_addr2rmd160(taddr,&addrtype,rmd160,coinaddr); + bitcoin_address(address,coin->taddr,coin->pubtype,rmd160,20); + //printf("%s taddr.%d addrtype.%u %s -> %s [%c %c].%d\n",coin->symbol,taddr,addrtype,coinaddr,address,coinaddr[0],coinaddr[1],coinaddr[0] == 't' && (coinaddr[1] == '1' || coinaddr[1] == '3')); + } + 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(address,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,errs,height,count=0; uint64_t value,val; cJSON *item,*txobj; bits256 txid; @@ -642,66 +735,6 @@ int32_t LP_unspents_array(struct iguana_info *coin,char *coinaddr,cJSON *array) return(count); } -void LP_utxosetkey(uint8_t *key,bits256 txid,int32_t vout) -{ - memcpy(key,txid.bytes,sizeof(txid)); - memcpy(&key[sizeof(txid)],&vout,sizeof(vout)); -} - -struct LP_utxoinfo *_LP_utxofind(int32_t iambob,bits256 txid,int32_t vout) -{ - struct LP_utxoinfo *utxo=0; uint8_t key[sizeof(txid) + sizeof(vout)]; - LP_utxosetkey(key,txid,vout); - HASH_FIND(hh,G.LP_utxoinfos[iambob!=0],key,sizeof(key),utxo); - return(utxo); -} - -void _LP_utxo_delete(int32_t iambob,struct LP_utxoinfo *utxo) -{ - HASH_DELETE(hh,G.LP_utxoinfos[iambob],utxo); -} - -void _LP_utxo2_delete(int32_t iambob,struct LP_utxoinfo *utxo) -{ - HASH_DELETE(hh,G.LP_utxoinfos2[iambob],utxo); -} - -struct LP_utxoinfo *_LP_utxo2find(int32_t iambob,bits256 txid2,int32_t vout2) -{ - struct LP_utxoinfo *utxo=0; uint8_t key2[sizeof(txid2) + sizeof(vout2)]; - LP_utxosetkey(key2,txid2,vout2); - HASH_FIND(hh2,G.LP_utxoinfos2[iambob],key2,sizeof(key2),utxo); - return(utxo); -} - -struct LP_utxoinfo *LP_utxofind(int32_t iambob,bits256 txid,int32_t vout) -{ - struct LP_utxoinfo *utxo=0; - /*if ( iambob != 0 ) - { - printf("LP_utxofind deprecated iambob\n"); - return(0); - }*/ - portable_mutex_lock(&LP_utxomutex); - utxo = _LP_utxofind(iambob,txid,vout); - portable_mutex_unlock(&LP_utxomutex); - return(utxo); -} - -struct LP_utxoinfo *LP_utxo2find(int32_t iambob,bits256 txid2,int32_t vout2) -{ - struct LP_utxoinfo *utxo=0; - /*if ( iambob != 0 ) - { - printf("LP_utxo2find deprecated iambob\n"); - return(0); - }*/ - portable_mutex_lock(&LP_utxomutex); - utxo = _LP_utxo2find(iambob,txid2,vout2); - portable_mutex_unlock(&LP_utxomutex); - return(utxo); -} - struct LP_transaction *LP_transactionfind(struct iguana_info *coin,bits256 txid) { struct LP_transaction *tx; @@ -741,7 +774,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); @@ -798,12 +831,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"); @@ -823,13 +856,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); @@ -843,7 +886,7 @@ 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)) != 0 ) + else if ( (txobj= LP_gettx(symbol,txid,1)) != 0 ) { numconfirms = jint(txobj,"confirmations"); free_json(txobj); @@ -851,9 +894,10 @@ int32_t LP_numconfirms(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int } 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 ) @@ -964,6 +1008,23 @@ 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; cJSON *txobj; int32_t bypass = 0; char destaddr[64],destaddr2[64]; struct iguana_info *coin = LP_coinfind(symbol); @@ -989,8 +1050,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; @@ -999,38 +1058,16 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol strcpy(destaddr,destaddr2); if ( coin != 0 ) { - /*if ( coin->electrum != 0 ) - { - if ( (tx= LP_transactionfind(coin,txid)) != 0 && vout < tx->numvouts && tx->outpoints[vout].spendheight > 0 ) - { - //printf("txid spent\n"); - return(0); - } - if ( (tx= LP_transactionfind(coin,txid2)) != 0 && vout2 < tx->numvouts && tx->outpoints[vout2].spendheight > 0 ) - { - //printf("txid2 spent\n"); - return(0); - } - if ( (up= LP_address_utxofind(coin,destaddr,txid,vout)) != 0 && up->spendheight > 0 ) - { - //printf("txid %s spentB\n",destaddr); - return(0); - } - if ( (up= LP_address_utxofind(coin,destaddr,txid2,vout2)) != 0 && up->spendheight > 0 ) - { - //printf("txid2 %s spentB\n",destaddr); - return(0); - } - } - else*/ - { - if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid,vout)) == 0 ) - return(0); - else free_json(txobj); - if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid2,vout2)) == 0 ) - return(0); - else free_json(txobj); - } + if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid,vout)) == 0 ) + return(0); + else free_json(txobj); + if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid2,vout2)) == 0 ) + return(0); + else free_json(txobj); + if ( LP_numconfirms(coin->symbol,destaddr,txid,vout,0) <= 0 ) + return(0); + if ( LP_numconfirms(coin->symbol,destaddr,txid2,vout2,0) <= 0 ) + return(0); } return(1); } @@ -1077,12 +1114,12 @@ 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_address_utxo *up; struct LP_utxoinfo *utxo; struct LP_transaction *tx; struct iguana_info *coin; + 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 ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 || (utxo= LP_utxo2find(iambob,txid,vout)) != 0 ) { if ( coin != 0 && (tx= LP_transactionfind(coin,txid)) != 0 ) { @@ -1095,7 +1132,7 @@ 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); diff --git a/iguana/exchanges/LP_utxos.c b/iguana/exchanges/LP_utxos.c deleted file mode 100644 index 90e0aafc8..000000000 --- a/iguana/exchanges/LP_utxos.c +++ /dev/null @@ -1,905 +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_isunspent(struct LP_utxoinfo *utxo) -{ - struct LP_address_utxo *up; struct _LP_utxoinfo u; struct iguana_info *coin; - if ( (coin= LP_coinfind(utxo->coin)) == 0 ) - return(0); - if ( (up= LP_address_utxofind(coin,utxo->coinaddr,utxo->payment.txid,utxo->payment.vout)) != 0 && up->spendheight > 0 ) - { - utxo->T.spentflag = up->spendheight; - return(0); - } - u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; - if ( (up= LP_address_utxofind(coin,utxo->coinaddr,u.txid,u.vout)) != 0 && up->spendheight > 0 ) - { - utxo->T.spentflag = up->spendheight; - return(0); - } - if ( utxo != 0 && utxo->T.spentflag == 0 && LP_isavailable(utxo) > 0 ) - return(1); - else return(0); -} - -struct LP_utxoinfo *LP_utxopairfind(int32_t iambob,bits256 txid,int32_t vout,bits256 txid2,int32_t vout2) -{ - struct LP_utxoinfo *utxo=0; struct _LP_utxoinfo u; - if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 ) - { - u = (iambob != 0) ? utxo->deposit : utxo->fee; - if (vout2 == u.vout && bits256_cmp(u.txid,txid2) == 0 ) - return(utxo); - } - return(0); -} - -struct LP_utxoinfo *LP_utxofinds(int32_t iambob,bits256 txid,int32_t vout,bits256 txid2,int32_t vout2) -{ - struct LP_utxoinfo *utxo; - if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 || (utxo= LP_utxofind(iambob,txid2,vout2)) != 0 || (utxo= LP_utxo2find(iambob,txid,vout)) != 0 || (utxo= LP_utxo2find(iambob,txid2,vout2)) != 0 ) - return(utxo); - else return(0); -} - -int32_t LP_utxoaddptrs(struct LP_utxoinfo *ptrs[],int32_t n,struct LP_utxoinfo *utxo) -{ - int32_t i; - for (i=0; i utxo->T.swappending ) - utxo->T.swappending = 0; - if ( utxo != 0 && utxo->T.swappending == 0 && utxo->S.swap == 0 ) - return(1); - else return(0); -} - -int32_t LP_utxocollisions(struct LP_utxoinfo *ptrs[],struct LP_utxoinfo *refutxo) -{ - int32_t iambob,n = 0; struct LP_utxoinfo *utxo; struct _LP_utxoinfo u; - if ( refutxo == 0 ) - return(0); - portable_mutex_lock(&LP_utxomutex); - for (iambob=0; iambob<=1; iambob++) - { - if ( (utxo= _LP_utxofind(iambob,refutxo->payment.txid,refutxo->payment.vout)) != 0 && utxo != refutxo ) - n = LP_utxoaddptrs(ptrs,n,utxo); - if ( (utxo= _LP_utxo2find(iambob,refutxo->payment.txid,refutxo->payment.vout)) != 0 && utxo != refutxo ) - n = LP_utxoaddptrs(ptrs,n,utxo); - u = (refutxo->iambob != 0) ? refutxo->deposit : refutxo->fee; - if ( (utxo= _LP_utxofind(iambob,u.txid,u.vout)) != 0 && utxo != refutxo ) - n = LP_utxoaddptrs(ptrs,n,utxo); - if ( (utxo= _LP_utxo2find(iambob,u.txid,u.vout)) != 0 && utxo != refutxo ) - n = LP_utxoaddptrs(ptrs,n,utxo); - } - portable_mutex_unlock(&LP_utxomutex); - if ( 0 && n > 0 ) - printf("LP_utxocollisions n.%d\n",n); - return(n); -} - -int32_t _LP_availableset(struct LP_utxoinfo *utxo) -{ - int32_t flag = 0; - if ( utxo != 0 ) - { - if ( bits256_nonz(utxo->S.otherpubkey) != 0 ) - flag = 1, memset(&utxo->S.otherpubkey,0,sizeof(utxo->S.otherpubkey)); - if ( utxo->S.swap != 0 ) - flag = 1, utxo->S.swap = 0; - if ( utxo->T.swappending != 0 ) - flag = 1, utxo->T.swappending = 0; - return(flag); - } - return(0); -} - -void _LP_unavailableset(struct LP_utxoinfo *utxo,bits256 otherpubkey) -{ - if ( utxo != 0 ) - { - utxo->T.swappending = (uint32_t)(time(NULL) + LP_RESERVETIME); - utxo->S.otherpubkey = otherpubkey; - } -} - -void LP_unavailableset(struct LP_utxoinfo *utxo,bits256 otherpubkey) -{ - struct LP_utxoinfo *ptrs[8]; int32_t i,n; struct _LP_utxoinfo u; - memset(ptrs,0,sizeof(ptrs)); - if ( (n= LP_utxocollisions(ptrs,utxo)) > 0 ) - { - for (i=0; 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_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); - /*if ( iambob != 0 && value2 < 9 * (satoshis >> 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 = (satoshis - txfee);*/ - char str[65],str2[65],dispflag = 0;//(iambob == 0); - if ( iambob == 0 && bits256_cmp(pubkey,G.LP_mypub25519) != 0 ) - { - printf("trying to add Alice utxo when not mine? %s/v%d\n",bits256_str(str,txid),vout); - return(0); - } - if ( 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); -} - -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,biggerval,value,total = 0; int64_t targetval; - 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); - array = LP_listunspent(coin->symbol,coin->smartaddr); - if ( array != 0 ) - { - txfee = LP_txfeecalc(coin,0,0); - if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) - { - coin->numutxos = n; - //printf("LP_privkey_init %s %d\n",coin->symbol,n); - for (iambob=0; iambob<=1; iambob++) - { - if ( iambob == 0 ) - values = calloc(n,sizeof(*values)); - else memset(values,0,n * sizeof(*values)); - 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 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(coin) > 0 ) - { - LP_listunspent_issue(coin->symbol,coin->smartaddr,0); - if ( (retjson= LP_importprivkey(coin->symbol,tmpstr,coin->smartaddr,-1)) != 0 ) - { - if ( jobj(retjson,"error") != 0 ) - { - 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 ( LP_privkey_init(pubsock,coin,G.LP_privkey,G.LP_mypub25519) == 0 && (LP_rand() % 10) == 0 ) - { - //LP_postutxos(coin->symbol,coin->smartaddr); - } - } - } -} - -int32_t LP_passphrase_init(char *passphrase,char *gui) -{ - static void *ctx; int32_t iambob,counter; struct LP_utxoinfo *utxo,*tmp; - if ( ctx == 0 ) - ctx = bitcoin_ctx(); - if ( G.LP_pendingswaps != 0 ) - return(-1); - G.initializing = 1; - if ( gui == 0 ) - gui = "cli"; - counter = G.USERPASS_COUNTER; - while ( G.waiting == 0 ) - { - printf("waiting for G.waiting\n"); - sleep(5); - } - for (iambob=0; iambob<2; iambob++) - { - if ( G.LP_utxoinfos[iambob] != 0 ) - { - HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,tmp) - { - HASH_DELETE(hh,G.LP_utxoinfos[iambob],utxo); - //free(utxo); - } - } - if ( G.LP_utxoinfos2[iambob] != 0 ) - { - G.LP_utxoinfos2[iambob] = 0; - /*HASH_ITER(hh,G.LP_utxoinfos2[iambob],utxo,tmp) - { - HASH_DELETE(hh,G.LP_utxoinfos2[iambob],utxo); - free(utxo); - }*/ - } - } - memset(&G,0,sizeof(G)); - LP_privkey_updates(ctx,LP_mypubsock,passphrase); - init_hexbytes_noT(G.LP_myrmd160str,G.LP_myrmd160,20); - G.LP_sessionid = (uint32_t)time(NULL); - safecopy(G.gui,gui,sizeof(G.gui)); - G.USERPASS_COUNTER = counter; - G.initializing = 0; - return(0); -} - - diff --git a/iguana/exchanges/auto_chipsbtc b/iguana/exchanges/auto_chipsbtc new file mode 100755 index 000000000..e4b2490cc --- /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.05,\"refbase\":\"chips\",\"refrel\":\"coinmarketcap\"}" diff --git a/iguana/exchanges/auto_chipskmd b/iguana/exchanges/auto_chipskmd new file mode 100755 index 000000000..aee6c0548 --- /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.05,\"refbase\":\"chips\",\"refrel\":\"coinmarketcap\"}" diff --git a/iguana/exchanges/autofill b/iguana/exchanges/autofill deleted file mode 100755 index b0724a9db..000000000 --- a/iguana/exchanges/autofill +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -source userpass -curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autofill\",\"base\":\"KMD\",\"rel\":\"BTC\",\"price\":0.0005,\"relvolume\":0.1}" diff --git a/iguana/exchanges/autotrade b/iguana/exchanges/autotrade deleted file mode 100755 index 72e14f84a..000000000 --- a/iguana/exchanges/autotrade +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -source userpass -curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autotrade\",\"base\":\"REVS\",\"rel\":\"KMD\",\"relvolume\":1.01,\"price\":1.234}" diff --git a/iguana/exchanges/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/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 9b5789e13..0df7c558e 100644 --- a/iguana/exchanges/coins +++ b/iguana/exchanges/coins @@ -1,4 +1,3 @@ -export coins="[{\"coin\":\"QTUM\",\"name\":\"qtum\",\"rpcport\":3889,\"pubtype\":58,\"p2shtype\":50,\"wiftype\":128,\"txfee\":400000}, {\"coin\":\"PURA\",\"name\":\"pura\",\"rpcport\":55555,\"pubtype\":55,\"p2shtype\":16,\"wiftype\":150,\"txfee\":10000}, {\"coin\":\"DSR\",\"name\":\"desire\",\"confpath\":\"${HOME#}/.desirecore/desire.conf\",\"rpcport\":9918,\"pubtype\":30,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"MNZ\",\"asset\":\"MNZ\",\"rpcport\":14337},{\"coin\":\"BTCZ\",\"name\":\"bitcoinz\",\"rpcport\":1979,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"MAGA\",\"name\":\"magacoin\",\"rpcport\":5332,\"pubtype\":23,\"p2shtype\":50,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"BSD\",\"name\":\"bitsend\",\"rpcport\":8800,\"pubtype\":102,\"p2shtype\":5,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"IOP\",\"name\":\"IoP\",\"rpcport\":8337,\"pubtype\":117,\"p2shtype\":174,\"wiftype\":49,\"txfee\":10000}, {\"coin\":\"BLOCK\",\"name\":\"blocknetdx\",\"rpcport\":41414,\"pubtype\":26,\"p2shtype\":28,\"wiftype\":154,\"txfee\":10000}, {\"coin\":\"CHIPS\", \"name\": \"chips\", \"rpcport\":57776,\"pubtype\":60, \"p2shtype\":85, \"wiftype\":188, \"txfee\":10000}, {\"coin\":\"888\",\"name\":\"octocoin\",\"rpcport\":22888,\"pubtype\":18,\"p2shtype\":5,\"wiftype\":176,\"txfee\":2000000}, {\"coin\":\"ARG\",\"name\":\"argentum\",\"rpcport\":13581,\"pubtype\":23,\"p2shtype\":5,\"wiftype\":151,\"txfee\":50000}, {\"coin\":\"GLT\",\"name\":\"globaltoken\",\"rpcport\":9320,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":166,\"txfee\":10000}, {\"coin\":\"ZER\",\"name\":\"zero\",\"rpcport\":23801,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"HODLC\",\"name\":\"hodlcoin\",\"rpcport\":11989,\"pubtype\":40,\"p2shtype\":5,\"wiftype\":168,\"txfee\":5000}, {\"coin\":\"UIS\",\"name\":\"unitus\",\"rpcport\":50604,\"pubtype\":68,\"p2shtype\":10,\"wiftype\":132,\"txfee\":2000000}, {\"coin\":\"CRW\",\"name\":\"crown\",\"rpcport\":9341,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"HUC\",\"name\":\"huntercoin\",\"rpcport\":8399,\"pubtype\":40,\"p2shtype\":13,\"wiftype\":168,\"txfee\":100000}, {\"coin\":\"PIVX\",\"name\":\"pivx\",\"rpcport\":51473,\"pubtype\":30,\"p2shtype\":13,\"wiftype\":212,\"txfee\":10000}, {\"coin\":\"BDL\",\"name\":\"bitdeal\",\"rpcport\":9332,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"ARC\",\"name\":\"arcticcoin\",\"confpath\":\"${HOME#}/.arcticcore/arcticcoin.conf\",\"rpcport\":7208,\"pubtype\":23,\"p2shtype\":8,\"wiftype\":176,\"txfee\":10000}, {\"coin\":\"ZCL\",\"name\":\"zclassic\",\"rpcport\":8023,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"VIA\",\"name\":\"viacoin\",\"rpcport\":5222,\"pubtype\":71,\"p2shtype\":33,\"wiftype\":199,\"txfee\":100000}, {\"coin\":\"ERC\",\"name\":\"europecoin\",\"rpcport\":11989,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":168,\"txfee\":10000},{\"coin\":\"FAIR\",\"name\":\"faircoin\",\"confpath\":\"${HOME#}/.faircoin2/faircoin.conf\",\"rpcport\":40405,\"pubtype\":95,\"p2shtype\":36,\"wiftype\":223,\"txfee\":1000000}, {\"coin\":\"FLO\",\"name\":\"florincoin\",\"rpcport\":7313,\"pubtype\":35,\"p2shtype\":8,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"SXC\",\"name\":\"sexcoin\",\"rpcport\":9561,\"pubtype\":62,\"p2shtype\":5,\"wiftype\":190,\"txfee\":100000}, {\"coin\":\"CREA\",\"name\":\"creativecoin\",\"rpcport\":17711,\"pubtype\":28,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"TRC\",\"name\":\"terracoin\",\"confpath\":\"${HOME#}/.terracoincore/terracoin.conf\",\"rpcport\":13332,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"BTA\",\"name\":\"bata\",\"rpcport\":5493,\"pubtype\":25,\"p2shtype\":5,\"wiftype\":188,\"txfee\":100000}, {\"coin\":\"SMC\",\"name\":\"smartcoin\",\"rpcport\":58583,\"pubtype\":63,\"p2shtype\":5,\"wiftype\":191,\"txfee\":1000000}, {\"coin\":\"NMC\",\"name\":\"namecoin\",\"rpcport\":8336,\"pubtype\":52,\"p2shtype\":13,\"wiftype\":180,\"txfee\":100000}, {\"coin\":\"NAV\",\"name\":\"navcoin\",\"isPoS\":1,\"confpath\":\"${HOME#}/.navcoin4/navcoin.conf\",\"rpcport\":44444,\"pubtype\":53,\"p2shtype\":85,\"wiftype\":150,\"txfee\":10000}, {\"coin\":\"MOON\",\"name\":\"Mooncoin\",\"rpcport\":44663,\"pubtype\":3,\"p2shtype\":22,\"wiftype\":131,\"txfee\":100000}, {\"coin\":\"EMC2\",\"name\":\"einsteinium\",\"rpcport\":41879,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"SYS\",\"name\":\"syscoin\",\"rpcport\":8370,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"I0C\",\"name\":\"i0coin\",\"rpcport\":7332,\"pubtype\":105,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"DASH\",\"confpath\":\"${HOME#}/.dashcore/dash.conf\",\"name\":\"dashcore\",\"rpcport\":9998,\"pubtype\":76,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"STRAT\", \"name\": \"stratis\", \"active\":0, \"rpcport\":16174,\"pubtype\":63, \"p2shtype\":125, \"wiftype\":191, \"txfee\":10000}, {\"confpath\":\"${HOME#}/.muecore/mue.conf\",\"coin\":\"MUE\",\"name\":\"muecore\",\"rpcport\":29683,\"pubtype\":16,\"p2shtype\":76,\"wiftype\":126,\"txfee\":10000}, {\"coin\":\"MONA\",\"name\":\"monacoin\",\"rpcport\":9402,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"XMY\",\"name\":\"myriadcoin\",\"rpcport\":10889,\"pubtype\":50,\"p2shtype\":9,\"wiftype\":178,\"txfee\":5000}, {\"coin\":\"MAC\",\"name\":\"machinecoin\",\"rpcport\":40332,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":178,\"txfee\":50000}, {\"coin\":\"BTX\",\"name\":\"bitcore\",\"rpcport\":8556,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":50000}, {\"coin\":\"XRE\",\"name\":\"revolvercoin\",\"rpcport\":8775,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"LBC\",\"name\":\"lbrycrd\",\"rpcport\":9245,\"pubtype\":85,\"p2shtype\":122,\"wiftype\":28,\"txfee\":1000}, {\"coin\":\"SIB\",\"name\":\"sibcoin\",\"rpcport\":1944,\"pubtype\":63,\"p2shtype\":40,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"VTC\", \"name\":\"vertcoin\", \"rpcport\":5888, \"pubtype\":71, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000 }, {\"coin\":\"REVS\",\"active\":0, \"asset\":\"REVS\",\"rpcport\":10196}, {\"coin\":\"JUMBLR\",\"active\":0, \"asset\":\"JUMBLR\",\"rpcport\":15106}, {\"coin\":\"DOGE\",\"name\":\"dogecoin\",\"rpcport\":22555,\"pubtype\":30,\"p2shtype\":22,\"wiftype\":158,\"txfee\":100000000}, {\"coin\":\"HUSH\",\"name\":\"hush\",\"rpcport\":8822,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000 }, {\"active\":0,\"coin\":\"ZEC\",\"name\":\"zcash\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000 }, {\"coin\":\"DGB\",\"name\":\"digibyte\",\"rpcport\":14022,\"pubtype\":30,\"p2shtype\":5,\"wiftype\":128,\"txfee\":100000}, {\"coin\":\"ZET\", \"name\":\"zetacoin\", \"pubtype\":80, \"p2shtype\":9,\"rpcport\":8332, \"wiftype\":224, \"txfee\":10000}, {\"coin\":\"GAME\", \"rpcport\":40001, \"name\":\"gamecredits\", \"pubtype\":38, \"p2shtype\":5, \"wiftype\":166, \"txfee\":100000}, {\"coin\":\"LTC\", \"name\":\"litecoin\", \"rpcport\":9332, \"pubtype\":48, \"p2shtype\":5, \"wiftype\":176, \"txfee\":100000 }, {\"coin\":\"SUPERNET\",\"asset\":\"SUPERNET\",\"rpcport\":11341}, {\"coin\":\"WLC\",\"asset\":\"WLC\",\"rpcport\":12167}, {\"coin\":\"PANGEA\",\"asset\":\"PANGEA\",\"rpcport\":14068}, {\"coin\":\"DEX\",\"asset\":\"DEX\",\"rpcport\":11890}, {\"coin\":\"BET\",\"asset\":\"BET\",\"rpcport\":14250}, {\"coin\":\"CRYPTO\",\"asset\":\"CRYPTO\",\"rpcport\":8516}, {\"coin\":\"HODL\",\"asset\":\"HODL\",\"rpcport\":14431}, {\"coin\":\"SHARK\",\"asset\":\"SHARK\",\"rpcport\":10114}, {\"coin\":\"BOTS\",\"asset\":\"BOTS\",\"rpcport\":11964}, {\"coin\":\"MGW\",\"asset\":\"MGW\",\"rpcport\":12386}, {\"coin\":\"COQUI\",\"asset\":\"COQUI\",\"rpcport\":14276}, {\"coin\":\"KV\",\"asset\":\"KV\",\"rpcport\":8299}, {\"coin\":\"CEAL\",\"asset\":\"CEAL\",\"rpcport\":11116}, {\"coin\":\"MESH\",\"asset\":\"MESH\",\"rpcport\":9455}]" +export coins="[{\"coin\":\"XMCC\",\"name\":\"monoeci\",\"confpath\":\"${HOME#}/.monoeciCore/monoeci.conf\",\"rpcport\":24156,\"pubtype\":50,\"p2shtype\":73,\"wiftype\":77,\"txfee\":10000}, {\"coin\":\"BTCH\",\"asset\":\"BTCH\",\"rpcport\":8800},{\"coin\":\"ETOMIC\",\"asset\":\"ETOMIC\",\"rpcport\":10271},{\"coin\":\"AXO\",\"asset\":\"AXO\",\"rpcport\":12927},{\"coin\":\"CRC\",\"name\":\"crowdcoin\",\"confpath\":\"${HOME#}/.crowdcoincore/crowdcoin.conf\",\"rpcport\":9998,\"pubtype\":28,\"p2shtype\":88,\"wiftype\":0,\"txfee\":10000}, {\"coin\":\"VOT\",\"name\":\"votecoin\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"INN\",\"name\":\"innova\",\"confpath\":\"${HOME#}/.innovacore/innova.conf\",\"rpcport\":8818,\"pubtype\":102,\"p2shtype\":20,\"wiftype\":195,\"txfee\":10000}, {\"coin\":\"MOON\",\"name\":\"mooncoin\",\"rpcport\":44663,\"pubtype\":3,\"p2shtype\":22,\"wiftype\":131,\"txfee\":100000}, {\"coin\":\"CRW\",\"name\":\"crown\",\"rpcport\":9341,\"pubtype\":0,\"p2shtype\":28,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"EFL\",\"name\":\"egulden\",\"confpath\":\"${HOME#}/.egulden/coin.conf\",\"rpcport\":21015,\"pubtype\":48,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"GBX\",\"name\":\"gobyte\",\"confpath\":\"${HOME#}/.gobytecore/gobyte.conf\",\"rpcport\":12454,\"pubtype\":38,\"p2shtype\":10,\"wiftype\":198,\"txfee\":10000}, {\"coin\":\"BCO\",\"name\":\"bridgecoin\",\"rpcport\":6332,\"pubtype\":27,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"BLK\",\"name\":\"blackcoin\",\"confpath\":\"${HOME#}/.lore/blackcoin.conf\",\"isPoS\":1,\"rpcport\":15715,\"pubtype\":25,\"p2shtype\":85,\"wiftype\":153,\"txfee\":100000}, {\"coin\":\"BTG\",\"name\":\"bitcoingold\",\"rpcport\":8332,\"pubtype\":38,\"p2shtype\":23,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"BCH\",\"name\":\"bch\",\"rpcport\":33333,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"ABY\",\"name\":\"applebyte\",\"rpcport\":8607,\"pubtype\":23,\"p2shtype\":5,\"wiftype\":151,\"txfee\":100000}, {\"coin\":\"STAK\",\"name\":\"straks\",\"rpcport\":7574,\"pubtype\":63,\"p2shtype\":5,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"XZC\",\"name\":\"zcoin\",\"rpcport\":8888,\"pubtype\":82,\"p2shtype\":7,\"wiftype\":210,\"txfee\":10000}, {\"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\":\"HUC\",\"name\":\"huntercoin\",\"rpcport\":8399,\"pubtype\":40,\"p2shtype\":13,\"wiftype\":168,\"txfee\":100000}, {\"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\":\"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\":100000}, {\"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}, +#{\"coin\":\"PIVX\",\"name\":\"pivx\",\"rpcport\":51473,\"pubtype\":30,\"p2shtype\":13,\"wiftype\":212,\"txfee\":10000}, diff --git a/iguana/exchanges/coins.json b/iguana/exchanges/coins.json index 320b6ccaf..6c61ab8af 100644 --- a/iguana/exchanges/coins.json +++ b/iguana/exchanges/coins.json @@ -1,4 +1 @@ -[{\"coin\":\"QTUM\",\"name\":\"qtum\",\"rpcport\":3889,\"pubtype\":58,\"p2shtype\":50,\"wiftype\":128,\"txfee\":400000}, {\"coin\":\"PURA\",\"name\":\"pura\",\"rpcport\":55555,\"pubtype\":55,\"p2shtype\":16,\"wiftype\":150,\"txfee\":10000}, {\"coin\":\"DSR\",\"name\":\"desire\",\"confpath\":\"${HOME#}/.desirecore/desire.conf\",\"rpcport\":9918,\"pubtype\":30,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"MNZ\",\"asset\":\"MNZ\",\"rpcport\":14337},{\"coin\":\"BTCZ\",\"name\":\"bitcoinz\",\"rpcport\":1979,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"MAGA\",\"name\":\"magacoin\",\"rpcport\":5332,\"pubtype\":23,\"p2shtype\":50,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"BSD\",\"name\":\"bitsend\",\"rpcport\":8800,\"pubtype\":102,\"p2shtype\":5,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"IOP\",\"name\":\"IoP\",\"rpcport\":8337,\"pubtype\":117,\"p2shtype\":174,\"wiftype\":49,\"txfee\":10000}, {\"coin\":\"BLOCK\",\"name\":\"blocknetdx\",\"rpcport\":41414,\"pubtype\":26,\"p2shtype\":28,\"wiftype\":154,\"txfee\":10000}, {\"coin\":\"CHIPS\", \"name\": \"chips\", \"rpcport\":57776,\"pubtype\":60, \"p2shtype\":85, \"wiftype\":188, \"txfee\":10000}, {\"coin\":\"888\",\"name\":\"octocoin\",\"rpcport\":22888,\"pubtype\":18,\"p2shtype\":5,\"wiftype\":176,\"txfee\":2000000}, {\"coin\":\"ARG\",\"name\":\"argentum\",\"rpcport\":13581,\"pubtype\":23,\"p2shtype\":5,\"wiftype\":151,\"txfee\":50000}, {\"coin\":\"GLT\",\"name\":\"globaltoken\",\"rpcport\":9320,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":166,\"txfee\":10000}, {\"coin\":\"ZER\",\"name\":\"zero\",\"rpcport\":23801,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"HODLC\",\"name\":\"hodlcoin\",\"rpcport\":11989,\"pubtype\":40,\"p2shtype\":5,\"wiftype\":168,\"txfee\":5000}, {\"coin\":\"UIS\",\"name\":\"unitus\",\"rpcport\":50604,\"pubtype\":68,\"p2shtype\":10,\"wiftype\":132,\"txfee\":2000000}, {\"coin\":\"CRW\",\"name\":\"crown\",\"rpcport\":9341,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"HUC\",\"name\":\"huntercoin\",\"rpcport\":8399,\"pubtype\":40,\"p2shtype\":13,\"wiftype\":168,\"txfee\":100000}, {\"coin\":\"PIVX\",\"name\":\"pivx\",\"rpcport\":51473,\"pubtype\":30,\"p2shtype\":13,\"wiftype\":212,\"txfee\":10000}, {\"coin\":\"BDL\",\"name\":\"bitdeal\",\"rpcport\":9332,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"ARC\",\"name\":\"arcticcoin\",\"confpath\":\"${HOME#}/.arcticcore/arcticcoin.conf\",\"rpcport\":7208,\"pubtype\":23,\"p2shtype\":8,\"wiftype\":176,\"txfee\":10000}, {\"coin\":\"ZCL\",\"name\":\"zclassic\",\"rpcport\":8023,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"VIA\",\"name\":\"viacoin\",\"rpcport\":5222,\"pubtype\":71,\"p2shtype\":33,\"wiftype\":199,\"txfee\":100000}, {\"coin\":\"ERC\",\"name\":\"europecoin\",\"rpcport\":11989,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":168,\"txfee\":10000},{\"coin\":\"FAIR\",\"name\":\"faircoin\",\"confpath\":\"${HOME#}/.faircoin2/faircoin.conf\",\"rpcport\":40405,\"pubtype\":95,\"p2shtype\":36,\"wiftype\":223,\"txfee\":1000000}, {\"coin\":\"FLO\",\"name\":\"florincoin\",\"rpcport\":7313,\"pubtype\":35,\"p2shtype\":8,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"SXC\",\"name\":\"sexcoin\",\"rpcport\":9561,\"pubtype\":62,\"p2shtype\":5,\"wiftype\":190,\"txfee\":100000}, {\"coin\":\"CREA\",\"name\":\"creativecoin\",\"rpcport\":17711,\"pubtype\":28,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"TRC\",\"name\":\"terracoin\",\"confpath\":\"${HOME#}/.terracoincore/terracoin.conf\",\"rpcport\":13332,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"BTA\",\"name\":\"bata\",\"rpcport\":5493,\"pubtype\":25,\"p2shtype\":5,\"wiftype\":188,\"txfee\":100000}, {\"coin\":\"SMC\",\"name\":\"smartcoin\",\"rpcport\":58583,\"pubtype\":63,\"p2shtype\":5,\"wiftype\":191,\"txfee\":1000000}, {\"coin\":\"NMC\",\"name\":\"namecoin\",\"rpcport\":8336,\"pubtype\":52,\"p2shtype\":13,\"wiftype\":180,\"txfee\":100000}, {\"coin\":\"NAV\",\"name\":\"navcoin\",\"isPoS\":1,\"confpath\":\"${HOME#}/.navcoin4/navcoin.conf\",\"rpcport\":44444,\"pubtype\":53,\"p2shtype\":85,\"wiftype\":150,\"txfee\":10000}, {\"coin\":\"MOON\",\"name\":\"Mooncoin\",\"rpcport\":44663,\"pubtype\":3,\"p2shtype\":22,\"wiftype\":131,\"txfee\":100000}, {\"coin\":\"EMC2\",\"name\":\"einsteinium\",\"rpcport\":41879,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"SYS\",\"name\":\"syscoin\",\"rpcport\":8370,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"I0C\",\"name\":\"i0coin\",\"rpcport\":7332,\"pubtype\":105,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"DASH\",\"confpath\":\"${HOME#}/.dashcore/dash.conf\",\"name\":\"dashcore\",\"rpcport\":9998,\"pubtype\":76,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"STRAT\", \"name\": \"stratis\", \"active\":0, \"rpcport\":16174,\"pubtype\":63, \"p2shtype\":125, \"wiftype\":191, \"txfee\":10000}, {\"confpath\":\"${HOME#}/.muecore/mue.conf\",\"coin\":\"MUE\",\"name\":\"muecore\",\"rpcport\":29683,\"pubtype\":16,\"p2shtype\":76,\"wiftype\":126,\"txfee\":10000}, {\"coin\":\"MONA\",\"name\":\"monacoin\",\"rpcport\":9402,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"XMY\",\"name\":\"myriadcoin\",\"rpcport\":10889,\"pubtype\":50,\"p2shtype\":9,\"wiftype\":178,\"txfee\":5000}, {\"coin\":\"MAC\",\"name\":\"machinecoin\",\"rpcport\":40332,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":178,\"txfee\":50000}, {\"coin\":\"BTX\",\"name\":\"bitcore\",\"rpcport\":8556,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":50000}, {\"coin\":\"XRE\",\"name\":\"revolvercoin\",\"rpcport\":8775,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"LBC\",\"name\":\"lbrycrd\",\"rpcport\":9245,\"pubtype\":85,\"p2shtype\":122,\"wiftype\":28,\"txfee\":1000}, {\"coin\":\"SIB\",\"name\":\"sibcoin\",\"rpcport\":1944,\"pubtype\":63,\"p2shtype\":40,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"VTC\", \"name\":\"vertcoin\", \"rpcport\":5888, \"pubtype\":71, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000 }, {\"coin\":\"REVS\",\"active\":0, \"asset\":\"REVS\",\"rpcport\":10196}, {\"coin\":\"JUMBLR\",\"active\":0, \"asset\":\"JUMBLR\",\"rpcport\":15106}, {\"coin\":\"DOGE\",\"name\":\"dogecoin\",\"rpcport\":22555,\"pubtype\":30,\"p2shtype\":22,\"wiftype\":158,\"txfee\":100000000}, {\"coin\":\"HUSH\",\"name\":\"hush\",\"rpcport\":8822,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000 }, {\"active\":0,\"coin\":\"ZEC\",\"name\":\"zcash\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000 }, {\"coin\":\"DGB\",\"name\":\"digibyte\",\"rpcport\":14022,\"pubtype\":30,\"p2shtype\":5,\"wiftype\":128,\"txfee\":100000}, {\"coin\":\"ZET\", \"name\":\"zetacoin\", \"pubtype\":80, \"p2shtype\":9,\"rpcport\":8332, \"wiftype\":224, \"txfee\":10000}, {\"coin\":\"GAME\", \"rpcport\":40001, \"name\":\"gamecredits\", \"pubtype\":38, \"p2shtype\":5, \"wiftype\":166, \"txfee\":100000}, {\"coin\":\"LTC\", \"name\":\"litecoin\", \"rpcport\":9332, \"pubtype\":48, \"p2shtype\":5, \"wiftype\":176, \"txfee\":100000 }, {\"coin\":\"SUPERNET\",\"asset\":\"SUPERNET\",\"rpcport\":11341}, {\"coin\":\"WLC\",\"asset\":\"WLC\",\"rpcport\":12167}, {\"coin\":\"PANGEA\",\"asset\":\"PANGEA\",\"rpcport\":14068}, {\"coin\":\"DEX\",\"asset\":\"DEX\",\"rpcport\":11890}, {\"coin\":\"BET\",\"asset\":\"BET\",\"rpcport\":14250}, {\"coin\":\"CRYPTO\",\"asset\":\"CRYPTO\",\"rpcport\":8516}, {\"coin\":\"HODL\",\"asset\":\"HODL\",\"rpcport\":14431}, {\"coin\":\"SHARK\",\"asset\":\"SHARK\",\"rpcport\":10114}, {\"coin\":\"BOTS\",\"asset\":\"BOTS\",\"rpcport\":11964}, {\"coin\":\"MGW\",\"asset\":\"MGW\",\"rpcport\":12386}, {\"coin\":\"COQUI\",\"asset\":\"COQUI\",\"rpcport\":14276}, {\"coin\":\"KV\",\"asset\":\"KV\",\"rpcport\":8299}, {\"coin\":\"CEAL\",\"asset\":\"CEAL\",\"rpcport\":11116}, {\"coin\":\"MESH\",\"asset\":\"MESH\",\"rpcport\":9455}]" -#, {\"coin\":\"AUD\",\"asset\":\"AUD\",\"rpcport\":8045}, {\"coin\":\"BGN\",\"asset\":\"BGN\",\"rpcport\":9110}, {\"coin\":\"CAD\",\"asset\":\"CAD\",\"rpcport\":8720}, {\"coin\":\"CHF\",\"asset\":\"CHF\",\"rpcport\":15312}, {\"coin\":\"CNY\",\"asset\":\"CNY\",\"rpcport\":10384}, {\"coin\":\"CZK\",\"asset\":\"CZK\",\"rpcport\":9482}, {\"coin\":\"DKK\",\"asset\":\"DKK\",\"rpcport\":13830}, {\"coin\":\"EUR\",\"asset\":\"EUR\",\"rpcport\":8065}, {\"coin\":\"GBP\",\"asset\":\"GBP\",\"rpcport\":11505}, {\"coin\":\"HKD\",\"asset\":\"HKD\",\"rpcport\":15409}, {\"coin\":\"HRK\",\"asset\":\"HRK\",\"rpcport\":12617}, {\"coin\":\"HUF\",\"asset\":\"HUF\",\"rpcport\":13699}, {\"coin\":\"IDR\",\"asset\":\"IDR\",\"rpcport\":14459}, {\"coin\":\"ILS\",\"asset\":\"ILS\",\"rpcport\":14638}, {\"coin\":\"INR\",\"asset\":\"INR\",\"rpcport\":10536}, {\"coin\":\"JPY\",\"asset\":\"JPY\",\"rpcport\":13145}, {\"coin\":\"KRW\",\"asset\":\"KRW\",\"rpcport\":14020}, {\"coin\":\"MXN\",\"asset\":\"MXN\",\"rpcport\":13970}, {\"coin\":\"MYR\",\"asset\":\"MYR\",\"rpcport\":10688}, {\"coin\":\"NOK\",\"asset\":\"NOK\",\"rpcport\":11588}, {\"coin\":\"NZD\",\"asset\":\"NZD\",\"rpcport\":10915}, {\"coin\":\"PHP\",\"asset\":\"PHP\",\"rpcport\":11181}, {\"coin\":\"PLN\",\"asset\":\"PLN\",\"rpcport\":13493}, {\"coin\":\"BRL\",\"asset\":\"BRL\",\"rpcport\":9914}, {\"coin\":\"RON\",\"asset\":\"RON\",\"rpcport\":8675}, {\"coin\":\"RUB\",\"asset\":\"RUB\",\"rpcport\":8199}, {\"coin\":\"SEK\",\"asset\":\"SEK\",\"rpcport\":11447}, {\"coin\":\"SGD\",\"asset\":\"SGD\",\"rpcport\":14475}, {\"coin\":\"THB\",\"asset\":\"THB\",\"rpcport\":11847}, {\"coin\":\"TRY\",\"asset\":\"TRY\",\"rpcport\":13924}, {\"coin\":\"USD\",\"asset\":\"USD\",\"rpcport\":13967}, {\"coin\":\"ZAR\",\"asset\":\"ZAR\",\"rpcport\":15160}] -#{\"coin\":\"ZEN\",\"name\":\"zen\",\"rpcport\":8231,\"pubtype\":137,\"taddr\":32,\"p2shtype\":150,\"wiftype\":128,\"txfee\":10000}, -#{\"coin\":\"BLK\",\"name\":\"blackcoin\",\"rpcport\":15715,\"pubtype\":25,\"p2shtype\":85,\"wiftype\":153,\"txfee\":10000}, +[{\"coin\":\"XMCC\",\"name\":\"monoeci\",\"confpath\":\"${HOME#}/.monoeciCore/monoeci.conf\",\"rpcport\":24156,\"pubtype\":50,\"p2shtype\":73,\"wiftype\":77,\"txfee\":10000}, {\"coin\":\"BTCH\",\"asset\":\"BTCH\",\"rpcport\":8800},{\"coin\":\"ETOMIC\",\"asset\":\"ETOMIC\",\"rpcport\":10271},{\"coin\":\"AXO\",\"asset\":\"AXO\",\"rpcport\":12927},{\"coin\":\"CRC\",\"name\":\"crowdcoin\",\"confpath\":\"${HOME#}/.crowdcoincore/crowdcoin.conf\",\"rpcport\":9998,\"pubtype\":28,\"p2shtype\":88,\"wiftype\":0,\"txfee\":10000}, {\"coin\":\"VOT\",\"name\":\"votecoin\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"INN\",\"name\":\"innova\",\"confpath\":\"${HOME#}/.innovacore/innova.conf\",\"rpcport\":8818,\"pubtype\":102,\"p2shtype\":20,\"wiftype\":195,\"txfee\":10000}, {\"coin\":\"MOON\",\"name\":\"mooncoin\",\"rpcport\":44663,\"pubtype\":3,\"p2shtype\":22,\"wiftype\":131,\"txfee\":100000}, {\"coin\":\"CRW\",\"name\":\"crown\",\"rpcport\":9341,\"pubtype\":0,\"p2shtype\":28,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"EFL\",\"name\":\"egulden\",\"confpath\":\"${HOME#}/.egulden/coin.conf\",\"rpcport\":21015,\"pubtype\":48,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"GBX\",\"name\":\"gobyte\",\"confpath\":\"${HOME#}/.gobytecore/gobyte.conf\",\"rpcport\":12454,\"pubtype\":38,\"p2shtype\":10,\"wiftype\":198,\"txfee\":10000}, {\"coin\":\"BCO\",\"name\":\"bridgecoin\",\"rpcport\":6332,\"pubtype\":27,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"BLK\",\"name\":\"blackcoin\",\"confpath\":\"${HOME#}/.lore/blackcoin.conf\",\"isPoS\":1,\"rpcport\":15715,\"pubtype\":25,\"p2shtype\":85,\"wiftype\":153,\"txfee\":100000}, {\"coin\":\"BTG\",\"name\":\"bitcoingold\",\"rpcport\":8332,\"pubtype\":38,\"p2shtype\":23,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"BCH\",\"name\":\"bch\",\"rpcport\":33333,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"ABY\",\"name\":\"applebyte\",\"rpcport\":8607,\"pubtype\":23,\"p2shtype\":5,\"wiftype\":151,\"txfee\":100000}, {\"coin\":\"STAK\",\"name\":\"straks\",\"rpcport\":7574,\"pubtype\":63,\"p2shtype\":5,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"XZC\",\"name\":\"zcoin\",\"rpcport\":8888,\"pubtype\":82,\"p2shtype\":7,\"wiftype\":210,\"txfee\":10000}, {\"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\":\"HUC\",\"name\":\"huntercoin\",\"rpcport\":8399,\"pubtype\":40,\"p2shtype\":13,\"wiftype\":168,\"txfee\":100000}, {\"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\":\"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\":100000}, {\"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}] 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..08da14bf7 100755 --- a/iguana/exchanges/enable +++ b/iguana/exchanges/enable @@ -1,5 +1,18 @@ #!/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\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"HUSH\",\"ipaddr\":\"173.212.225.176\",\"port\":50013}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"BTCH\",\"ipaddr\":\"electrum1.cipig.net\",\"port\":10020}" + 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/get_supernet b/iguana/exchanges/get_supernet new file mode 100755 index 000000000..2d43c6ba9 --- /dev/null +++ b/iguana/exchanges/get_supernet @@ -0,0 +1,15 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"REVS\",\"rel\":\"KMD\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"CHIPS\",\"rel\":\"KMD\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"KMD\",\"rel\":\"BTC\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"SUPERNET\",\"rel\":\"KMD\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"CRYPTO\",\"rel\":\"KMD\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"DEX\",\"rel\":\"KMD\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"BOTS\",\"rel\":\"KMD\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"BET\",\"rel\":\"KMD\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"HODL\",\"rel\":\"KMD\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"MSHARK\",\"rel\":\"KMD\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"MGW\",\"rel\":\"KMD\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"PANGEA\",\"rel\":\"KMD\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"JUMBLR\",\"rel\":\"KMD\"}" 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 efb2c7a2e..6f5c28723 100755 --- a/iguana/exchanges/install +++ b/iguana/exchanges/install @@ -1,5 +1,5 @@ #!/bin/bash -cp invreset sendrawtransaction processfiles stop millis mnzservers bot_buy bot_list bot_statuslist bot_pause bot_resume bot_sell bot_settings bot_status bot_stop guistats pubkeystats pendings coinswaps baserelswaps setpassphrase notarizations getrawtransaction parselog statsdisp m_js trust trusted setconfirms balance listunspent electrum snapshot_balance snapshot_loop secretaddresses dividends snapshot goals goal portfolio autoprice deletemessages getmessages debug buy sell bestfit orderbook client run_osx client_osx run coins disable enable myprice myprices getcoins getpeers getpeersIP getprices help inv setprice status ../dexscripts +cp install get_supernet trackbtc 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/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/mm 17740.c b/iguana/exchanges/mm 17740.c new file mode 100644 index 000000000..5382b33c3 --- /dev/null +++ b/iguana/exchanges/mm 17740.c @@ -0,0 +1,943 @@ +/****************************************************************************** + * 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. * + * * + ******************************************************************************/ +// +// main.c +// marketmaker +// +// Copyright © 2017 SuperNET. All rights reserved. +// + + +void PNACL_message(char *arg,...) +{ + +} +#define FROM_MARKETMAKER + +#include +#include +#ifndef NATIVE_WINDOWS +#include "OS_portable.h" +#else +#include "../../crypto777/OS_portable.h" +#endif // !_WIN_32 + +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" +void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32]); + +//defined(__APPLE__) || +#ifdef FROM_JS // defined(WIN32) || defined(USE_STATIC_NANOMSG) +#include "../../crypto777/nanosrc/nn.h" +#include "../../crypto777/nanosrc/bus.h" +#include "../../crypto777/nanosrc/pubsub.h" +#include "../../crypto777/nanosrc/pipeline.h" +#include "../../crypto777/nanosrc/reqrep.h" +#include "../../crypto777/nanosrc/tcp.h" +#include "../../crypto777/nanosrc/pair.h" +#else +#if defined(WIN32) || defined(USE_STATIC_NANOMSG) + #include "../../crypto777/nanosrc/nn.h" + #include "../../crypto777/nanosrc/bus.h" + #include "../../crypto777/nanosrc/pubsub.h" + #include "../../crypto777/nanosrc/pipeline.h" + #include "../../crypto777/nanosrc/reqrep.h" + #include "../../crypto777/nanosrc/tcp.h" + #include "../../crypto777/nanosrc/pair.h" +#else + #include "/usr/local/include/nanomsg/nn.h" + #include "/usr/local/include/nanomsg/bus.h" + #include "/usr/local/include/nanomsg/pubsub.h" + #include "/usr/local/include/nanomsg/pipeline.h" + #include "/usr/local/include/nanomsg/reqrep.h" + #include "/usr/local/include/nanomsg/tcp.h" + #include "/usr/local/include/nanomsg/pair.h" +#endif +#endif + +char DEX_baseaddr[64],DEX_reladdr[64]; +struct mmpending_order +{ + double price,volume; + int32_t dir; + uint32_t pending,completed,canceled,cancelstarted,reported; + cJSON *errorjson; + char exchange[16],base[65],rel[65],orderid[64]; +} *Pending_orders; +int32_t Num_Pending; + +#define IGUANA_URL "http://127.0.0.1:7778" + +/*char CURRENCIES[][8] = { "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", // major currencies + "CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", // end of currencies +};*/ +double PAXPRICES[sizeof(CURRENCIES)/sizeof(*CURRENCIES)]; +uint32_t PAXACTIVE; + +char *DEX_swapstatus() +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"getswaplist\"}"); + return(bitcoind_RPC(0,"InstantDEX",url,0,"getswaplist",postdata,0)); +} + +char *DEX_amlp(char *blocktrail) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"amlp\",\"blocktrail\":\"%s\"}",blocktrail); + return(bitcoind_RPC(0,"tradebot",url,0,"amlp",postdata,0)); +} + +char *DEX_openorders(char *exchange) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"openorders\",\"exchange\":\"%s\"}",exchange); + return(bitcoind_RPC(0,"InstantDEX",url,0,"openorders",postdata,0)); +} + +char *DEX_tradehistory(char *exchange) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"tradehistory\",\"exchange\":\"%s\"}",exchange); + return(bitcoind_RPC(0,"InstantDEX",url,0,"tradehistory",postdata,0)); +} + +char *DEX_orderstatus(char *exchange,char *orderid) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"orderstatus\",\"exchange\":\"%s\",\"orderid\":\"%s\"}",exchange,orderid); + return(bitcoind_RPC(0,"InstantDEX",url,0,"orderstatus",postdata,0)); +} + +char *DEX_cancelorder(char *exchange,char *orderid) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"cancelorder\",\"exchange\":\"%s\",\"orderid\":\"%s\"}",exchange,orderid); + return(bitcoind_RPC(0,"InstantDEX",url,0,"cancelorder",postdata,0)); +} + +char *DEX_balance(char *exchange,char *base,char *coinaddr) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + if ( strcmp(exchange,"DEX") == 0 ) + { + sprintf(postdata,"{\"agent\":\"dex\",\"method\":\"getbalance\",\"address\":\"%s\",\"symbol\":\"%s\"}",coinaddr,base); + return(bitcoind_RPC(0,"dex",url,0,"getbalance",postdata,0)); + } + else + { + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"balance\",\"exchange\":\"%s\",\"base\":\"%s\"}",exchange,base); + return(bitcoind_RPC(0,"InstantDEX",url,0,"balance",postdata,0)); + } +} + +char *DEX_apikeypair(char *exchange,char *apikey,char *apisecret) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"apikeypair\",\"exchange\":\"%s\",\"apikey\":\"%s\",\"apisecret\":\"%s\"}",exchange,apikey,apisecret); + return(bitcoind_RPC(0,"InstantDEX",url,0,"apikeypair",postdata,0)); +} + +char *DEX_setuserid(char *exchange,char *userid,char *tradepassword) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"setuserid\",\"exchange\":\"%s\",\"userid\":\"%s\",\"tradepassword\":\"%s\"}",exchange,userid,tradepassword); + return(bitcoind_RPC(0,"InstantDEX",url,0,"setuserid",postdata,0)); +} + +char *DEX_trade(char *exchange,char *base,char *rel,int32_t dir,double price,double volume) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"%s\",\"exchange\":\"%s\",\"base\":\"%s\",\"rel\":\"%s\",\"price\":%.8f,\"volume\":%.8f,\"dotrade\":1}",dir>0?"buy":"sell",exchange,base,rel,price,volume); + //printf("DEX_trade.(%s)\n",postdata); + return(bitcoind_RPC(0,"InstantDEX",url,0,dir>0?"buy":"sell",postdata,0)); +} + +char *DEX_withdraw(char *exchange,char *base,char *destaddr,double amount) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"withdraw\",\"exchange\":\"%s\",\"destaddr\":\"%s\",\"amount\":%.8f}",exchange,destaddr,amount); + return(bitcoind_RPC(0,"InstantDEX",url,0,"withdraw",postdata,0)); +} + +char *iguana_walletpassphrase(char *passphrase,int32_t timeout) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/coin=KMD&agent=bitcoinrpc&method=walletpassphrase?",IGUANA_URL); + sprintf(postdata,"[\"%s\", %d]",passphrase,timeout); + return(bitcoind_RPC(0,"",url,0,"walletpassphrase",postdata,0)); +} + +/*char *iguana_listunspent(char *coin,char *coinaddr) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/coin=%s&agent=bitcoinrpc&method=listunspent?",IGUANA_URL,coin); + sprintf(postdata,"[\"%s\"]",coinaddr); + return(bitcoind_RPC(0,"",url,0,"listunspent",postdata)); +}*/ + +/*char *issue_LP_intro(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers) +{ + char url[512]; + sprintf(url,"http://%s:%u/api/stats/intro?ipaddr=%s&port=%u&numpeers=%d",destip,destport,ipaddr,port,numpeers); + printf("(%s)\n",url); + return(issue_curl(url)); +}*/ + +// +// http://127.0.0.1:7779/api/stats/getpeers + +char *DEX_listunspent(char *coin,char *coinaddr) +{ + char url[512],postdata[1024]; + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"dex\",\"method\":\"listunspent\",\"address\":\"%s\",\"symbol\":\"%s\",\"timeout\":60000}",coinaddr,coin); + return(bitcoind_RPC(0,"dex",url,0,"listunspent",postdata,0)); +} + +bits256 iguana_wif2privkey(char *wifstr) +{ + char url[512],postdata[1024],*retstr,*privstr; bits256 privkey; cJSON *retjson; + memset(privkey.bytes,0,sizeof(privkey)); + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"SuperNET\",\"method\":\"wif2priv\",\"wif\":\"%s\"}",wifstr); + if ( (retstr= bitcoind_RPC(0,"SuperNET",url,0,"wif2priv",postdata,0)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( (privstr= jstr(retjson,"privkey")) != 0 ) + { + if ( strlen(privstr) == 64 ) + decode_hex(privkey.bytes,32,privstr); + } + free_json(retjson); + } + free(retstr); + } + return(privkey); +} + +double bittrex_balance(char *base,char *coinaddr) +{ + char *retstr; cJSON *retjson; double balance = 0.; + if ( (retstr= DEX_balance("bittrex",base,coinaddr)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + balance = jdouble(retjson,"balance"); + free_json(retjson); + } + free(retstr); + } + return(balance); +} + +double dex_balance(char *base,char *coinaddr) +{ + char *retstr; cJSON *retjson; double balance = 0.; + if ( (retstr= DEX_balance("DEX",base,coinaddr)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + balance = jdouble(retjson,"balance"); + free_json(retjson); + } + free(retstr); + } + return(balance); +} + +int32_t komodo_baseid(char *base) +{ + int32_t i; + for (i=0; i 0 ) + { + for (i=0; i SMALLVAL && (name= jstr(item,"name")) != 0 && strncmp(name,"USD/",4) == 0 ) + { + if ( (baseid= komodo_baseid(name+4)) >= 0 && baseid < 32 ) + { + if ( ((1LL << baseid) & mask) == 0 ) + { + _marketmaker_fiatupdate(baseid,price); + mask |= (1LL << baseid); + } else if ( fabs(price*PAXPRICES[0] - PAXPRICES[baseid]) > SMALLVAL ) + printf("DUPLICATE PRICE? %s %.8f vs %.8f\n",name+4,price*PAXPRICES[0],PAXPRICES[baseid]); + } + } + } + } + } + printf("pax mask.%x\n",(uint32_t)mask); + return((uint32_t)mask); +} + +void marketmaker_cancel(struct mmpending_order *ptr) +{ + char *retstr; cJSON *retjson; + if ( ptr->pending != 0 && ptr->cancelstarted == 0 ) + { + ptr->cancelstarted = (uint32_t)time(NULL); + if ( (retstr= DEX_cancelorder(ptr->exchange,ptr->orderid)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + printf("cancel %s (%s/%s) %.8f vol %.8f dir.%d -> (%s)\n",ptr->exchange,ptr->base,ptr->rel,ptr->price,ptr->volume,ptr->dir,jprint(retjson,0)); + free_json(retjson); + ptr->pending = 0; + ptr->canceled = (uint32_t)time(NULL); + } + free(retstr); + } + } +} + +void marketmaker_queue(char *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *retjson) +{ + struct mmpending_order *ptr; char *orderid; + //DEX_trade.({"success":true,"message":"","result":{"uuid":"d5faa9e4-660d-436f-a257-2c6a40442d8c"},"tag":"11271578410079391025"} + if ( is_cJSON_True(jobj(retjson,"success")) != 0 && jobj(retjson,"result") != 0 ) + retjson = jobj(retjson,"result"); + printf("QUEUE.%s %s/%s dir.%d %.8f %.6f (%s)\n",exchange,base,rel,dir,price,volume,jprint(retjson,0)); + Pending_orders = realloc(Pending_orders,(1 + Num_Pending) * sizeof(*Pending_orders)); + ptr = &Pending_orders[Num_Pending++]; + memset(ptr,0,sizeof(*ptr)); + ptr->price = price; + ptr->volume = volume; + ptr->dir = dir; + ptr->pending = (uint32_t)time(NULL); + strcpy(ptr->exchange,exchange); + strcpy(ptr->base,base); + strcpy(ptr->rel,rel); + if ( (orderid= jstr(retjson,"OrderUuid")) != 0 || (orderid= jstr(retjson,"uuid")) != 0 ) + strcpy(ptr->orderid,orderid); + else strcpy(ptr->orderid,"0"); +} + +void marketmaker_pendingupdate(char *exchange,char *base,char *rel) +{ + char *retstr; cJSON *retjson,*obj; int32_t i; struct mmpending_order *ptr; + for (i=0; iexchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 ) + continue; + if ( ptr->completed == 0 && (retstr= DEX_orderstatus(exchange,ptr->orderid)) != 0 ) + { + //printf("%s status.(%s)\n",ptr->orderid,retstr); + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + obj = jobj(retjson,"result"); + if ( is_cJSON_Array(obj) != 0 ) + obj = jitem(retjson,0); + if ( jdouble(obj,"QuantityRemaining") == 0. || is_cJSON_True(jobj(obj,"IsOpen")) == 0 ) + { +//{"Uuid":null,"OrderUuid":"e7b0789c-0c4e-413b-a768-3d5734d9cbe5","Exchange":"BTC-KMD","OrderType":"LIMIT_SELL","Quantity":877.77700000,"QuantityRemaining":462.50512234,"Limit":0.00011770,"CommissionPaid":0.00012219,"Price":0.04887750,"PricePerUnit":0.00011769,"Opened":"2017-02-20T13:16:22.29","Closed":null,"CancelInitiated":false,"ImmediateOrCancel":false,"IsConditional":false,"Condition":"NONE","ConditionTarget":null} printf("uuid.(%s) finished.(%s)\n",ptr->orderid,jprint(retjson,0)); + ptr->completed = (uint32_t)time(NULL); + ptr->pending = 0; + } + free_json(retjson); + } + free(retstr); + } + } +} + +void marketmaker_pendinginit(char *exchange,char *base,char *rel) +{ + 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 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + //printf("%s\n",jprint(retjson,0)); + if ( is_cJSON_True(jobj(retjson,"success")) != 0 && (array= jarray(&n,retjson,"result")) != 0 ) + { + for (i=0; iexchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 ) + continue; + if ( strcmp(ptr->orderid,orderid) == 0 ) + { + ptr->pending = (uint32_t)time(NULL); + ptr->completed = 0; + printf("%s pending\n",orderid); + break; + } + } + if ( j == Num_Pending ) + { + if ( jstr(item,"OrderType") != 0 ) + { + if ( strcmp(jstr(item,"OrderType"),"LIMIT_BUY") == 0 ) + dir = 1; + else if ( strcmp(jstr(item,"OrderType"),"LIMIT_SELL") == 0 ) + dir = -1; + else dir = 0; + if ( dir != 0 ) + marketmaker_queue(exchange,base,rel,dir,jdouble(item,"Limit"),jdouble(item,"QuantityRemaining"),item); + else printf("no dir (%s) (%s)\n",jprint(item,0),jstr(item,"OrderType")); + } + } + } + } + } + free_json(retjson); + } + free(retstr); + } +} + +double marketmaker_filled(char *exchange,char *base,char *rel,double *buyvolp,double *sellvolp,double *pendingbidsp,double *pendingasksp) +{ + double pricesum = 0.,volsum = 0.; struct mmpending_order *ptr; int32_t i; + *pendingbidsp = *pendingasksp = 0.; + for (i=0; iexchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 ) + continue; + if ( ptr->completed != 0 ) + { + if ( ptr->reported == 0 ) + { + if ( ptr->dir > 0 ) + (*buyvolp) += ptr->volume; + else if ( ptr->dir < 0 ) + (*sellvolp) += ptr->volume; + pricesum += ptr->volume * ptr->price; + volsum += ptr->volume; + ptr->reported = (uint32_t)time(NULL); + printf("REPORT dir.%d vol %.8f\n",ptr->dir,ptr->volume); + } + } + else if ( ptr->pending != 0 ) // alternative is error or cancelled + { + if ( ptr->dir > 0 ) + (*pendingbidsp) += ptr->volume; + else if ( ptr->dir < 0 ) + (*pendingasksp) += ptr->volume; + } + } + if ( volsum != 0. ) + pricesum /= volsum; + return(pricesum); +} + +int32_t marketmaker_prune(char *exchange,char *base,char *rel,int32_t polarity,double bid,double ask,double separation) +{ + int32_t i,n = 0; struct mmpending_order *ptr; + for (i=0; iexchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 ) + continue; + if ( ptr->pending != 0 && ptr->cancelstarted == 0 ) + { + if ( polarity != 0 ) + { + if ( ((ptr->dir*polarity > 0 && ptr->price < bid-separation) || (ptr->dir*polarity < 0 && ptr->price > ask+separation)) ) + { + printf("polarity.%d dir.%d price.%f bid.%f ask.%f\n",polarity,ptr->dir,ptr->price,bid,ask); + marketmaker_cancel(ptr), n++; + } + } + /*else + {,*prunebid=0,*pruneask=0; double lowbid=0.,highask=0. + if ( ptr->dir > 0 && (lowbid == 0. || ptr->price < lowbid) ) + { + lowbid = ptr->price; + prunebid = ptr; + } + else if ( ptr->dir < 0 && (highask == 0. || ptr->price > highask) ) + { + highask = ptr->price; + pruneask = ptr; + } + }*/ + } + } + /*if ( polarity == 0 ) + { + if ( prunebid != 0 && fabs(prunebid->price - bid) > separation ) + marketmaker_cancel(prunebid), n++; + if ( pruneask != 0 && fabs(pruneask->price - ask) > separation ) + marketmaker_cancel(pruneask), n++; + }*/ + return(n); +} + +void marketmaker_volumeset(double *bidincrp,double *askincrp,double incr,double buyvol,double pendingbids,double sellvol,double pendingasks,double maxexposure) +{ + *bidincrp = *askincrp = incr; + //if ( pendingbids >= pendingasks+maxexposure ) + // *bidincrp = 0.; + //else if ( pendingasks >= pendingbids+maxexposure ) + // *askincrp = 0.; + if ( *bidincrp > 0. && pendingbids + *bidincrp > maxexposure ) + *bidincrp = (maxexposure - *bidincrp); + if ( *askincrp > 0. && pendingasks + *askincrp > maxexposure ) + *askincrp = (maxexposure - *askincrp); + if ( *bidincrp < 0. ) + *bidincrp = 0.; + if ( *askincrp < 0. ) + *askincrp = 0.; +} + +int32_t marketmaker_spread(char *exchange,char *base,char *rel,double bid,double bidvol,double ask,double askvol,double separation) +{ + int32_t nearflags[2],i,n = 0; struct mmpending_order *ptr; cJSON *retjson,*vals; char *retstr,postdata[1024],url[128]; double vol,spread_ratio; + memset(nearflags,0,sizeof(nearflags)); + if ( strcmp("DEX",exchange) != 0 ) + { + for (i=0; iexchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 ) + continue; + if ( ptr->pending != 0 && ptr->cancelstarted == 0 ) + { + if ( bid > SMALLVAL && bidvol > SMALLVAL && ptr->dir > 0 && fabs(bid - ptr->price) < separation ) + { + //printf("bid %.8f near %.8f\n",bid,ptr->price); + nearflags[0]++; + } + if ( ask > SMALLVAL && askvol > SMALLVAL && ptr->dir < 0 && fabs(ask - ptr->price) < separation ) + { + //printf("%.8f near %.8f\n",ask,ptr->price); + nearflags[1]++; + } + } + } + } + //printf("spread.%s (%.8f %.6f) (%.8f %.6f)\n",exchange,bid,bidvol,ask,askvol); + if ( bid > SMALLVAL && bidvol > SMALLVAL && nearflags[0] == 0 ) + { + if ( strcmp("DEX",exchange) == 0 && strcmp(base,"KMD") == 0 && strcmp(rel,"BTC") == 0 ) + { + if ( ask > SMALLVAL && askvol > SMALLVAL ) + { + /*li.profit = jdouble(vals,"profit"); + li.refprice = jdouble(vals,"refprice"); + li.bid = jdouble(vals,"bid"); + li.ask = jdouble(vals,"ask"); + if ( (li.minvol= jdouble(vals,"minvol")) <= 0. ) + li.minvol = (strcmp("BTC",base) == 0) ? 0.0001 : 0.001; + if ( (li.maxvol= jdouble(vals,"maxvol")) < li.minvol ) + li.maxvol = li.minvol;*/ + //curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"MVP\",\"vals\":{\"rel\":\"USD\",\"bid\":0.09,\"ask\":0.11,\"maxvol\":100}}" + vals = cJSON_CreateObject(); + jaddstr(vals,"rel","BTC"); + jaddnum(vals,"bid",bid); + jaddnum(vals,"ask",ask); + vol = bidvol > askvol ? askvol : bidvol; + jaddnum(vals,"maxvol",vol); + jaddnum(vals,"minvol",vol*0.1 > 100 ? 100 : vol * 0.1); + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"%s\",\"vals\":%s}",base,jprint(vals,1)); + //printf("(%s)\n",postdata); + if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata,0)) != 0 ) + { + //printf("(%s) -> (%s)\n",postdata,retstr); + free(retstr); + } + spread_ratio = .5 * ((ask - bid) / (bid + ask)); + for (i=0; i SMALLVAL ) + { + vals = cJSON_CreateObject(); + jaddstr(vals,"rel",CURRENCIES[i]); + jaddnum(vals,"bid",PAXPRICES[i] * (1. - spread_ratio)); + jaddnum(vals,"ask",PAXPRICES[i] * (1. + spread_ratio)); + jaddnum(vals,"maxvol",vol * PAXPRICES[i]); + jaddnum(vals,"minvol",MAX(1,(int32_t)(vol * 0.01 * PAXPRICES[i]))); + sprintf(url,"%s/?",IGUANA_URL); + sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"%s\",\"vals\":%s}","KMD",jprint(vals,1)); + if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata,0)) != 0 ) + { + //printf("(%s) -> (%s)\n",postdata,retstr); + free(retstr); + } + } +//break; + } + } else printf("unsupported ask only for DEX %s/%s\n",base,rel); + } + else if ( (retstr= DEX_trade(exchange,base,rel,1,bid,bidvol)) != 0 ) + { + //printf("DEX_trade.(%s)\n",retstr); + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + marketmaker_queue(exchange,base,rel,1,bid,bidvol,retjson); + free_json(retjson); + } + free(retstr); + } //else printf("skip bid %s %.8f vol %f\n",exchange,bid,bidvol); + } + if ( ask > SMALLVAL && askvol > SMALLVAL && nearflags[1] == 0 && strcmp("DEX",exchange) != 0 ) + { + if ( (retstr= DEX_trade(exchange,base,rel,-1,ask,askvol)) != 0 ) + { + //printf("DEX_trade.(%s)\n",retstr); + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + marketmaker_queue(exchange,base,rel,-1,ask,askvol,retjson); + free_json(retjson); + } + free(retstr); + } + } //else printf("skip ask %s %.8f vol %f\n",exchange,bid,bidvol); + return(n); +} + +double marketmaker_updateprice(char *name,char *base,char *rel,double theoretical,double *incrp) +{ + static uint32_t counter; + cJSON *fiatjson; double USD_average=0.,usdprice=0.,CMC_average=0.,avebid=0.,aveask=0.,val,changes[3],highbid=0.,lowask=0.; + if ( (val= get_theoretical(&avebid,&aveask,&highbid,&lowask,&CMC_average,changes,name,base,rel,&USD_average)) != 0. ) + { + if ( theoretical == 0. ) + { + theoretical = val; + if ( *incrp > 2 ) + { + *incrp = (int32_t)*incrp; + *incrp += 0.777; + } + } else theoretical = (theoretical + val) * 0.5; + if ( (counter++ % 12) == 0 ) + { + if ( USD_average > SMALLVAL && CMC_average > SMALLVAL && theoretical > SMALLVAL ) + { + usdprice = USD_average * (theoretical / CMC_average); + printf("USD %.4f <- (%.6f * (%.8f / %.8f))\n",usdprice,USD_average,theoretical,CMC_average); + PAXPRICES[0] = usdprice; + if ( (fiatjson= yahoo_allcurrencies()) != 0 ) + { + marketmaker_fiatupdate(fiatjson); + free_json(fiatjson); + } + } + } + LP_priceupdate(base,rel,theoretical,avebid,aveask,highbid,lowask,PAXPRICES); + } + return(theoretical); +} + +void marketmaker(double minask,double maxbid,char *baseaddr,char *reladdr,double start_BASE,double start_REL,double profitmargin,double maxexposure,double ratioincr,char *exchange,char *name,char *base,char *rel) +{ + char *retstr; double bid,ask,start_DEXbase,start_DEXrel,DEX_base = 0.,DEX_rel = 0.,balance_base=0.,balance_rel=0.,mmbid,mmask,aveprice,incr,pendingbids,pendingasks,buyvol,sellvol,bidincr,askincr,filledprice,avebid=0.,aveask=0.,highbid=0.,lowask=0.,theoretical = 0.; uint32_t lasttime = 0; + incr = maxexposure * ratioincr; + buyvol = sellvol = 0.; + start_DEXbase = dex_balance(base,baseaddr); + start_DEXrel = dex_balance(rel,reladdr); + while ( 1 ) + { + if ( time(NULL) > lasttime+60 ) + { + if ( (theoretical= marketmaker_updateprice(name,base,rel,theoretical,&incr)) != 0. ) + { + if ( lasttime == 0 ) + maxexposure /= theoretical; + } + if ( strcmp(exchange,"bittrex") == 0 ) + { + balance_base = bittrex_balance(base,""); + balance_rel = bittrex_balance(rel,""); + DEX_base = dex_balance(base,baseaddr); + DEX_rel = dex_balance(rel,reladdr); + } else printf("add support for %s balance\n",exchange); + lasttime = (uint32_t)time(NULL); + } + marketmaker_pendingupdate(exchange,base,rel); + if ( theoretical > SMALLVAL && avebid > SMALLVAL && aveask > SMALLVAL ) + { + aveprice = (avebid + aveask) * 0.5; + // if order is filled, theoretical <- filled (theoretical + price)/2 + if ( (filledprice= marketmaker_filled(exchange,base,rel,&buyvol,&sellvol,&pendingbids,&pendingasks)) != 0. ) + theoretical = (theoretical + filledprice) * 0.5; + buyvol = sellvol = 0; + if ( (balance_base + DEX_base) < (start_BASE + start_DEXbase) ) + sellvol += ((start_BASE + start_DEXbase) - (balance_base + DEX_base)); + else buyvol += ((balance_base + DEX_base) - (start_BASE + start_DEXbase)); + if ( (balance_rel + DEX_rel) < (start_REL + start_DEXrel) ) + buyvol += ((start_REL + start_DEXrel) - (balance_rel + DEX_rel)) / theoretical; + else sellvol += ((balance_rel + DEX_rel) - (start_REL + start_DEXrel)) / theoretical; + mmbid = theoretical - theoretical*profitmargin; + mmask = theoretical + theoretical*profitmargin; + // if any existing order exceeds double margin distance, cancel + marketmaker_prune(exchange,base,rel,1,mmbid - theoretical*profitmargin,mmask + theoretical*profitmargin,0.); + // if new prices crosses existing order, cancel old order first + marketmaker_prune(exchange,base,rel,-1,mmbid,mmask,0.); + //printf("(%.8f %.8f) ",mmbid,mmask); + if ( (1) ) + { + if ( mmbid >= lowask || (maxbid > SMALLVAL && mmbid > maxbid) ) //mmbid < highbid || + { + printf("clear mmbid %.8f lowask %.8f maxbid %.8f\n",mmbid,lowask,maxbid); + mmbid = 0.; + } + if ( mmask <= highbid || (minask > SMALLVAL && mmask < minask) ) // mmask > lowask || + mmask = 0.; + } + marketmaker_volumeset(&bidincr,&askincr,incr,buyvol,pendingbids,sellvol,pendingasks,maxexposure); + printf("AVE.(%.8f %.8f) hbla %.8f %.8f bid %.8f ask %.8f theory %.8f buys.(%.6f %.6f) sells.(%.6f %.6f) incr.(%.6f %.6f) balances.(%.8f + %.8f, %.8f + %.8f) test %f\n",avebid,aveask,highbid,lowask,mmbid,mmask,theoretical,buyvol,pendingbids,sellvol,pendingasks,bidincr,askincr,balance_base,DEX_base,balance_rel,DEX_rel,(aveask - avebid)/aveprice); + if ( (retstr= DEX_swapstatus()) != 0 ) + printf("%s\n",retstr), free(retstr); + printf("%s %s %s, %s %s %s\n",base,DEX_baseaddr,DEX_balance("DEX",base,DEX_baseaddr),rel,DEX_reladdr,DEX_balance("DEX",rel,DEX_reladdr)); + if ( (aveask - avebid)/aveprice > profitmargin ) + bid = highbid * (1 - profitmargin), ask = lowask * (1 + profitmargin); + else bid = avebid - profitmargin*aveprice, ask = avebid + profitmargin*aveprice; + marketmaker_spread("DEX",base,rel,bid,incr,ask,incr,profitmargin*aveprice*0.5); + if ( (pendingbids + buyvol) > (pendingasks + sellvol) && (pendingbids + buyvol) > bidincr ) + { + bidincr *= ((double)(pendingasks + sellvol) / ((pendingbids + buyvol) + (pendingasks + sellvol))); + printf("bidincr %f buy.(%f + %f) sell.(%f + %f)\n",bidincr,pendingbids,buyvol,pendingasks,sellvol); + if ( bidincr < 0.1*incr ) + bidincr = 0.1*incr; + if ( bidincr > 1. ) + bidincr = (int32_t)bidincr + 0.777; + } + if ( (pendingbids + buyvol) < (pendingasks + sellvol) && (pendingasks + sellvol) > askincr ) + { + askincr *= (double)(pendingbids + buyvol) / ((pendingbids + buyvol) + (pendingasks + sellvol)); + if ( askincr < 0.1*incr ) + askincr = 0.1*incr; + if ( askincr > 1. ) + askincr = (int32_t)askincr + 0.777; + } + //printf("mmbid %.8f %.6f, mmask %.8f %.6f\n",mmbid,bidincr,mmask,askincr); + marketmaker_spread(exchange,base,rel,mmbid,bidincr,mmask,askincr,profitmargin*aveprice*0.5); + sleep(60); + } + } +} + +#include "LP_nativeDEX.c" + +void LP_main(void *ptr) +{ + char *passphrase; double profitmargin; uint16_t port; cJSON *argjson = ptr; + if ( (passphrase= jstr(argjson,"passphrase")) != 0 ) + { + profitmargin = jdouble(argjson,"profitmargin"); + LP_profitratio += profitmargin; + if ( (port= juint(argjson,"rpcport")) < 1000 ) + port = LP_RPCPORT; + LPinit(port,LP_RPCPORT+10,LP_RPCPORT+20,LP_RPCPORT+30,passphrase,jint(argjson,"client"),jstr(argjson,"userhome"),argjson); + } +} + +int main(int argc, const char * argv[]) +{ + char dirname[512],*base,*rel,*name,*exchange,*apikey,*apisecret,*blocktrail,*retstr,*baseaddr,*reladdr,*passphrase; + double profitmargin,maxexposure,incrratio,start_rel,start_base,minask,maxbid,incr; + cJSON *retjson,*loginjson; int32_t i; + OS_init(); + if ( strstr(argv[0],"btc2kmd") != 0 && argv[1] != 0 ) + { + uint8_t addrtype,rmd160[20],rmd160b[20]; char coinaddr[64],coinaddr2[64]; + bitcoin_addr2rmd160(0,&addrtype,rmd160,(char *)argv[1]); + 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); + } + sprintf(dirname,"%s",GLOBAL_DBDIR), OS_ensure_directory(dirname); + sprintf(dirname,"%s/SWAPS",GLOBAL_DBDIR), OS_ensure_directory(dirname); + sprintf(dirname,"%s/PRICES",GLOBAL_DBDIR), OS_ensure_directory(dirname); + sprintf(dirname,"%s/UNSPENTS",GLOBAL_DBDIR), OS_ensure_directory(dirname); +#ifdef FROM_JS + argc = 2; + retjson = cJSON_Parse("{\"client\":1,\"passphrase\":\"test\"}"); + printf("calling LP_main(%s)\n",jprint(retjson,0)); + LP_main(retjson); + emscripten_set_main_loop(LP_fromjs_iter,1,0); +#else + if ( argc == 1 ) + { + LP_NXT_redeems(); + sleep(3); + return(0); + } + if ( argc > 1 && (retjson= cJSON_Parse(argv[1])) != 0 ) + { + if ( 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 ) + { + printf("error launching LP_main (%s)\n",jprint(retjson,0)); + exit(-1); + } //else printf("(%s) launched.(%s)\n",argv[1],passphrase); + incr = 100.; + while ( (1) ) + sleep(100000); + profitmargin = jdouble(retjson,"profitmargin"); + minask = jdouble(retjson,"minask"); + maxbid = jdouble(retjson,"maxbid"); + maxexposure = jdouble(retjson,"maxexposure"); + incrratio = jdouble(retjson,"lotratio"); + start_base = jdouble(retjson,"start_base"); + start_rel = jdouble(retjson,"start_rel"); + apikey = jstr(retjson,"apikey"); + apisecret = jstr(retjson,"apisecret"); + base = jstr(retjson,"base"); + name = jstr(retjson,"name"); + rel = jstr(retjson,"rel"); + blocktrail = jstr(retjson,"blocktrail"); + exchange = jstr(retjson,"exchange"); + PAXACTIVE = juint(retjson,"paxactive"); + if ( profitmargin < 0. || maxexposure <= 0. || incrratio <= 0. || apikey == 0 || apisecret == 0 || base == 0 || name == 0 || rel == 0 || exchange == 0 || blocktrail == 0 ) + { + printf("illegal parameter (%s)\n",jprint(retjson,0)); + exit(-1); + } + if ( (retstr= iguana_walletpassphrase(passphrase,999999)) != 0 ) + { + printf("(%s/%s) login.(%s)\n",base,rel,retstr); + if ( (loginjson= cJSON_Parse(retstr)) != 0 ) + { + if ( PAXACTIVE != 0 ) + { + for (i=0; i<32; i++) + { + if ( ((1< (b) ? (a) : (b)) char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *remoteaddr,uint16_t port); #include "stats.c" @@ -69,799 +69,8 @@ void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveas #endif #endif -char DEX_baseaddr[64],DEX_reladdr[64]; -struct mmpending_order -{ - double price,volume; - int32_t dir; - uint32_t pending,completed,canceled,cancelstarted,reported; - cJSON *errorjson; - char exchange[16],base[65],rel[65],orderid[64]; -} *Pending_orders; -int32_t Num_Pending; - -#define IGUANA_URL "http://127.0.0.1:7778" - -/*char CURRENCIES[][8] = { "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", // major currencies - "CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", // end of currencies -};*/ -double PAXPRICES[sizeof(CURRENCIES)/sizeof(*CURRENCIES)]; -uint32_t PAXACTIVE; - -char *DEX_swapstatus() -{ - char url[512],postdata[1024]; - sprintf(url,"%s/?",IGUANA_URL); - sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"getswaplist\"}"); - return(bitcoind_RPC(0,"InstantDEX",url,0,"getswaplist",postdata,0)); -} - -char *DEX_amlp(char *blocktrail) -{ - char url[512],postdata[1024]; - sprintf(url,"%s/?",IGUANA_URL); - sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"amlp\",\"blocktrail\":\"%s\"}",blocktrail); - return(bitcoind_RPC(0,"tradebot",url,0,"amlp",postdata,0)); -} - -char *DEX_openorders(char *exchange) -{ - char url[512],postdata[1024]; - sprintf(url,"%s/?",IGUANA_URL); - sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"openorders\",\"exchange\":\"%s\"}",exchange); - return(bitcoind_RPC(0,"InstantDEX",url,0,"openorders",postdata,0)); -} - -char *DEX_tradehistory(char *exchange) -{ - char url[512],postdata[1024]; - sprintf(url,"%s/?",IGUANA_URL); - sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"tradehistory\",\"exchange\":\"%s\"}",exchange); - return(bitcoind_RPC(0,"InstantDEX",url,0,"tradehistory",postdata,0)); -} - -char *DEX_orderstatus(char *exchange,char *orderid) -{ - char url[512],postdata[1024]; - sprintf(url,"%s/?",IGUANA_URL); - sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"orderstatus\",\"exchange\":\"%s\",\"orderid\":\"%s\"}",exchange,orderid); - return(bitcoind_RPC(0,"InstantDEX",url,0,"orderstatus",postdata,0)); -} - -char *DEX_cancelorder(char *exchange,char *orderid) -{ - char url[512],postdata[1024]; - sprintf(url,"%s/?",IGUANA_URL); - sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"cancelorder\",\"exchange\":\"%s\",\"orderid\":\"%s\"}",exchange,orderid); - return(bitcoind_RPC(0,"InstantDEX",url,0,"cancelorder",postdata,0)); -} - -char *DEX_balance(char *exchange,char *base,char *coinaddr) -{ - char url[512],postdata[1024]; - sprintf(url,"%s/?",IGUANA_URL); - if ( strcmp(exchange,"DEX") == 0 ) - { - sprintf(postdata,"{\"agent\":\"dex\",\"method\":\"getbalance\",\"address\":\"%s\",\"symbol\":\"%s\"}",coinaddr,base); - return(bitcoind_RPC(0,"dex",url,0,"getbalance",postdata,0)); - } - else - { - sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"balance\",\"exchange\":\"%s\",\"base\":\"%s\"}",exchange,base); - return(bitcoind_RPC(0,"InstantDEX",url,0,"balance",postdata,0)); - } -} - -char *DEX_apikeypair(char *exchange,char *apikey,char *apisecret) -{ - char url[512],postdata[1024]; - sprintf(url,"%s/?",IGUANA_URL); - sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"apikeypair\",\"exchange\":\"%s\",\"apikey\":\"%s\",\"apisecret\":\"%s\"}",exchange,apikey,apisecret); - return(bitcoind_RPC(0,"InstantDEX",url,0,"apikeypair",postdata,0)); -} - -char *DEX_setuserid(char *exchange,char *userid,char *tradepassword) -{ - char url[512],postdata[1024]; - sprintf(url,"%s/?",IGUANA_URL); - sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"setuserid\",\"exchange\":\"%s\",\"userid\":\"%s\",\"tradepassword\":\"%s\"}",exchange,userid,tradepassword); - return(bitcoind_RPC(0,"InstantDEX",url,0,"setuserid",postdata,0)); -} - -char *DEX_trade(char *exchange,char *base,char *rel,int32_t dir,double price,double volume) -{ - char url[512],postdata[1024]; - sprintf(url,"%s/?",IGUANA_URL); - sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"%s\",\"exchange\":\"%s\",\"base\":\"%s\",\"rel\":\"%s\",\"price\":%.8f,\"volume\":%.8f,\"dotrade\":1}",dir>0?"buy":"sell",exchange,base,rel,price,volume); - //printf("DEX_trade.(%s)\n",postdata); - return(bitcoind_RPC(0,"InstantDEX",url,0,dir>0?"buy":"sell",postdata,0)); -} - -char *DEX_withdraw(char *exchange,char *base,char *destaddr,double amount) -{ - char url[512],postdata[1024]; - sprintf(url,"%s/?",IGUANA_URL); - sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"withdraw\",\"exchange\":\"%s\",\"destaddr\":\"%s\",\"amount\":%.8f}",exchange,destaddr,amount); - return(bitcoind_RPC(0,"InstantDEX",url,0,"withdraw",postdata,0)); -} - -char *iguana_walletpassphrase(char *passphrase,int32_t timeout) -{ - char url[512],postdata[1024]; - sprintf(url,"%s/coin=KMD&agent=bitcoinrpc&method=walletpassphrase?",IGUANA_URL); - sprintf(postdata,"[\"%s\", %d]",passphrase,timeout); - return(bitcoind_RPC(0,"",url,0,"walletpassphrase",postdata,0)); -} - -/*char *iguana_listunspent(char *coin,char *coinaddr) -{ - char url[512],postdata[1024]; - sprintf(url,"%s/coin=%s&agent=bitcoinrpc&method=listunspent?",IGUANA_URL,coin); - sprintf(postdata,"[\"%s\"]",coinaddr); - return(bitcoind_RPC(0,"",url,0,"listunspent",postdata)); -}*/ - -/*char *issue_LP_intro(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers) -{ - char url[512]; - sprintf(url,"http://%s:%u/api/stats/intro?ipaddr=%s&port=%u&numpeers=%d",destip,destport,ipaddr,port,numpeers); - printf("(%s)\n",url); - return(issue_curl(url)); -}*/ - -// -// http://127.0.0.1:7779/api/stats/getpeers - -char *DEX_listunspent(char *coin,char *coinaddr) -{ - char url[512],postdata[1024]; - sprintf(url,"%s/?",IGUANA_URL); - sprintf(postdata,"{\"agent\":\"dex\",\"method\":\"listunspent\",\"address\":\"%s\",\"symbol\":\"%s\",\"timeout\":60000}",coinaddr,coin); - return(bitcoind_RPC(0,"dex",url,0,"listunspent",postdata,0)); -} - -bits256 iguana_wif2privkey(char *wifstr) -{ - char url[512],postdata[1024],*retstr,*privstr; bits256 privkey; cJSON *retjson; - memset(privkey.bytes,0,sizeof(privkey)); - sprintf(url,"%s/?",IGUANA_URL); - sprintf(postdata,"{\"agent\":\"SuperNET\",\"method\":\"wif2priv\",\"wif\":\"%s\"}",wifstr); - if ( (retstr= bitcoind_RPC(0,"SuperNET",url,0,"wif2priv",postdata,0)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( (privstr= jstr(retjson,"privkey")) != 0 ) - { - if ( strlen(privstr) == 64 ) - decode_hex(privkey.bytes,32,privstr); - } - free_json(retjson); - } - free(retstr); - } - return(privkey); -} - -double bittrex_balance(char *base,char *coinaddr) -{ - char *retstr; cJSON *retjson; double balance = 0.; - if ( (retstr= DEX_balance("bittrex",base,coinaddr)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - balance = jdouble(retjson,"balance"); - free_json(retjson); - } - free(retstr); - } - return(balance); -} - -double dex_balance(char *base,char *coinaddr) -{ - char *retstr; cJSON *retjson; double balance = 0.; - if ( (retstr= DEX_balance("DEX",base,coinaddr)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - balance = jdouble(retjson,"balance"); - free_json(retjson); - } - free(retstr); - } - return(balance); -} - -int32_t komodo_baseid(char *base) -{ - int32_t i; - for (i=0; i 0 ) - { - for (i=0; i SMALLVAL && (name= jstr(item,"name")) != 0 && strncmp(name,"USD/",4) == 0 ) - { - if ( (baseid= komodo_baseid(name+4)) >= 0 && baseid < 32 ) - { - if ( ((1LL << baseid) & mask) == 0 ) - { - _marketmaker_fiatupdate(baseid,price); - mask |= (1LL << baseid); - } else if ( fabs(price*PAXPRICES[0] - PAXPRICES[baseid]) > SMALLVAL ) - printf("DUPLICATE PRICE? %s %.8f vs %.8f\n",name+4,price*PAXPRICES[0],PAXPRICES[baseid]); - } - } - } - } - } - printf("pax mask.%x\n",(uint32_t)mask); - return((uint32_t)mask); -} - -void marketmaker_cancel(struct mmpending_order *ptr) -{ - char *retstr; cJSON *retjson; - if ( ptr->pending != 0 && ptr->cancelstarted == 0 ) - { - ptr->cancelstarted = (uint32_t)time(NULL); - if ( (retstr= DEX_cancelorder(ptr->exchange,ptr->orderid)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - printf("cancel %s (%s/%s) %.8f vol %.8f dir.%d -> (%s)\n",ptr->exchange,ptr->base,ptr->rel,ptr->price,ptr->volume,ptr->dir,jprint(retjson,0)); - free_json(retjson); - ptr->pending = 0; - ptr->canceled = (uint32_t)time(NULL); - } - free(retstr); - } - } -} - -void marketmaker_queue(char *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *retjson) -{ - struct mmpending_order *ptr; char *orderid; - //DEX_trade.({"success":true,"message":"","result":{"uuid":"d5faa9e4-660d-436f-a257-2c6a40442d8c"},"tag":"11271578410079391025"} - if ( is_cJSON_True(jobj(retjson,"success")) != 0 && jobj(retjson,"result") != 0 ) - retjson = jobj(retjson,"result"); - printf("QUEUE.%s %s/%s dir.%d %.8f %.6f (%s)\n",exchange,base,rel,dir,price,volume,jprint(retjson,0)); - Pending_orders = realloc(Pending_orders,(1 + Num_Pending) * sizeof(*Pending_orders)); - ptr = &Pending_orders[Num_Pending++]; - memset(ptr,0,sizeof(*ptr)); - ptr->price = price; - ptr->volume = volume; - ptr->dir = dir; - ptr->pending = (uint32_t)time(NULL); - strcpy(ptr->exchange,exchange); - strcpy(ptr->base,base); - strcpy(ptr->rel,rel); - if ( (orderid= jstr(retjson,"OrderUuid")) != 0 || (orderid= jstr(retjson,"uuid")) != 0 ) - strcpy(ptr->orderid,orderid); - else strcpy(ptr->orderid,"0"); -} - -void marketmaker_pendingupdate(char *exchange,char *base,char *rel) -{ - char *retstr; cJSON *retjson,*obj; int32_t i; struct mmpending_order *ptr; - for (i=0; iexchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 ) - continue; - if ( ptr->completed == 0 && (retstr= DEX_orderstatus(exchange,ptr->orderid)) != 0 ) - { - //printf("%s status.(%s)\n",ptr->orderid,retstr); - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - obj = jobj(retjson,"result"); - if ( is_cJSON_Array(obj) != 0 ) - obj = jitem(retjson,0); - if ( jdouble(obj,"QuantityRemaining") == 0. || is_cJSON_True(jobj(obj,"IsOpen")) == 0 ) - { -//{"Uuid":null,"OrderUuid":"e7b0789c-0c4e-413b-a768-3d5734d9cbe5","Exchange":"BTC-KMD","OrderType":"LIMIT_SELL","Quantity":877.77700000,"QuantityRemaining":462.50512234,"Limit":0.00011770,"CommissionPaid":0.00012219,"Price":0.04887750,"PricePerUnit":0.00011769,"Opened":"2017-02-20T13:16:22.29","Closed":null,"CancelInitiated":false,"ImmediateOrCancel":false,"IsConditional":false,"Condition":"NONE","ConditionTarget":null} printf("uuid.(%s) finished.(%s)\n",ptr->orderid,jprint(retjson,0)); - ptr->completed = (uint32_t)time(NULL); - ptr->pending = 0; - } - free_json(retjson); - } - free(retstr); - } - } -} - -void marketmaker_pendinginit(char *exchange,char *base,char *rel) -{ - 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 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - //printf("%s\n",jprint(retjson,0)); - if ( is_cJSON_True(jobj(retjson,"success")) != 0 && (array= jarray(&n,retjson,"result")) != 0 ) - { - for (i=0; iexchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 ) - continue; - if ( strcmp(ptr->orderid,orderid) == 0 ) - { - ptr->pending = (uint32_t)time(NULL); - ptr->completed = 0; - printf("%s pending\n",orderid); - break; - } - } - if ( j == Num_Pending ) - { - if ( jstr(item,"OrderType") != 0 ) - { - if ( strcmp(jstr(item,"OrderType"),"LIMIT_BUY") == 0 ) - dir = 1; - else if ( strcmp(jstr(item,"OrderType"),"LIMIT_SELL") == 0 ) - dir = -1; - else dir = 0; - if ( dir != 0 ) - marketmaker_queue(exchange,base,rel,dir,jdouble(item,"Limit"),jdouble(item,"QuantityRemaining"),item); - else printf("no dir (%s) (%s)\n",jprint(item,0),jstr(item,"OrderType")); - } - } - } - } - } - free_json(retjson); - } - free(retstr); - } -} - -double marketmaker_filled(char *exchange,char *base,char *rel,double *buyvolp,double *sellvolp,double *pendingbidsp,double *pendingasksp) -{ - double pricesum = 0.,volsum = 0.; struct mmpending_order *ptr; int32_t i; - *pendingbidsp = *pendingasksp = 0.; - for (i=0; iexchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 ) - continue; - if ( ptr->completed != 0 ) - { - if ( ptr->reported == 0 ) - { - if ( ptr->dir > 0 ) - (*buyvolp) += ptr->volume; - else if ( ptr->dir < 0 ) - (*sellvolp) += ptr->volume; - pricesum += ptr->volume * ptr->price; - volsum += ptr->volume; - ptr->reported = (uint32_t)time(NULL); - printf("REPORT dir.%d vol %.8f\n",ptr->dir,ptr->volume); - } - } - else if ( ptr->pending != 0 ) // alternative is error or cancelled - { - if ( ptr->dir > 0 ) - (*pendingbidsp) += ptr->volume; - else if ( ptr->dir < 0 ) - (*pendingasksp) += ptr->volume; - } - } - if ( volsum != 0. ) - pricesum /= volsum; - return(pricesum); -} - -int32_t marketmaker_prune(char *exchange,char *base,char *rel,int32_t polarity,double bid,double ask,double separation) -{ - int32_t i,n = 0; struct mmpending_order *ptr; - for (i=0; iexchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 ) - continue; - if ( ptr->pending != 0 && ptr->cancelstarted == 0 ) - { - if ( polarity != 0 ) - { - if ( ((ptr->dir*polarity > 0 && ptr->price < bid-separation) || (ptr->dir*polarity < 0 && ptr->price > ask+separation)) ) - { - printf("polarity.%d dir.%d price.%f bid.%f ask.%f\n",polarity,ptr->dir,ptr->price,bid,ask); - marketmaker_cancel(ptr), n++; - } - } - /*else - {,*prunebid=0,*pruneask=0; double lowbid=0.,highask=0. - if ( ptr->dir > 0 && (lowbid == 0. || ptr->price < lowbid) ) - { - lowbid = ptr->price; - prunebid = ptr; - } - else if ( ptr->dir < 0 && (highask == 0. || ptr->price > highask) ) - { - highask = ptr->price; - pruneask = ptr; - } - }*/ - } - } - /*if ( polarity == 0 ) - { - if ( prunebid != 0 && fabs(prunebid->price - bid) > separation ) - marketmaker_cancel(prunebid), n++; - if ( pruneask != 0 && fabs(pruneask->price - ask) > separation ) - marketmaker_cancel(pruneask), n++; - }*/ - return(n); -} - -void marketmaker_volumeset(double *bidincrp,double *askincrp,double incr,double buyvol,double pendingbids,double sellvol,double pendingasks,double maxexposure) -{ - *bidincrp = *askincrp = incr; - //if ( pendingbids >= pendingasks+maxexposure ) - // *bidincrp = 0.; - //else if ( pendingasks >= pendingbids+maxexposure ) - // *askincrp = 0.; - if ( *bidincrp > 0. && pendingbids + *bidincrp > maxexposure ) - *bidincrp = (maxexposure - *bidincrp); - if ( *askincrp > 0. && pendingasks + *askincrp > maxexposure ) - *askincrp = (maxexposure - *askincrp); - if ( *bidincrp < 0. ) - *bidincrp = 0.; - if ( *askincrp < 0. ) - *askincrp = 0.; -} - -int32_t marketmaker_spread(char *exchange,char *base,char *rel,double bid,double bidvol,double ask,double askvol,double separation) -{ - int32_t nearflags[2],i,n = 0; struct mmpending_order *ptr; cJSON *retjson,*vals; char *retstr,postdata[1024],url[128]; double vol,spread_ratio; - memset(nearflags,0,sizeof(nearflags)); - if ( strcmp("DEX",exchange) != 0 ) - { - for (i=0; iexchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 ) - continue; - if ( ptr->pending != 0 && ptr->cancelstarted == 0 ) - { - if ( bid > SMALLVAL && bidvol > SMALLVAL && ptr->dir > 0 && fabs(bid - ptr->price) < separation ) - { - //printf("bid %.8f near %.8f\n",bid,ptr->price); - nearflags[0]++; - } - if ( ask > SMALLVAL && askvol > SMALLVAL && ptr->dir < 0 && fabs(ask - ptr->price) < separation ) - { - //printf("%.8f near %.8f\n",ask,ptr->price); - nearflags[1]++; - } - } - } - } - //printf("spread.%s (%.8f %.6f) (%.8f %.6f)\n",exchange,bid,bidvol,ask,askvol); - if ( bid > SMALLVAL && bidvol > SMALLVAL && nearflags[0] == 0 ) - { - if ( strcmp("DEX",exchange) == 0 && strcmp(base,"KMD") == 0 && strcmp(rel,"BTC") == 0 ) - { - if ( ask > SMALLVAL && askvol > SMALLVAL ) - { - /*li.profit = jdouble(vals,"profit"); - li.refprice = jdouble(vals,"refprice"); - li.bid = jdouble(vals,"bid"); - li.ask = jdouble(vals,"ask"); - if ( (li.minvol= jdouble(vals,"minvol")) <= 0. ) - li.minvol = (strcmp("BTC",base) == 0) ? 0.0001 : 0.001; - if ( (li.maxvol= jdouble(vals,"maxvol")) < li.minvol ) - li.maxvol = li.minvol;*/ - //curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"MVP\",\"vals\":{\"rel\":\"USD\",\"bid\":0.09,\"ask\":0.11,\"maxvol\":100}}" - vals = cJSON_CreateObject(); - jaddstr(vals,"rel","BTC"); - jaddnum(vals,"bid",bid); - jaddnum(vals,"ask",ask); - vol = bidvol > askvol ? askvol : bidvol; - jaddnum(vals,"maxvol",vol); - jaddnum(vals,"minvol",vol*0.1 > 100 ? 100 : vol * 0.1); - sprintf(url,"%s/?",IGUANA_URL); - sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"%s\",\"vals\":%s}",base,jprint(vals,1)); - //printf("(%s)\n",postdata); - if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata,0)) != 0 ) - { - //printf("(%s) -> (%s)\n",postdata,retstr); - free(retstr); - } - spread_ratio = .5 * ((ask - bid) / (bid + ask)); - for (i=0; i SMALLVAL ) - { - vals = cJSON_CreateObject(); - jaddstr(vals,"rel",CURRENCIES[i]); - jaddnum(vals,"bid",PAXPRICES[i] * (1. - spread_ratio)); - jaddnum(vals,"ask",PAXPRICES[i] * (1. + spread_ratio)); - jaddnum(vals,"maxvol",vol * PAXPRICES[i]); - jaddnum(vals,"minvol",MAX(1,(int32_t)(vol * 0.01 * PAXPRICES[i]))); - sprintf(url,"%s/?",IGUANA_URL); - sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"%s\",\"vals\":%s}","KMD",jprint(vals,1)); - if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata,0)) != 0 ) - { - //printf("(%s) -> (%s)\n",postdata,retstr); - free(retstr); - } - } -//break; - } - } else printf("unsupported ask only for DEX %s/%s\n",base,rel); - } - else if ( (retstr= DEX_trade(exchange,base,rel,1,bid,bidvol)) != 0 ) - { - //printf("DEX_trade.(%s)\n",retstr); - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - marketmaker_queue(exchange,base,rel,1,bid,bidvol,retjson); - free_json(retjson); - } - free(retstr); - } //else printf("skip bid %s %.8f vol %f\n",exchange,bid,bidvol); - } - if ( ask > SMALLVAL && askvol > SMALLVAL && nearflags[1] == 0 && strcmp("DEX",exchange) != 0 ) - { - if ( (retstr= DEX_trade(exchange,base,rel,-1,ask,askvol)) != 0 ) - { - //printf("DEX_trade.(%s)\n",retstr); - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - marketmaker_queue(exchange,base,rel,-1,ask,askvol,retjson); - free_json(retjson); - } - free(retstr); - } - } //else printf("skip ask %s %.8f vol %f\n",exchange,bid,bidvol); - return(n); -} - -double marketmaker_updateprice(char *name,char *base,char *rel,double theoretical,double *incrp) -{ - static uint32_t counter; - cJSON *fiatjson; double USD_average=0.,usdprice=0.,CMC_average=0.,avebid=0.,aveask=0.,val,changes[3],highbid=0.,lowask=0.; - if ( (val= get_theoretical(&avebid,&aveask,&highbid,&lowask,&CMC_average,changes,name,base,rel,&USD_average)) != 0. ) - { - if ( theoretical == 0. ) - { - theoretical = val; - if ( *incrp > 2 ) - { - *incrp = (int32_t)*incrp; - *incrp += 0.777; - } - } else theoretical = (theoretical + val) * 0.5; - if ( (counter++ % 12) == 0 ) - { - if ( USD_average > SMALLVAL && CMC_average > SMALLVAL && theoretical > SMALLVAL ) - { - usdprice = USD_average * (theoretical / CMC_average); - printf("USD %.4f <- (%.6f * (%.8f / %.8f))\n",usdprice,USD_average,theoretical,CMC_average); - PAXPRICES[0] = usdprice; - if ( (fiatjson= yahoo_allcurrencies()) != 0 ) - { - marketmaker_fiatupdate(fiatjson); - free_json(fiatjson); - } - } - } - LP_priceupdate(base,rel,theoretical,avebid,aveask,highbid,lowask,PAXPRICES); - } - return(theoretical); -} - -void marketmaker(double minask,double maxbid,char *baseaddr,char *reladdr,double start_BASE,double start_REL,double profitmargin,double maxexposure,double ratioincr,char *exchange,char *name,char *base,char *rel) -{ - char *retstr; double bid,ask,start_DEXbase,start_DEXrel,DEX_base = 0.,DEX_rel = 0.,balance_base=0.,balance_rel=0.,mmbid,mmask,aveprice,incr,pendingbids,pendingasks,buyvol,sellvol,bidincr,askincr,filledprice,avebid=0.,aveask=0.,highbid=0.,lowask=0.,theoretical = 0.; uint32_t lasttime = 0; - incr = maxexposure * ratioincr; - buyvol = sellvol = 0.; - start_DEXbase = dex_balance(base,baseaddr); - start_DEXrel = dex_balance(rel,reladdr); - while ( 1 ) - { - if ( time(NULL) > lasttime+60 ) - { - if ( (theoretical= marketmaker_updateprice(name,base,rel,theoretical,&incr)) != 0. ) - { - if ( lasttime == 0 ) - maxexposure /= theoretical; - } - if ( strcmp(exchange,"bittrex") == 0 ) - { - balance_base = bittrex_balance(base,""); - balance_rel = bittrex_balance(rel,""); - DEX_base = dex_balance(base,baseaddr); - DEX_rel = dex_balance(rel,reladdr); - } else printf("add support for %s balance\n",exchange); - lasttime = (uint32_t)time(NULL); - } - marketmaker_pendingupdate(exchange,base,rel); - if ( theoretical > SMALLVAL && avebid > SMALLVAL && aveask > SMALLVAL ) - { - aveprice = (avebid + aveask) * 0.5; - // if order is filled, theoretical <- filled (theoretical + price)/2 - if ( (filledprice= marketmaker_filled(exchange,base,rel,&buyvol,&sellvol,&pendingbids,&pendingasks)) != 0. ) - theoretical = (theoretical + filledprice) * 0.5; - buyvol = sellvol = 0; - if ( (balance_base + DEX_base) < (start_BASE + start_DEXbase) ) - sellvol += ((start_BASE + start_DEXbase) - (balance_base + DEX_base)); - else buyvol += ((balance_base + DEX_base) - (start_BASE + start_DEXbase)); - if ( (balance_rel + DEX_rel) < (start_REL + start_DEXrel) ) - buyvol += ((start_REL + start_DEXrel) - (balance_rel + DEX_rel)) / theoretical; - else sellvol += ((balance_rel + DEX_rel) - (start_REL + start_DEXrel)) / theoretical; - mmbid = theoretical - theoretical*profitmargin; - mmask = theoretical + theoretical*profitmargin; - // if any existing order exceeds double margin distance, cancel - marketmaker_prune(exchange,base,rel,1,mmbid - theoretical*profitmargin,mmask + theoretical*profitmargin,0.); - // if new prices crosses existing order, cancel old order first - marketmaker_prune(exchange,base,rel,-1,mmbid,mmask,0.); - //printf("(%.8f %.8f) ",mmbid,mmask); - if ( (1) ) - { - if ( mmbid >= lowask || (maxbid > SMALLVAL && mmbid > maxbid) ) //mmbid < highbid || - { - printf("clear mmbid %.8f lowask %.8f maxbid %.8f\n",mmbid,lowask,maxbid); - mmbid = 0.; - } - if ( mmask <= highbid || (minask > SMALLVAL && mmask < minask) ) // mmask > lowask || - mmask = 0.; - } - marketmaker_volumeset(&bidincr,&askincr,incr,buyvol,pendingbids,sellvol,pendingasks,maxexposure); - printf("AVE.(%.8f %.8f) hbla %.8f %.8f bid %.8f ask %.8f theory %.8f buys.(%.6f %.6f) sells.(%.6f %.6f) incr.(%.6f %.6f) balances.(%.8f + %.8f, %.8f + %.8f) test %f\n",avebid,aveask,highbid,lowask,mmbid,mmask,theoretical,buyvol,pendingbids,sellvol,pendingasks,bidincr,askincr,balance_base,DEX_base,balance_rel,DEX_rel,(aveask - avebid)/aveprice); - if ( (retstr= DEX_swapstatus()) != 0 ) - printf("%s\n",retstr), free(retstr); - printf("%s %s %s, %s %s %s\n",base,DEX_baseaddr,DEX_balance("DEX",base,DEX_baseaddr),rel,DEX_reladdr,DEX_balance("DEX",rel,DEX_reladdr)); - if ( (aveask - avebid)/aveprice > profitmargin ) - bid = highbid * (1 - profitmargin), ask = lowask * (1 + profitmargin); - else bid = avebid - profitmargin*aveprice, ask = avebid + profitmargin*aveprice; - marketmaker_spread("DEX",base,rel,bid,incr,ask,incr,profitmargin*aveprice*0.5); - if ( (pendingbids + buyvol) > (pendingasks + sellvol) && (pendingbids + buyvol) > bidincr ) - { - bidincr *= ((double)(pendingasks + sellvol) / ((pendingbids + buyvol) + (pendingasks + sellvol))); - printf("bidincr %f buy.(%f + %f) sell.(%f + %f)\n",bidincr,pendingbids,buyvol,pendingasks,sellvol); - if ( bidincr < 0.1*incr ) - bidincr = 0.1*incr; - if ( bidincr > 1. ) - bidincr = (int32_t)bidincr + 0.777; - } - if ( (pendingbids + buyvol) < (pendingasks + sellvol) && (pendingasks + sellvol) > askincr ) - { - askincr *= (double)(pendingbids + buyvol) / ((pendingbids + buyvol) + (pendingasks + sellvol)); - if ( askincr < 0.1*incr ) - askincr = 0.1*incr; - if ( askincr > 1. ) - askincr = (int32_t)askincr + 0.777; - } - //printf("mmbid %.8f %.6f, mmask %.8f %.6f\n",mmbid,bidincr,mmask,askincr); - marketmaker_spread(exchange,base,rel,mmbid,bidincr,mmask,askincr,profitmargin*aveprice*0.5); - sleep(60); - } - } -} - #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; @@ -877,10 +86,83 @@ void LP_main(void *ptr) 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; + char dirname[512],*passphrase; double incr; cJSON *retjson; OS_init(); + if ( strstr(argv[0],"btc2kmd") != 0 && argv[1] != 0 ) + { + uint8_t addrtype,rmd160[20],rmd160b[20]; char coinaddr[64],coinaddr2[64]; + bitcoin_addr2rmd160(0,&addrtype,rmd160,(char *)argv[1]); + 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); + } + else if ( argv[1] != 0 && strcmp(argv[1],"hush") == 0 ) + { + uint32_t timestamp; char str[65],wifstr[128]; bits256 privkey; int32_t i; + timestamp = (uint32_t)time(NULL); + //printf("start hush vanitygen t.%u\n",timestamp); + for (i=0; i<1000000000; i++) + { + OS_randombytes(privkey.bytes,sizeof(privkey)); + privkey.bytes[0] = 0x0e; + privkey.bytes[1] = 0x5b; + privkey.bytes[2] = 0xf9; + privkey.bytes[3] = 0xc6; + privkey.bytes[4] = 0x06; + privkey.bytes[5] = 0xdd; + privkey.bytes[6] = 0xbb; + bitcoin_priv2wiflong(0xab,wifstr,privkey,0x36); + if ( wifstr[2] == 'x' && wifstr[4] == 'H' && wifstr[5] == 'u' && wifstr[6] == 's' )//&& wifstr[3] == 'x' ) + { + if ( wifstr[7] == 'h' && wifstr[8] == 'L' && wifstr[9] == 'i' ) + { + //printf("i.%d %s -> wif.%s\n",i,bits256_str(str,privkey),wifstr); + if ( wifstr[10] == 's' && wifstr[11] == 't' ) + { + printf("{\"iters\":%d,\"privkey\":\"%s\",\"wif\":\"%s\"}\n",i,bits256_str(str,privkey),wifstr); + break; + } + } + } //else printf("failed %s\n",wifstr); + } + //printf("done hush vanitygen done %u elapsed %d\n",(uint32_t)time(NULL),(uint32_t)time(NULL) - timestamp); + exit(0); + } + else if ( argv[1] != 0 && strcmp(argv[1],"vanity") == 0 && argv[2] != 0 ) + { + uint32_t timestamp; uint8_t pubkey33[33]; char str[65],coinaddr[64],wifstr[128]; bits256 privkey; int32_t i,len; void *ctx; + ctx = bitcoin_ctx(); + len = (int32_t)strlen(argv[2]); + timestamp = (uint32_t)time(NULL); + printf("start vanitygen (%s).%d t.%u\n",argv[2],len,timestamp); + for (i=0; i<1000000000; i++) + { + OS_randombytes(privkey.bytes,sizeof(privkey)); + bitcoin_priv2pub(ctx,pubkey33,coinaddr,privkey,0,60); + if ( strncmp(coinaddr+1,argv[2],len-1) == 0 ) + { + bitcoin_priv2wif(0,wifstr,privkey,188); + printf("i.%d %s -> %s wif.%s\n",i,bits256_str(str,privkey),coinaddr,wifstr); + if ( coinaddr[1+len-1] == argv[2][len-1] ) + break; + } //else printf("failed %s\n",wifstr); + } + printf("done vanitygen.(%s) done %u elapsed %d\n",argv[2],(uint32_t)time(NULL),(uint32_t)time(NULL) - timestamp); + exit(0); + } sprintf(dirname,"%s",GLOBAL_DBDIR), OS_ensure_directory(dirname); sprintf(dirname,"%s/SWAPS",GLOBAL_DBDIR), OS_ensure_directory(dirname); sprintf(dirname,"%s/PRICES",GLOBAL_DBDIR), OS_ensure_directory(dirname); @@ -894,12 +176,17 @@ int main(int argc, const char * argv[]) #else if ( argc == 1 ) { + //LP_privkey_tests(); 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 ) @@ -910,64 +197,6 @@ int main(int argc, const char * argv[]) incr = 100.; while ( (1) ) sleep(100000); - profitmargin = jdouble(retjson,"profitmargin"); - minask = jdouble(retjson,"minask"); - maxbid = jdouble(retjson,"maxbid"); - maxexposure = jdouble(retjson,"maxexposure"); - incrratio = jdouble(retjson,"lotratio"); - start_base = jdouble(retjson,"start_base"); - start_rel = jdouble(retjson,"start_rel"); - apikey = jstr(retjson,"apikey"); - apisecret = jstr(retjson,"apisecret"); - base = jstr(retjson,"base"); - name = jstr(retjson,"name"); - rel = jstr(retjson,"rel"); - blocktrail = jstr(retjson,"blocktrail"); - exchange = jstr(retjson,"exchange"); - PAXACTIVE = juint(retjson,"paxactive"); - if ( profitmargin < 0. || maxexposure <= 0. || incrratio <= 0. || apikey == 0 || apisecret == 0 || base == 0 || name == 0 || rel == 0 || exchange == 0 || blocktrail == 0 ) - { - printf("illegal parameter (%s)\n",jprint(retjson,0)); - exit(-1); - } - if ( (retstr= iguana_walletpassphrase(passphrase,999999)) != 0 ) - { - printf("(%s/%s) login.(%s)\n",base,rel,retstr); - if ( (loginjson= cJSON_Parse(retstr)) != 0 ) - { - if ( PAXACTIVE != 0 ) - { - for (i=0; i<32; i++) - { - if ( ((1< 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),jprint(json,0),*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); @@ -597,15 +607,16 @@ void LP_rpc_processreq(void *_ptr) static uint32_t spawned,maxspawned; char filetype[128],content_type[128]; int32_t recvlen,flag,postflag=0,contentlen,remains,sock,numsent,jsonflag=0,hdrsize,len; - char helpname[512],remoteaddr[64],*buf,*retstr,*space,*jsonbuf; struct rpcrequest_info *req = _ptr; + char helpname[512],remoteaddr[64],*buf,*retstr,space[8192],space2[32786],*jsonbuf; struct rpcrequest_info *req = _ptr; uint32_t ipbits,i,size = IGUANA_MAXPACKETSIZE + 512; ipbits = req->ipbits;; expand_ipbits(remoteaddr,ipbits); sock = req->sock; recvlen = flag = 0; retstr = 0; - space = calloc(1,size); + //space = calloc(1,size); jsonbuf = calloc(1,size); + //printf("alloc jsonbuf.%p\n",jsonbuf); remains = size-1; buf = jsonbuf; spawned++; @@ -624,10 +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; @@ -694,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); - 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)); + 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)+1); response[0] = '\0'; strcat(response,hdrs); strcat(response,retstr); strcat(response,"\n"); if ( retstr != space ) + { + //printf("free retstr0.%p\n",retstr); free(retstr); + } retstr = response; //printf("RET.(%s)\n",retstr); } @@ -727,16 +747,28 @@ void LP_rpc_processreq(void *_ptr) printf("iguana sent.%d remains.%d of recvlen.%d (%s)\n",numsent,remains,recvlen,jsonbuf); } } - if ( retstr != space) + if ( retstr != space && retstr != space2 ) + { + //printf("free retstr.%p\n",retstr); free(retstr); + } } - free(space); + //free(space); + //printf("free jsonbuf.%p\n",jsonbuf); free(jsonbuf); closesocket(sock); - portable_mutex_lock(&LP_gcmutex); - DL_APPEND(LP_garbage_collector,req); + 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--; - portable_mutex_unlock(&LP_gcmutex); } extern int32_t IAMLP; @@ -761,7 +793,7 @@ void stats_rpcloop(void *args) //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(">>>>>>>>>> DEX stats 127.0.0.1:%d bind sock.%d DEX stats API enabled at unixtime.%u <<<<<<<<<\n",port,bindsock,(uint32_t)time(NULL)); } //printf("after sock.%d\n",sock); clilen = sizeof(cli_addr); @@ -785,12 +817,16 @@ void stats_rpcloop(void *args) } #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("port.%u RPC_port.%u ipbits %x != %x\n",port,RPC_port,ipbits,localhostbits); closesocket(sock); continue; } req = calloc(1,sizeof(*req)); + //printf("alloc req.%p\n",req); req->sock = sock; req->ipbits = ipbits; req->port = port; diff --git a/iguana/exchanges/supernet b/iguana/exchanges/supernet new file mode 100755 index 000000000..25e6af7e4 --- /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\":11000000}, {\"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\":\"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\":11000000}, {\"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/ticker b/iguana/exchanges/ticker new file mode 100755 index 000000000..2c1766600 --- /dev/null +++ b/iguana/exchanges/ticker @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"ticker\",\"base\":\"REVS\",\"rel\":\"KMD\"}" diff --git a/iguana/exchanges/trackbtc b/iguana/exchanges/trackbtc new file mode 100644 index 000000000..79366a1c4 --- /dev/null +++ b/iguana/exchanges/trackbtc @@ -0,0 +1,2 @@ +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"$coin\",\"offset\":0.0,\"refbase\":\"KMD\",\"refrel\":\"BTC\",\"factor\":$invprice,\"margin\":$margin}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"$coin\",\"rel\":\"KMD\",\"offset\":0.0,\"refbase\":\"BTC\",\"refrel\":\"KMD\",\"factor\":$price,\"margin\":$margin}" 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..eb058e620 100755 --- a/iguana/iguana777.h +++ b/iguana/iguana777.h @@ -18,6 +18,19 @@ 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 + 8. m_splitfunds + + */ + #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 c8808191b..b4a1cdef1 100755 --- a/iguana/iguana_notary.c +++ b/iguana/iguana_notary.c @@ -558,7 +558,78 @@ 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", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "MNZ", "CHIPS", "MSHARK", "AXO", "ETOMIC", "BTCH" }; // "LTC", + +void _iguana_notarystats(char *fname,int32_t totals[64],int32_t dispflag) +{ + FILE *fp; uint64_t signedmask; long fpos,startfpos; int32_t i,height,iter,prevheight; + if ( (fp= fopen(fname,"rb")) != 0 ) + { + printf("opened %s\n",fname); + startfpos = 0; + prevheight = -1; + for (iter=0; iter<2; iter++) + { + while ( 1 ) + { + fpos = ftell(fp); + if (fread(&height,1,sizeof(height),fp) == sizeof(height) && fread(&signedmask,1,sizeof(signedmask),fp) == sizeof(signedmask) ) + { + //printf("%6d %016llx\n",height,(long long)signedmask); + if ( height < prevheight ) + { + startfpos = fpos; + if ( iter == 0 ) + printf("found reversed height %d vs %d\n",height,prevheight); + else printf("fpos.%ld fatal unexpected height reversal %d vs %d\n",fpos,height,prevheight); + } + if ( iter == 1 && (height >= 180000 || strcmp(fname,"signedmasks") != 0) ) + { + for (i=0; i<64; i++) + { + if ( ((1LL << i) & signedmask) != 0 ) + { + totals[i]++; + if ( dispflag > 1 ) + printf("%2d ",i); + } + } + if ( dispflag > 1 ) + printf("height.%d %016llx %s\n",height,(long long)signedmask,fname); + } + prevheight = height; + } else break; + } + if ( iter == 0 ) + { + prevheight = -1; + fseek(fp,startfpos,SEEK_SET); + printf("set startfpos %ld\n",startfpos); + } + } + fclose(fp); + if ( dispflag != 0 ) + { + printf("after %s\n",fname); + for (i=0; i<64; i++) + { + if ( totals[i] != 0 ) + printf("%s, %d\n",Notaries_elected[i][0],totals[i]); + } + } + } else printf("couldnt open.(%s)\n",fname); +} + +void iguana_notarystats(int32_t totals[64],int32_t dispflag) +{ + int32_t i; char fname[512]; + _iguana_notarystats("signedmasks",totals,dispflag); + for (i=0; i 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..b3b789b32 --- /dev/null +++ b/iguana/m_notary_run @@ -0,0 +1,50 @@ +#!/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 +coins/axo_7776 +coins/etomic_7776 +coins/btch_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..75f4b0cfd 100755 --- a/iguana/m_splitfund +++ b/iguana/m_splitfund @@ -13,7 +13,7 @@ curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"JUMBLR\",\"agent\":\"igua curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"BET\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" 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}" @@ -23,37 +23,40 @@ curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"KV\",\"agent\":\"iguana\" curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CEAL\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MESH\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MNZ\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"AXO\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"BTCH\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}" +curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"ETOMIC\",\"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..0528393ed 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); @@ -2198,11 +2198,19 @@ void iguana_main(void *arg) { if ( strcmp((char *)arg,"OStests") == 0 ) do_OStests = 1; + else if ( strcmp((char *)arg,"stats") == 0 ) + { + void iguana_notarystats(int32_t totals[64],int32_t dispflag); + int32_t totals[64]; + memset(totals,0,sizeof(totals)); + iguana_notarystats(totals,1); + exit(0); + } else if ( strcmp((char *)arg,"notary") == 0 ) { myinfo->rpcport = IGUANA_NOTARYPORT; myinfo->IAMNOTARY = 1; - myinfo->DEXEXPLORER = 1; + myinfo->DEXEXPLORER = 0;//1; disable as SPV is used now } else if ( strncmp((char *)arg,"-port=",6) == 0 ) { @@ -2262,22 +2270,6 @@ void iguana_main(void *arg) { basilisks_init(myinfo); } - if ( (0) ) - { - char *jsonstr = "[\"03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828\", \"02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344\", \"03750cf30d739cd7632f77c1c02812dd7a7181628b0558058d4755838117e05339\", \"0394f3529d2e8cc69ffa7a2b55f3761e7be978fa1896ef4c55dc9c275e77e5bf5e\", \"0243c1eeb3777af47187d542e5f8c84f0ac4b05cf5a7ad77faa8cb6d2d56db7823\", \"02bb298844175640a34e908ffdfa2839f77aba3d5edadefee16beb107826e00063\", \"02fa88e549b4b871498f892e527a5d57287916809f8cc3163f641d71c535e8df5a\", \"032f799e370f06476793a122fcd623db7804898fe5aef5572095cfee6353df34bf\", \"02c06fe5401faff4442ef87b7d1b56c2e5a214166615f9a2f2030c71b0cb067ae8\", \"038ac67ca49a8169bcc5de83fe020071095a2c3b2bc4d1c17386977329758956d5\"]"; - - int32_t i,n; char coinaddr[64]; uint8_t pubkey33[33]; double val = 0.1; cJSON *array; - if ( (array= cJSON_Parse(jsonstr)) != 0 ) - { - n = cJSON_GetArraySize(array); - for (i=0; i= -1 && endian <= 1); - assert (size > 0 || u->_mp_size == 0); - - un = u->_mp_size; - count = 0; - if (un != 0) - { - size_t k; - uint8_t *p; - ptrdiff_t word_step; - /* The current (partial) limb. */ - mp_limb_t limb; - /* The number of bytes left to to in this limb. */ - size_t bytes; - /* The index where the limb was read. */ - mp_size_t i; - - un = GMP_ABS (un); - - /* Count bytes in top limb. */ - limb = u->_mp_d[un-1]; - assert (limb != 0); - - k = 0; - do { - k++; limb >>= CHAR_BIT; - } while (limb != 0); - - count = (k + (un-1) * sizeof (mp_limb_t) + size - 1) / size; - - if (!r) - r = malloc (count * size); - - if (endian == 0) - endian = gmp_detect_endian (); - - p = (uint8_t *) r; - - word_step = (order != endian) ? 2 * size : 0; - - /* Process bytes from the least significant end, so point p at the - least significant word. */ - if (order == 1) - { - p += size * (count - 1); - word_step = - word_step; - } - - /* And at least significant byte of that word. */ - if (endian == 1) - p += (size - 1); - - for (bytes = 0, i = 0, k = 0; k < count; k++, p += word_step) - { - size_t j; - for (j = 0; j < size; j++, p -= (ptrdiff_t) endian) - { - if (bytes == 0) - { - if (i < un) - limb = u->_mp_d[i++]; - bytes = sizeof (mp_limb_t); - } - *p = limb; - limb >>= CHAR_BIT; - bytes--; - } - } - assert (i == un); - assert (k == count); + size_t count; + mp_size_t un; + + if (nails != 0) + gmp_die ("mpz_import: Nails not supported."); + + assert (order == 1 || order == -1); + assert (endian >= -1 && endian <= 1); + assert (size > 0 || u->_mp_size == 0); + + un = u->_mp_size; + count = 0; + if (un != 0) + { + size_t k; + uint8_t *p; + ptrdiff_t word_step; + /* The current (partial) limb. */ + mp_limb_t limb; + /* The number of bytes left to to in this limb. */ + size_t bytes; + /* The index where the limb was read. */ + mp_size_t i; + + un = GMP_ABS (un); + + /* Count bytes in top limb. */ + limb = u->_mp_d[un-1]; + assert (limb != 0); + + k = 0; + do { + k++; limb >>= CHAR_BIT; + } while (limb != 0); + + count = (k + (un-1) * sizeof (mp_limb_t) + size - 1) / size; + + if (!r) + r = malloc (count * size); + + if (endian == 0) + endian = gmp_detect_endian (); + + p = (uint8_t *) r; + + word_step = (order != endian) ? 2 * size : 0; + + /* Process bytes from the least significant end, so point p at the + least significant word. */ + if (order == 1) + { + p += size * (count - 1); + word_step = - word_step; + } + + /* And at least significant byte of that word. */ + if (endian == 1) + p += (size - 1); + + for (bytes = 0, i = 0, k = 0; k < count; k++, p += word_step) + { + size_t j; + for (j = 0; j < size; j++, p -= (ptrdiff_t) endian) + { + if (bytes == 0) + { + if (i < un) + limb = u->_mp_d[i++]; + bytes = sizeof (mp_limb_t); + } + *p = limb; + //printf("{%02x} ",*p); + limb >>= CHAR_BIT; + bytes--; + } + } + assert (i == un); + assert (k == count); } - - if (countp) - *countp = count; - - return r; + + if (countp) + *countp = count; + //printf("mpz_export.%d\n",(int32_t)count); + return r; } ///////////////////////////////// @@ -4360,44 +4361,6 @@ char *bitcoin_base58encode(char *coinaddr,uint8_t *data,int32_t datalen) return(coinaddr); } -int32_t bitcoin_base58decode(uint8_t *data,char *coinaddr) -{ - uint32_t zeroes,be_sz=0; size_t count; const char *p,*p1; mpz_t bn58,bn; - mpz_init_set_ui(bn58,58); - mpz_init_set_ui(bn,0); - while ( isspace((uint32_t)(*coinaddr & 0xff)) ) - coinaddr++; - for (p=coinaddr; *p; p++) - { - p1 = strchr(base58_chars,*p); - if ( p1 == 0 ) - { - while (isspace((uint32_t)*p)) - p++; - if ( *p != '\0' ) - { - mpz_clear(bn), mpz_clear(bn58); - return(-1); - } - break; - } - mpz_mul(bn,bn,bn58); - mpz_add_ui(bn,bn,(int32_t)(p1 - base58_chars)); - } - zeroes = 0; - for (p=coinaddr; *p==base58_chars[0]; p++) - data[zeroes++] = 0; - mpz_export(data+zeroes,&count,1,sizeof(data[0]),-1,0,bn); - if ( count >= 2 && data[count - 1] == 0 && data[count - 2] >= 0x80 ) - count--; - be_sz = (uint32_t)count + (uint32_t)zeroes; - //memset(data,0,be_sz); - //for (i=0; i %s\n",bits256_str(str,privkey)); + }*/ + if ( count >= 2 && data[count - 1] == 0 && data[count - 2] >= 0x80 ) + count--; + be_sz = (uint32_t)count + (uint32_t)zeroes; + //memset(data,0,be_sz); + //for (i=0; i