diff --git a/crypto777/bitcoind_RPC.c b/crypto777/bitcoind_RPC.c index f624cd342..6bb5d3a12 100755 --- a/crypto777/bitcoind_RPC.c +++ b/crypto777/bitcoind_RPC.c @@ -96,6 +96,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 +113,10 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char * rpcstr = 0; } if ( rpcstr != 0 ) + { + //printf("free rpcstr.%p\n",rpcstr); free(rpcstr); + } } else retstr = rpcstr; free_json(json); //fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: postprocess returns.(%s)\n",retstr); @@ -231,30 +235,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_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/iguana/coins/basilisk/mshark b/iguana/coins/basilisk/mshark new file mode 100644 index 000000000..c664fe0b5 --- /dev/null +++ b/iguana/coins/basilisk/mshark @@ -0,0 +1,2 @@ +curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"SHARK.conf\",\"path\":\"${HOME#"/"}/.komodo/SHARK\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":0,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"SHARK\",\"name\":\"SHARK\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"54a5e30c\",\"p2p\":14103,\"rpc\":14104,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}" + diff --git a/iguana/coins/mshark_7776 b/iguana/coins/mshark_7776 new file mode 100644 index 000000000..d1a7bc525 --- /dev/null +++ b/iguana/coins/mshark_7776 @@ -0,0 +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\":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..c7e5d311a 100755 --- a/iguana/dpow/dpow_network.c +++ b/iguana/dpow/dpow_network.c @@ -584,6 +584,8 @@ char *dex_response(int32_t *broadcastflagp,struct supernet_info *myinfo,struct d { char buf[65],*retstr = 0; int32_t i,datalen; bits256 hash2; cJSON *retjson=0; struct iguana_info *coin; struct dex_request dexreq; *broadcastflagp = 0; +return(clonestr("{\"error\":\"basilisk disabled\"}")); + if ( strcmp(dexp->handler,"request") == 0 ) { datalen = dex_rwrequest(0,dexp->packet,&dexreq); diff --git a/iguana/exchanges/LP_RTmetrics.c b/iguana/exchanges/LP_RTmetrics.c index 53466e5e7..7bbab1c38 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,8 +130,8 @@ 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); + LP_RTmetrics_pendingswap(srcpub,LP_kmdvalue(base,basesatoshis)); + LP_RTmetrics_pendingswap(destpub,LP_kmdvalue(rel,relsatoshis)); if ( 0 && (retstr= basilisk_swapentry(requestid,quoteid)) != 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..f9c212cd1 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); @@ -2340,20 +2340,20 @@ int32_t iguana_scriptgen(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,int32_t return(scriptlen); } -int32_t bitcoin_scriptget(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint32_t *hashtypep,uint32_t *sigsizep,uint32_t *pubkeysizep,uint8_t **userdatap,uint32_t *userdatalenp,struct vin_info *vp,uint8_t *scriptsig,int32_t len,int32_t spendtype) +int32_t bitcoin_scriptget(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint32_t *hashtypep,uint32_t *sigsizep,uint32_t *pubkeysizep,uint8_t **userdatap,uint32_t *userdatalenp,struct vin_info *vp,uint8_t *scriptsig,int32_t len,int32_t spendtype,int32_t zcash) { int32_t j,n,siglen,plen; uint8_t *p2shscript; j = n = 0; *userdatap = 0; *userdatalenp = *pubkeysizep = *sigsizep = 0; - *hashtypep = SIGHASH_ALL; + *hashtypep = LP_sighash(symbol,zcash); while ( (siglen= scriptsig[n]) >= 70 && siglen <= 73 && n+siglen < len && j < 16 ) { vp->signers[j].siglen = siglen; memcpy(vp->signers[j].sig,&scriptsig[n+1],siglen); if ( j == 0 ) *hashtypep = vp->signers[j].sig[siglen-1]; - else if ( vp->signers[j].sig[siglen-1] != *hashtypep ) + else if ( vp->signers[j].sig[siglen-1] != (*hashtypep & (~SIGHASH_FORKID)) ) { //printf("SIGHASH.%d mismatch %d vs %d\n",j,vp->signers[j].sig[siglen-1],*hashtypep); break; @@ -2408,14 +2408,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,11 +2576,11 @@ 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 iguana_vinscriptparse(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,struct vin_info *vp,uint32_t *sigsizep,uint32_t *pubkeysizep,uint32_t *p2shsizep,uint32_t *userdatalenp,uint8_t *vinscript,int32_t scriptlen,int32_t zcash) { uint32_t hashtype; uint8_t *userdata = 0; *sigsizep = *pubkeysizep = *p2shsizep = *userdatalenp = 0; - if ( bitcoin_scriptget(taddr,pubtype,p2shtype,&hashtype,sigsizep,pubkeysizep,&userdata,userdatalenp,vp,vinscript,scriptlen,0) < 0 ) + if ( bitcoin_scriptget(symbol,taddr,pubtype,p2shtype,&hashtype,sigsizep,pubkeysizep,&userdata,userdatalenp,vp,vinscript,scriptlen,0,zcash) < 0 ) { printf("iguana_vinscriptparse: error parsing vinscript?\n"); return(-1); @@ -2600,7 +2593,7 @@ uint32_t iguana_vinscriptparse(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,st //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) { @@ -3040,7 +3033,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,9 +3272,9 @@ int32_t iguana_vinarray_check(cJSON *vinarray,bits256 txid,int32_t vout) return(-1); } -int32_t iguana_rwmsgtx(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,int32_t rwflag,cJSON *json,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,bits256 *txidp,char *vpnstr,uint8_t *extraspace,int32_t extralen,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash); +int32_t iguana_rwmsgtx(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,int32_t rwflag,cJSON *json,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,bits256 *txidp,char *vpnstr,uint8_t *extraspace,int32_t extralen,cJSON *vins,int32_t suppress_pubkeys,int32_t zcash); -bits256 bitcoin_sigtxid(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,uint8_t *serialized,int32_t maxlen,struct iguana_msgtx *msgtx,int32_t vini,uint8_t *spendscript,int32_t spendlen,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; dest = *msgtx; @@ -3290,47 +3283,82 @@ bits256 bitcoin_sigtxid(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t i memcpy(dest.vins,msgtx->vins,dest.tx_in * sizeof(*dest.vins)); memcpy(dest.vouts,msgtx->vouts,dest.tx_out * sizeof(*dest.vouts)); memset(sigtxid.bytes,0,sizeof(sigtxid)); - if ( (hashtype & ~SIGHASH_FORKID) != SIGHASH_ALL ) + if ( ((hashtype & ~SIGHASH_FORKID) & 0xff) != SIGHASH_ALL ) { printf("currently only SIGHASH_ALL supported, not %d\n",hashtype); return(sigtxid); } - for (i=0; i 0 ) { - dest.vins[i].vinscript = (uint8_t *)""; - dest.vins[i].scriptlen = 0; +#ifdef BTC2_VERSION + if ( height >= BTC2_HARDFORK_HEIGHT ) + hashtype |= (0x777 << 20); +#endif + len += iguana_rwnum(1,&serialized[len],sizeof(hashtype),&hashtype); } - dest.vins[i].p2shlen = 0; - dest.vins[i].redeemscript = 0; - dest.vins[i].userdata = 0; - dest.vins[i].userdatalen = 0; } - len = iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,1,0,serialized,maxlen,&dest,&txid,vpnstr,0,0,0,suppress_pubkeys,zcash); - //for (i=0; i 0 ) // (dest.tx_in != 1 || bits256_nonz(dest.vins[0].prev_hash) != 0) && dest.vins[0].scriptlen > 0 && + else { -#ifdef BTC2_VERSION - if ( height >= BTC2_HARDFORK_HEIGHT ) - hashtype |= (0x777 << 20); -#endif + bits256 prevouthash,seqhash,outputhash; + for (i=len=0; iversion),&msg->version); if ( json != 0 ) @@ -3535,10 +3577,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 +3677,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 +3711,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 +3722,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 +3740,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 +3749,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..c27fb2ecd 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; iSPV = height; - if ( tx->serialized != 0 ) + if ( strcmp(coinaddr,coin->smartaddr) != 0 && tx->serialized != 0 ) { free(tx->serialized); tx->serialized = 0; @@ -314,7 +313,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 +329,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..0bf61e969 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.HOME}`", *ht_start, *p_ht; + char ht_symbol[2]; + + ht_start = strstr(confpath, ht); + + if (ht_start) { + ht_start = ht_start + strlen(ht); + sprintf(fname, "%s\\", LP_getdatadir()); + p_ht = ht_start; + if (p_ht[0] == '/' && p_ht[1] == '.') { + p_ht += 2; + //printf("%s\n", p_ht); + while (p_ht[0] != '\0') { + if (p_ht[0] == '/') strcat(fname, "\\"); else + { + ht_symbol[0] = p_ht[0]; ht_symbol[1] = '\0'; + strcat(fname, ht_symbol); + } + p_ht++; + } + //printf("%s\n", fname); + } + } else strcpy(fname, confpath); + #else + strcpy(fname,confpath); + #endif return; } sprintf(fname,"%s",LP_getdatadir()); @@ -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); @@ -353,6 +380,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); } diff --git a/iguana/exchanges/LP_commands.c b/iguana/exchanges/LP_commands.c index d2f72406d..e7a6fa96b 100644 --- a/iguana/exchanges/LP_commands.c +++ b/iguana/exchanges/LP_commands.c @@ -38,7 +38,7 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r 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,22 +102,21 @@ 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\ +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\ @@ -128,7 +135,8 @@ setconfirms(coin, numconfirms, maxconfirms=6)\n\ trust(pubkey, trust) # positive to trust, 0 for normal, negative to blacklist\n\ balance(coin, address)\n\ orderbook(base, rel, duration=3600)\n\ -getprices(base, rel)\n\ +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 +154,8 @@ bot_settings(botid, newprice, newvolume)\n\ bot_status(botid)\n\ bot_stop(botid)\n\ bot_pause(botid)\n\ -bot_resume(botid)\n\ +zeroconf_deposit(weeks, amount, broadcast=0)\n\ +zeroconf_claim(address, expiration=0)\n\ \"}")); //sell(base, rel, price, basevolume, timeout=10, duration=3600)\n\ @@ -172,6 +181,7 @@ bot_resume(botid)\n\ jdelete(argjson,"userpass"); if ( strcmp(method,"passphrase") == 0 ) { + char coinaddr[64]; G.USERPASS_COUNTER = 1; if ( LP_passphrase_init(jstr(argjson,"passphrase"),jstr(argjson,"gui")) < 0 ) return(clonestr("{\"error\":\"couldnt change passphrase\"}")); @@ -180,9 +190,34 @@ bot_resume(botid)\n\ jaddstr(retjson,"result","success"); jaddstr(retjson,"userpass",G.USERPASS); jaddbits256(retjson,"mypubkey",G.LP_mypub25519); + bitcoin_address(coinaddr,0,60,G.LP_myrmd160,20); + jaddstr(retjson,"KMD",coinaddr); + bitcoin_address(coinaddr,0,0,G.LP_myrmd160,20); + jaddstr(retjson,"BTC",coinaddr); + jaddstr(retjson,"NXT",G.LP_NXTaddr); return(jprint(retjson,1)); } } + else if ( strcmp(method,"zeroconf_deposit") == 0 ) + { + if ( (ptr= LP_coinsearch("KMD")) != 0 ) + { + if ( jint(argjson,"weeks") < 0 || jdouble(argjson,"amount") < 10. ) + return(clonestr("{\"error\":\"deposit_create needs to have weeks and amount\"}")); + else return(LP_instantdex_deposit(ptr,juint(argjson,"weeks"),jdouble(argjson,"amount"),jint(argjson,"broadcast"))); + } + return(clonestr("{\"error\":\"cant find KMD\"}")); + } + else if ( strcmp(method,"zeroconf_claim") == 0 ) + { + if ( (ptr= LP_coinsearch("KMD")) != 0 ) + { + if ( jstr(argjson,"address") == 0 ) + return(clonestr("{\"error\":\"deposit_claim needs to have address\"}")); + else return(LP_instantdex_claim(ptr,jstr(argjson,"address"),juint(argjson,"expiration"))); + } + return(clonestr("{\"error\":\"cant find KMD\"}")); + } /*else if ( strcmp(method,"sendmessage") == 0 ) { if ( jobj(argjson,"method2") == 0 ) @@ -240,16 +275,9 @@ bot_resume(botid)\n\ { return(LP_portfolio()); } - else if ( strcmp(method,"parselog") == 0 ) - { - bits256 zero; int32_t n = LP_statslog_parse(); - memset(zero.bytes,0,sizeof(zero)); - return(LP_statslog_disp(n,2000000000,2000000000,"",zero)); - } else if ( strcmp(method,"statsdisp") == 0 ) { - int32_t n = LP_statslog_parse(); - return(LP_statslog_disp(n,juint(argjson,"starttime"),juint(argjson,"endtime"),jstr(argjson,"gui"),jbits256(argjson,"pubkey"))); + return(jprint(LP_statslog_disp(juint(argjson,"starttime"),juint(argjson,"endtime"),jstr(argjson,"gui"),jbits256(argjson,"pubkey"),jstr(argjson,"base"),jstr(argjson,"rel")),1)); } else if ( strcmp(method,"secretaddresses") == 0 ) { @@ -262,13 +290,32 @@ bot_resume(botid)\n\ { uint32_t requestid,quoteid; if ( (requestid= juint(argjson,"requestid")) != 0 && (quoteid= juint(argjson,"quoteid")) != 0 ) + { return(basilisk_swapentry(requestid,quoteid)); + } else if ( coin[0] != 0 ) return(basilisk_swapentries(coin,0,jint(argjson,"limit"))); else if ( base[0] != 0 && rel[0] != 0 ) return(basilisk_swapentries(base,rel,jint(argjson,"limit"))); else return(basilisk_swaplist(0,0)); } + else if ( 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); if ( base[0] != 0 && rel[0] != 0 ) @@ -280,31 +327,45 @@ bot_resume(botid)\n\ return(clonestr("{\"error\":\"couldnt set autoprice\"}")); else return(clonestr("{\"result\":\"success\"}")); } - if ( IAMLP == 0 && LP_isdisabled(base,rel) != 0 ) - return(clonestr("{\"error\":\"at least one of coins disabled\"}")); - price = jdouble(argjson,"price"); - if ( strcmp(method,"setprice") == 0 ) + else if ( strcmp(method,"getprice") == 0 ) { - if ( LP_mypriceset(&changed,base,rel,price) < 0 ) - return(clonestr("{\"error\":\"couldnt set price\"}")); - //else if ( LP_mypriceset(&changed,rel,base,1./price) < 0 ) - // return(clonestr("{\"error\":\"couldnt set price\"}")); - else return(LP_pricepings(ctx,myipaddr,LP_mypubsock,base,rel,price * LP_profitratio)); + double price; + price = LP_price(base,rel); + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jaddstr(retjson,"base",base); + jaddstr(retjson,"rel",rel); + jaddnum(retjson,"timestamp",time(NULL)); + jaddnum(retjson,"price",price); + return(jprint(retjson,1)); } 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 ) + 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,"lasttime"),jint(argjson,"timescale")),1)); + 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,"pricearray") == 0 ) + 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"); + if ( strcmp(method,"setprice") == 0 ) { - return(jprint(LP_pricearray(base,rel,juint(argjson,"starttime"),juint(argjson,"endtime"),jint(argjson,"timescale")),1)); - }*/ + if ( LP_mypriceset(&changed,base,rel,price) < 0 ) + return(clonestr("{\"error\":\"couldnt set price\"}")); + //else if ( LP_mypriceset(&changed,rel,base,1./price) < 0 ) + // return(clonestr("{\"error\":\"couldnt set price\"}")); + else if ( 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,"orderbook") == 0 ) return(LP_orderbook(base,rel,jint(argjson,"duration"))); else if ( strcmp(method,"myprice") == 0 ) @@ -336,13 +397,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,7 +414,7 @@ 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)); } @@ -361,13 +422,19 @@ bot_resume(botid)\n\ { ptr->inactive = 0; cJSON *array; - if ( ptr->smartaddr[0] != 0 ) - LP_unspents_load(coin,ptr->smartaddr); if ( LP_getheight(ptr) <= 0 ) { ptr->inactive = (uint32_t)time(NULL); return(clonestr("{\"error\":\"coin cant be activated till synced\"}")); - } else LP_unspents_load(coin,ptr->smartaddr); + } + else + { + if ( ptr->smartaddr[0] != 0 ) + LP_unspents_load(coin,ptr->smartaddr); + LP_unspents_load(coin,ptr->smartaddr); + if ( strcmp(ptr->symbol,"KMD") == 0 ) + LP_importaddress("KMD",BOTS_BONDADDRESS); + } array = cJSON_CreateArray(); jaddi(array,LP_coinjson(ptr,0)); return(jprint(array,1)); @@ -389,7 +456,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 +465,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); + //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 +494,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 +541,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 +565,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,12 +606,23 @@ bot_resume(botid)\n\ } argjson = reqjson; } + if ( strcmp(method,"gettradestatus") == 0 ) + retstr = clonestr("{\"result\":\"success\"}"); + } + else + { + if ( strcmp(method,"gettradestatus") == 0 ) + return(LP_gettradestatus(j64bits(argjson,"aliceid"))); + else if ( strcmp(method,"tradesarray") == 0 ) + { + return(jprint(LP_tradesarray(base,rel,juint(argjson,"starttime"),juint(argjson,"endtime"),jint(argjson,"timescale")),1)); + } } // received response - if ( strcmp(method,"postprice") == 0 ) + if ( strcmp(method,"swapstatus") == 0 ) + return(LP_swapstatus_recv(argjson)); + 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,"notify") == 0 ) @@ -569,7 +647,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..77c71ece4 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -21,11 +21,15 @@ #ifndef LP_INCLUDE_H #define LP_INCLUDE_H +#ifdef FROMGUI +#define printf(...) +#endif + #define LP_MAJOR_VERSION "0" #define LP_MINOR_VERSION "1" -#define LP_BUILD_NUMBER "15256" +#define LP_BUILD_NUMBER "17577" #define LP_BARTERDEX_VERSION 1 -#define LP_MAGICBITS 8 +#define LP_MAGICBITS 1 #ifdef FROM_JS #include @@ -43,18 +47,19 @@ 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 LP_AUTOTRADE_TIMEOUT 60 +#define LP_RESERVETIME 600 //(LP_AUTOTRADE_TIMEOUT * 2) #define ELECTRUM_TIMEOUT 7 #define LP_ELECTRUM_KEEPALIVE 60 #define LP_ELECTRUM_MAXERRORS 777 #define LP_MEMPOOL_TIMEINCR 10 +#define LP_SCREENWIDTH 1024 #define LP_MIN_PEERS 8 #define LP_MAX_PEERS 32 -#define LP_MAXDESIRED_UTXOS (IAMLP != 0 ? 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 @@ -82,7 +87,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 +103,10 @@ 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_WEEKMULT (7 * 24 * 2600) +#define LP_FIRSTWEEKTIME 1510790400 // must be 0 mod LP_WEEKMULT //#define BASILISK_DISABLEWAITTX //#define BASILISK_DISABLESENDTX @@ -113,15 +122,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; }; @@ -288,7 +311,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 +319,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 +340,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 @@ -372,15 +396,28 @@ 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; + double qprice; + uint64_t aliceid; + uint32_t ind,methodind,finished,expired,lasttime; + 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 +435,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,28 +456,28 @@ 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); 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); @@ -438,6 +488,7 @@ 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); 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); @@ -451,7 +502,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_ struct LP_address_utxo *LP_address_utxofind(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout); int32_t LP_destaddr(char *destaddr,cJSON *item); int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t duration); -char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey); +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); @@ -461,7 +512,7 @@ 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); +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 +521,20 @@ 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); +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(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..ba8cb6c4a --- /dev/null +++ b/iguana/exchanges/LP_instantdex.c @@ -0,0 +1,373 @@ + +/****************************************************************************** + * 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) +{ + sprintf(fname,"%s/instantdex.json",GLOBAL_DBDIR); +} + +cJSON *LP_instantdex_txidaddjson() +{ + char *filestr,fname[1024]; long fsize; cJSON *retjson=0; + LP_instantdex_txidaddfname(fname); + if ( (filestr= OS_filestr(&fsize,fname)) != 0 ) + { + retjson = cJSON_Parse(filestr); + free(filestr); + } + return(retjson); +} + +void LP_instantdex_txidadd(bits256 txid) +{ + cJSON *array; int32_t i,n; char fname[1024],*filestr; FILE *fp; + if ( (array= LP_instantdex_txidaddjson()) == 0 ) + array = cJSON_CreateArray(); + if ( (n= cJSON_GetArraySize(array)) >= 0 ) + { + for (i=0; i %s\n",bits256_str(str,txid),fname); + jaddibits256(array,txid); + if ( (fp= fopen(fname,"wb")) != 0 ) + { + filestr = jprint(array,0); + fwrite(filestr,1,strlen(filestr)+1,fp); + fclose(fp); + free(filestr); + } + } + } + if ( array != 0 ) + free_json(array); +} + +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 0 and 52\"}")); + if ( weeks > 0 ) + { + timestamp = (uint32_t)time(NULL); + timestamp /= LP_WEEKMULT; + timestamp += weeks+1; + 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 ( bits256_nonz(txid) != 0 ) + LP_instantdex_txidadd(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); + 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\"}")); +} + +char *LP_instantdex_claim(struct iguana_info *coin,char *depositaddr,uint32_t expiration) +{ + static void *ctx; + uint8_t redeemscript[512],userdata[64]; char vinaddr[64],str[65],*signedtx=0; uint32_t timestamp,now,redeemlen,claimtime; int32_t i,n,height,utxovout,userdatalen; bits256 signedtxid,utxotxid,sendtxid,zero; int64_t sum,destamount,satoshis; cJSON *array,*item,*txids,*retjson; + if ( ctx == 0 ) + ctx = bitcoin_ctx(); + if ( strcmp(coin->symbol,"KMD") != 0 ) + return(clonestr("{\"error\":\"instantdex deposit must be in KMD\"}")); + now = (uint32_t)time(NULL); + sum = 0; + txids = cJSON_CreateArray(); + 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 ) + { + userdata[0] = 0x51; + userdatalen = 1; + utxovout = 0; + //printf("unspents.(%s)\n",jprint(array,0)); + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; isymbol,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 ) + { + jaddibits256(txids,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)); + } + } + free_json(array); + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jaddnum(retjson,"claimed",dstr(sum)); + jadd(retjson,"txids",txids); + return(jprint(retjson,1)); + } + } + } + if ( expiration != 0 ) + break; + } + return(clonestr("{\"error\":\"no instantdex deposits to claim\"}")); +} + +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 ( time(NULL) < timestamp-60*3600 && (ap= LP_address(coin,coinaddr)) != 0 ) + { + ap->instantdex_credits += satoshis; + ap->didinstantdex = 1; + if ( strcmp(coinaddr,coin->smartaddr) == 0 ) + LP_instantdex_txidadd(txid); + if ( dispflag != 0 ) + printf("InstantDEX credit.(%s) %.8f weeki.%d (%s) -> sum %.8f\n",coinaddr,dstr(satoshis),weeki,p2shaddr,dstr(ap->instantdex_credits)); + return(satoshis); + } + } + 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); + //printf("%s funded %.8f weeki.%d\n",destaddr,dstr(satoshis),weeki); + 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); + } + } + } + } + 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(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); + if ((ap= LP_address(coin,coinaddr)) != 0 )//&& ap->instantdex_credits >= kmdvalue ) + { + DL_FOREACH_SAFE(pubp->bobswaps,ptr,tmp) + { + if ( (sp= ptr->swap) != 0 && sp->finished == 0 && sp->expired == 0 ) + swaps_kmdvalue += LP_kmdvalue(sp->Q.srccoin,sp->Q.satoshis); + } + DL_FOREACH_SAFE(pubp->aliceswaps,ptr,tmp) + { + if ( (sp= ptr->swap) != 0 && sp->finished == 0 && sp->expired == 0 ) + swaps_kmdvalue += LP_kmdvalue(sp->Q.destcoin,sp->Q.destsatoshis); + } + //printf("%s instantdex_credits %.8f vs (%.8f + current %.8f)\n",coinaddr,dstr(ap->instantdex_credits),dstr(swaps_kmdvalue),dstr(kmdvalue)); + //if ( ap->instantdex_credits > swaps_kmdvalue+kmdvalue ) + return(ap->instantdex_credits - (swaps_kmdvalue+kmdvalue)); + } + } + return(0); +} + +int64_t LP_instantdex_proofcheck(char *coinaddr,cJSON *proof,int32_t num) +{ + uint8_t rmd160[20],addrtype; int32_t i; int64_t net = 0; 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); + if ((ap= LP_address(coin,othersmartaddr)) != 0 && (coin->electrum == 0 || ap->didinstantdex == 0) ) + { + ap->instantdex_credits = 0; + for (i=0; ididinstantdex = 1; + //if ( ap->instantdex_credits > 0 ) + printf("validated instantdex %s.[%d] proof.(%s) credits %.8f net %.8f\n",othersmartaddr,num,jprint(proof,0),dstr(ap->instantdex_credits),dstr(net)); + } 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(net); +} diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index f1b89a40b..1ff7bbc91 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -17,14 +17,23 @@ // LP_nativeDEX.c // marketmaker // -// BCH signing: FORKID_BCC = 0, FORKID_BTG = 79, // Atomic number AU -// alice waiting for bestprice -// MNZ getcoin strangeness +// prune expired/spent deposits from instantdex.json +// -CPU usage spike after 12 hours +// verify claim works +// big BTC swaps +// https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki for signing BCH/BTG +// +// compress packets +// cancel bid/ask +// portfolio to set prices from historical +// portfolio value based on ask? +// USD paxprice based USDvalue in portfolio +// // improve critical section detection when parallel trades -// reduce mem: dont redundant store pubkey utxo info -// previously, it used to show amount, kmd equiv, perc +// delay swap credit back until notarization // dPoW security -> 4: KMD notarized, 5: BTC notarized, after next notary elections // bigendian architectures need to use little endian for sighash calcs +// #include @@ -35,7 +44,7 @@ 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; void LP_millistats_update(struct LP_millistats *mp) @@ -56,7 +65,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); } @@ -81,21 +90,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 +115,13 @@ struct LP_privkey { bits256 privkey; uint8_t rmd160[20]; }; struct LP_globals { - struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2]; + //struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2]; bits256 LP_mypub25519,LP_privkey,LP_mypriv25519; uint64_t LP_skipstatus[10000]; uint8_t LP_myrmd160[20],LP_pubsecp[33]; uint32_t LP_sessionid,counter; int32_t LP_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; @@ -173,9 +182,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 +196,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,7 +207,13 @@ char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson //if ( pubsock >= 0 ) //strncmp("{\"error\":",retstr,strlen("{\"error\":")) != 0 && //LP_send(pubsock,retstr,(int32_t)strlen(retstr)+1,0); } - } //else printf("finished tradecommand (%s)\n",jprint(argjson,0)); + } + 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); } @@ -307,8 +323,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\"}"); @@ -445,10 +461,9 @@ int32_t LP_nanomsg_recvs(void *ctx) return(nonz); } -void command_rpcloop(void *myipaddr) +void command_rpcloop(void *ctx) { - int32_t nonz = 0; void *ctx; - ctx = bitcoin_ctx(); + int32_t nonz = 0; strcpy(command_rpcloop_stats.name,"command_rpcloop"); command_rpcloop_stats.threshold = 1000.; while ( 1 ) @@ -468,18 +483,6 @@ 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; @@ -530,17 +533,20 @@ void LP_coinsloop(void *_coins) coin->longestchain = LP_getheight(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 ) @@ -582,7 +588,7 @@ 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 = ep->prev; @@ -639,7 +645,7 @@ 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; + static uint32_t counter;//,didinstantdex; struct iguana_info *coin,*ctmp; char *origipaddr; uint32_t now; int32_t height,nonz = 0; if ( (origipaddr= myipaddr) == 0 ) origipaddr = "127.0.0.1"; @@ -648,6 +654,13 @@ 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); +#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); @@ -679,13 +692,19 @@ void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins) printf("%s ",activecoins[i]); LP_coinfind(activecoins[i]); LP_priceinfoadd(activecoins[i]); - //test_validate("02000000010e62f95ff5881de8853ce1a5ddbaad731a62879d719367f539103600f1895477010000006b483045022100c684a0871689519bd97f2e61275752124f0f1498360750c87cf99a8acf06fd8c022047e7e62a7bfd481599130e6f40c95833f6ed6f44aa8b6ead7b0ec86a738b98a041210361857e1ba609aadff520a2ca9886fe7548c7154fab2cbe108c3b0e1e7635eb1ffeffffff02a0860100000000001976a9146cfa0a987f4c8f2ffee7e9944ef0c86fcda9671d88ac1e6f0700000000001976a9147f4b7113f9e26d84b150f2cc6d219baaf27f884488ace6b00700"); + //test_validate("02000000010e62f95ff5881de8853ce1a5ddbaad731a62879d719367f539103600f1895477010000006b483045022100c684a0871689519bd97f2e61275752124f0f1498360750c87cf99a8acf06fd8c022047e7e62a7bfd481599130e6f40c95833f6ed6f44aa8b6ead7b0ec86a738b98a041210361857e1ba609aadff520a2ca9886fe7548c7154fab2cbe108c3b0e1e7635eb1ffeffffff02a0860100000000001976a9146cfa0a987f4c8f2ffee7e9944ef0c86fcda9671d88ac1e6f0700000000001976a9147f4b7113f9e26d84b150f2cc6d219baaf27f884488ace6b00700"); + //test_validate("01000000011434b89cc4d41bcbbda87db58b5167bce50ea025d5fba3f4d7bbd9ec1b620d98000000006a47304402205aba01fa2b895df6069dc7458fcc7aac6da1ffbc2811eb43382a5a342a342c6202207da60859f45893785322fede2f82b1f7c76cd9882b6a8ed6d25037f4184b60514121029d1e15b82fc3e11b51b61eb65545b0c93baebb17de5118979f261a086575bcd6ffffffff0210270000000000001976a9146cfa0a987f4c8f2ffee7e9944ef0c86fcda9671d88ac80380100000000001976a9146cfa0a987f4c8f2ffee7e9944ef0c86fcda9671d88ac00000000"); //getchar(); if ( (coin= LP_coinfind(activecoins[i])) != 0 ) { if ( LP_getheight(coin) <= 0 ) coin->inactive = (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); + } if ( coin->txfee == 0 && strcmp(coin->symbol,"BTC") != 0 ) coin->txfee = LP_MIN_TXFEE; } @@ -758,23 +777,13 @@ void LP_initpeers(int32_t pubsock,struct LP_peerinfo *mypeer,char *myipaddr,uint void LP_pubkeysloop(void *ctx) { - static uint32_t lasttime; cJSON *retjson; struct iguana_info *coin,*tmp; + static uint32_t lasttime; strcpy(LP_pubkeysloop_stats.name,"LP_pubkeysloop"); LP_pubkeysloop_stats.threshold = 15000.; sleep(10); while ( 1 ) { LP_millistats_update(&LP_pubkeysloop_stats); - 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); - } - } if ( time(NULL) > lasttime+LP_ORDERBOOK_DURATION*0.5 ) { //printf("LP_pubkeysloop %u\n",(uint32_t)time(NULL)); @@ -785,22 +794,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 +803,126 @@ 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 ) 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; int32_t sentbytes,nonz,flag,duplicate,n=0; + strcpy(queue_loop_stats.name,"queue_loop"); + queue_loop_stats.threshold = 1000.; + while ( 1 ) + { + LP_millistats_update(&queue_loop_stats); + //printf("LP_Q.%p next.%p prev.%p\n",LP_Q,LP_Q!=0?LP_Q->next:0,LP_Q!=0?LP_Q->prev:0); + n = nonz = flag = 0; + DL_FOREACH_SAFE(LP_Q,ptr,tmp) + { + n++; + flag = 0; + if ( ptr->sock >= 0 ) + { + if ( ptr->notready == 0 || (LP_rand() % ptr->notready) == 0 ) + { + if ( LP_sockcheck(ptr->sock) > 0 ) + { + bits256 magic; + magic = LP_calc_magic(ptr->msg,(int32_t)(ptr->msglen - sizeof(bits256))); + memcpy(&ptr->msg[ptr->msglen - sizeof(bits256)],&magic,sizeof(magic)); + if ( (sentbytes= nn_send(ptr->sock,ptr->msg,ptr->msglen,0)) != ptr->msglen ) + printf("%d LP_send sent %d instead of %d\n",n,sentbytes,ptr->msglen); + else flag++; + ptr->sock = -1; + if ( ptr->peerind > 0 ) + ptr->starttime = (uint32_t)time(NULL); + } + else + { + if ( ptr->notready++ > 1000 ) + flag = 1; + } + } + } + else if ( 0 && time(NULL) > ptr->starttime+13 ) + { + LP_crc32find(&duplicate,-1,ptr->crc32); + if ( duplicate > 0 ) + { + LP_Qfound++; + if ( (LP_Qfound % 100) == 0 ) + printf("found.%u Q.%d err.%d match.%d\n",ptr->crc32,LP_Qenqueued,LP_Qerrors,LP_Qfound); + flag++; + } + else if ( 0 ) // too much beyond duplicate filter when network is busy + { + printf("couldnt find.%u peerind.%d Q.%d err.%d match.%d\n",ptr->crc32,ptr->peerind,LP_Qenqueued,LP_Qerrors,LP_Qfound); + ptr->peerind++; + if ( (ptr->sock= LP_peerindsock(&ptr->peerind)) < 0 ) + { + printf("%d no more peers to try at peerind.%d %p Q_LP.%p\n",n,ptr->peerind,ptr,LP_Q); + flag++; + LP_Qerrors++; + } + } + } + if ( flag != 0 ) + { + nonz++; + portable_mutex_lock(&LP_networkmutex); + DL_DELETE(LP_Q,ptr); + portable_mutex_unlock(&LP_networkmutex); + free(ptr); + ptr = 0; + break; + } + } + if ( nonz == 0 ) + { + if ( IAMLP == 0 ) + usleep(50000); + else usleep(10000); + } + } +} + void LP_reserved_msgs(void *ignore) { bits256 zero; int32_t flag,nonz; struct nn_pollfd pfd; @@ -875,7 +981,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]; @@ -960,6 +1066,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 @@ -1049,11 +1158,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 +1169,63 @@ 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 ( 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_privkeysloop,ctx) != 0 ) + { + printf("error launching LP_privkeysloop for ctx.%p\n",ctx); + exit(-1); + }*/ + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_swapsloop,ctx) != 0 ) { - printf("error launching LP_swapsloop for port.%u\n",myport); + printf("error launching LP_swapsloop for ctx.%p\n",ctx); exit(-1); } int32_t nonz; + LP_statslog_parse(); while ( 1 ) { nonz = 0; @@ -1182,8 +1292,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,10 +1299,10 @@ 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); @@ -1202,7 +1310,6 @@ void LP_fromjs_iter() free(retstr); } } - LP_counter++; } #endif diff --git a/iguana/exchanges/LP_network.c b/iguana/exchanges/LP_network.c index d1b147bc8..673db2940 100644 --- a/iguana/exchanges/LP_network.c +++ b/iguana/exchanges/LP_network.c @@ -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..43f64946d 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.; @@ -177,14 +177,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 +278,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 +318,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 +326,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 +334,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 +364,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 +379,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 +393,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,30 +419,32 @@ 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 ) + if ( targetval != 0 && (mini= LP_nearest_utxovalue(coin,coinaddr,utxos,m,targetval+fee)) >= 0 ) { up = utxos[mini]; utxos[mini] = 0; //printf("found mini.%d %.8f for targetval %.8f -> targetval2 %.8f, ratio %.2f\n",mini,dstr(up->U.value),dstr(targetval),dstr(targetval2),(double)up->U.value/targetval); - if ( (double)up->U.value/targetval < LP_MINVOL-1 ) + if ( (double)up->U.value/targetval < ratio-1 ) { - if ( (mini= LP_nearest_utxovalue(coin,coinaddr,utxos,m,(targetval2+2*txfee) * 1.01)) >= 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 ( up != 0 && (up2= utxos[mini]) != 0 ) { - /*if ( (utxo= LP_utxoadd(1,coin->symbol,up->U.txid,up->U.vout,up->U.value,up2->U.txid,up2->U.vout,up2->U.value,coinaddr,ap->pubkey,G.gui,0,targetval)) != 0 ) - { - utxo->S.satoshis = targetval; - char str[65],str2[65]; printf("butxo.%p targetval %.8f, found val %.8f %s | targetval2 %.8f val2 %.8f %s\n",utxo,dstr(targetval),dstr(up->U.value),bits256_str(str,utxo->payment.txid),dstr(targetval2),dstr(up2->U.value),bits256_str(str2,utxo->deposit.txid)); - return(butxo); - }*/ - LP_butxo_set(butxo,coin,up,up2,targetval); + LP_butxo_set(butxo,iambob,coin,up,up2,targetval); return(butxo); - } + } else printf("cant find utxos[mini %d]\n",mini); } else printf("cant find targetval2 %.8f\n",dstr(targetval2)); } else printf("failed ratio test %.8f\n",(double)up->U.value/targetval); } else if ( targetval != 0 && mini >= 0 ) @@ -435,10 +454,9 @@ struct LP_utxoinfo *LP_address_myutxopair(struct LP_utxoinfo *butxo,int32_t iamb 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]; cJSON *reqjson; bits256 privkey; int32_t pair=-1,retval = -1,DEXselector = 0; struct basilisk_swap *swap; struct iguana_info *coin; qp->quotetime = (uint32_t)time(NULL); if ( (coin= LP_coinfind(qp->srccoin)) == 0 ) { @@ -454,7 +472,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->desthash,LP_kmdvalue(qp->destcoin,qp->destsatoshis)) > 0)) == 0 ) { printf("cant initialize swap\n"); return(-1); @@ -466,16 +484,18 @@ 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); + jadd(reqjson,"proof",LP_instantdex_txidaddjson()); 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)); + //sleep(1); + //LP_reserved_msg(1,base,rel,qp->desthash,jprint(reqjson,0)); + //LP_reserved_msg(0,base,rel,zero,jprint(reqjson,0)); + free_json(reqjson); retval = 0; } else printf("error launching swaploop\n"); } else printf("couldnt bind to any port %s\n",pairstr); @@ -492,12 +512,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 +562,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; 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); + LP_availableset(qp->desttxid,qp->vout); + LP_availableset(qp->feetxid,qp->feevout); + LP_aliceid(qp->tradeid,qp->aliceid,"error4",0,0); printf("quote validate error %.0f\n",qprice); return(clonestr("{\"error\":\"quote validation error\"}")); } - if ( LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin) <= SMALLVAL || bid <= SMALLVAL ) + if ( LP_myprice(&bid,&ask,qp->srccoin,qp->destcoin) <= SMALLVAL || bid <= SMALLVAL ) { - printf("this node has no price for %s/%s (%.8f %.8f)\n",Q.destcoin,Q.srccoin,bid,ask); - LP_availableset(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->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 +642,48 @@ 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); + LP_aliceid(qp->tradeid,qp->aliceid,"started",qp->R.requestid,qp->R.quoteid); printf("alice pairstr.(%s) pairsock.%d\n",pairstr,pairsock); if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_aliceloop,(void *)swap) == 0 ) { - retjson = LP_quotejson(&Q); + 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 ) @@ -765,117 +712,514 @@ 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 validate error %.0f\n",qprice); + return(-3); + } + if ( qprice < (price - 0.00000001) * 0.998 ) + { + printf(" quote price %.8f too low vs %.8f for %s/%s %.8f < %.8f\n",qprice,price,qp->srccoin,qp->destcoin,qprice,(price - 0.00000001) * 0.998); + return(-77); + } + return(qprice); +} + +struct LP_quoteinfo *LP_trades_gotrequest(void *ctx,struct LP_quoteinfo *qp,struct LP_quoteinfo *newqp,char *pairstr) +{ + double price,qprice,myprice,bestprice,range,bid,ask; struct iguana_info *coin; struct LP_utxoinfo A,B,*autxo,*butxo; cJSON *reqjson; char str[65]; struct LP_address_utxo *utxos[1000]; int32_t r,counter,max = (int32_t)(sizeof(utxos)/sizeof(*utxos)); + *newqp = *qp; + qp = newqp; + if ( (coin= LP_coinfind(qp->srccoin)) == 0 ) + return(0); + //printf("LP_trades_gotrequest %s/%s %.8f\n",qp->srccoin,qp->destcoin,LP_trades_bobprice(&bid,&ask,qp)); + if ( (myprice= LP_trades_bobprice(&bid,&ask,qp)) == 0. ) + return(0); + autxo = &A; + butxo = &B; + memset(autxo,0,sizeof(*autxo)); + memset(butxo,0,sizeof(*butxo)); + LP_abutxo_set(autxo,butxo,qp); + if ( bits256_nonz(qp->srchash) == 0 || bits256_cmp(qp->srchash,G.LP_mypub25519) == 0 ) + { + qprice = (double)qp->destsatoshis / (qp->satoshis - qp->txfee); + strcpy(qp->gui,G.gui); + strcpy(qp->coinaddr,coin->smartaddr); + strcpy(butxo->coinaddr,coin->smartaddr); + qp->srchash = G.LP_mypub25519; + memset(&qp->txid,0,sizeof(qp->txid)); + memset(&qp->txid2,0,sizeof(qp->txid2)); + qp->vout = qp->vout2 = -1; + } else return(0); + //printf("LP_trades_gotrequest qprice %.8f vs myprice %.8f\n",qprice,myprice); + if ( qprice > myprice ) + { + r = (LP_rand() % 100); + range = (qprice - myprice); + price = myprice + (r * range) / 100.; + bestprice = LP_bob_competition(&counter,qp->aliceid,price,0); + printf("%llu >>>>>>> qprice %.8f r.%d range %.8f -> %.8f, bestprice %.8f counter.%d\n",(long long)qp->aliceid,qprice,r,range,price,bestprice,counter); + if ( counter > 3 && price >= bestprice-SMALLVAL ) // skip if late or bad price + return(0); + } else return(0); + //LP_RTmetrics_update(qp->srccoin,qp->destcoin); + if ( LP_RTmetrics_blacklisted(qp->desthash) >= 0 ) + { + printf("request from blacklisted %s, ignore\n",bits256_str(str,qp->desthash)); + return(0); + } + LP_address_utxo_reset(coin); + if ( (butxo= LP_address_myutxopair(butxo,1,utxos,max,LP_coinfind(qp->srccoin),qp->coinaddr,qp->txfee,dstr(qp->destsatoshis),price,qp->desttxfee)) != 0 ) + { + strcpy(qp->gui,G.gui); + strcpy(qp->coinaddr,coin->smartaddr); + qp->srchash = G.LP_mypub25519; + qp->txid = butxo->payment.txid; + qp->vout = butxo->payment.vout; + qp->txid2 = butxo->deposit.txid; + qp->vout2 = butxo->deposit.vout; + qp->satoshis = butxo->swap_satoshis;// + qp->txfee; + qp->quotetime = (uint32_t)time(NULL); + } + else + { + printf("cant find utxopair aliceid.%llu %s/%s %.8f -> relvol %.8f\n",(long long)qp->aliceid,qp->srccoin,qp->destcoin,dstr(LP_basesatoshis(dstr(qp->destsatoshis),price,qp->txfee,qp->desttxfee)),dstr(qp->destsatoshis)); + return(0); + } + if ( (qprice= LP_trades_pricevalidate(qp,coin,myprice)) < 0. ) + return(0); + if ( LP_allocated(qp->txid,qp->vout) == 0 && LP_allocated(qp->txid2,qp->vout2) == 0 ) + { + reqjson = LP_quotejson(qp); + LP_unavailableset(qp->txid,qp->vout,qp->timestamp + LP_RESERVETIME,qp->desthash); + LP_unavailableset(qp->txid2,qp->vout2,qp->timestamp + LP_RESERVETIME,qp->desthash); + if ( qp->quotetime == 0 ) + qp->quotetime = (uint32_t)time(NULL); + jaddnum(reqjson,"quotetime",qp->quotetime); + jaddnum(reqjson,"pending",qp->timestamp + LP_RESERVETIME); + jaddstr(reqjson,"method","reserved"); + bits256 zero; + memset(zero.bytes,0,sizeof(zero)); + LP_reserved_msg(1,qp->srccoin,qp->destcoin,zero,jprint(reqjson,0)); + //LP_reserved_msg(0,qp->srccoin,qp->destcoin,zero,jprint(reqjson,0)); + //sleep(1); + //LP_reserved_msg(1,qp->srccoin,qp->destcoin,qp->desthash,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_pubkeyfind(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.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); 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 ( 0 ) { - if (bits256_cmp(LP_Alicedestpubkey,Q.srchash) != 0 ) - { - printf("got reserved response from different node %s\n",bits256_str(str,Q.srchash)); + if ( LP_Alicemaxprice == 0. ) 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 ) - { - 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 ) + if ( bits256_nonz(LP_Alicedestpubkey) != 0 ) { - printf("reserved quote validate error %.0f\n",qprice); - return(retval); - } - if ( LP_validSPV(Q.srccoin,Q.coinaddr,Q.txid,Q.vout) < 0 ) - { - printf("%s src %s failed SPV check\n",Q.srccoin,bits256_str(str,Q.txid)); - return(retval); + 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 ) + 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 ) - { - //printf("this node has no price for %s/%s\n",Q.srccoin,Q.destcoin); - return(retval); - } - price = ask; - //printf("MYPRICE %s/%s %.8f vs qprice %.8f\n",Q.srccoin,Q.destcoin,price,qprice); - if ( LP_validSPV(Q.destcoin,Q.destaddr,Q.desttxid,Q.destvout) < 0 ) + if ( (coin= LP_coinfind(Q.srccoin)) == 0 || coin->inactive != 0 ) { - printf("%s dest %s failed SPV check\n",Q.destcoin,bits256_str(str,Q.desttxid)); + //printf("%s is not active\n",Q.srccoin); return(retval); } - else if (LP_validSPV(Q.destcoin,Q.destaddr,Q.feetxid,Q.feevout) < 0 ) + if ( price <= SMALLVAL || ask <= SMALLVAL ) { - 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 +1229,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 ) + 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 +1285,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,22 +1298,24 @@ 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 ) + //if ( (autxo= LP_utxo_bestfit(rel,destsatoshis + 2*desttxfee)) == 0 ) + return(clonestr("{\"error\":\"cant find alice utxo that is close enough in size\"}")); + //printf("bestfit selected alice (%.8f %.8f) for %.8f sats %.8f\n",dstr(autxo->payment.value),dstr(autxo->fee.value),dstr(destsatoshis),dstr(autxo->swap_satoshis)); + if ( destsatoshis - desttxfee < autxo->swap_satoshis ) { destsatoshis -= desttxfee; - autxo->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 ) { @@ -1180,49 +1332,6 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel int32_t changed; LP_mypriceset(&changed,autxo->coin,base,1. / maxprice); return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration,tradeid,destpubkey)); -#ifdef oldway - LP_RTmetrics_update(base,rel); - while ( 1 ) - { - 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..cf11dbe17 100644 --- a/iguana/exchanges/LP_portfolio.c +++ b/iguana/exchanges/LP_portfolio.c @@ -48,9 +48,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 +64,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 +76,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 +96,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 ) @@ -489,7 +491,8 @@ void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp) int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,struct iguana_info *buy,struct iguana_info *sell,double relvolume,int32_t setbaserel,char *gui) { - char *retstr2; double bid,ask,maxprice; bits256 zero; uint32_t requestid,quoteid,iter,i; cJSON *retjson2; + char *retstr2; uint64_t txfee,desttxfee; double bid,ask,maxprice; bits256 zero; uint32_t requestid,quoteid,iter,i; cJSON *retjson2; struct LP_utxoinfo A; struct LP_address_utxo *utxos[1000]; int32_t max=(int32_t)(sizeof(utxos)/sizeof(*utxos)); + LP_txfees(&txfee,&desttxfee,buy->symbol,sell->symbol); requestid = quoteid = 0; LP_myprice(&bid,&ask,buy->symbol,sell->symbol); maxprice = ask; @@ -507,7 +510,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 +535,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; diff --git a/iguana/exchanges/LP_prices.c b/iguana/exchanges/LP_prices.c index 7c91647aa..8c23d87fb 100644 --- a/iguana/exchanges/LP_prices.c +++ b/iguana/exchanges/LP_prices.c @@ -18,7 +18,15 @@ // 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 { @@ -49,7 +57,7 @@ struct LP_cacheinfo } *LP_cacheinfos; -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 +83,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 +99,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 +124,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 +227,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 +243,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 +259,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 +273,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 +307,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 +315,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 +326,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 +335,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 +356,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 +393,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 +401,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; @@ -472,7 +415,7 @@ double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,i 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 +429,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,7 +498,7 @@ 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 ) { @@ -750,11 +693,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 +711,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 +737,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 +772,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 +785,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 +832,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 +859,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 +890,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,14 +901,14 @@ 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 ( (retstr= LP_orderbook(coin->symbol,"KMD",-1)) != 0 ) { if ( (orderbook= cJSON_Parse(retstr)) != 0 ) { @@ -972,11 +931,26 @@ uint64_t LP_KMDvalue(struct iguana_info *coin,uint64_t balance) free_json(orderbook); } free(retstr); + }*/ + else + { + price = LP_price(coin->symbol,"KMD"); + KMDvalue = price * balance; } } 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 +975,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 +1084,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 +1120,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(); diff --git a/iguana/exchanges/LP_privkey.c b/iguana/exchanges/LP_privkey.c new file mode 100644 index 000000000..f9c533419 --- /dev/null +++ b/iguana/exchanges/LP_privkey.c @@ -0,0 +1,354 @@ + +/****************************************************************************** + * Copyright © 2014-2017 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ +// +// LP_utxos.c +// marketmaker +// + +int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 myprivkey,bits256 mypub) +{ + int32_t enable_utxos = 0; + char *script,destaddr[64]; cJSON *array,*item; bits256 txid,deposittxid,zero; int32_t used,i,flag=0,height,n,cmpflag,iambob,vout,depositvout; uint64_t *values=0,satoshis,txfee,biggerval,value,total = 0; int64_t targetval; //struct LP_utxoinfo *utxo; + if ( coin == 0 || (IAMLP == 0 && coin->inactive != 0) ) + { + //printf("coin not active\n"); + return(0); + } + if ( coin->privkeydepth > 0 ) + return(0); + coin->privkeydepth++; + LP_address(coin,coin->smartaddr); + //if ( coin->inactive == 0 ) + // LP_listunspent_issue(coin->symbol,coin->smartaddr,0); + memset(zero.bytes,0,sizeof(zero)); + array = LP_listunspent(coin->symbol,coin->smartaddr,zero,zero); + if ( array != 0 ) + { + txfee = LP_txfeecalc(coin,0,0); + if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) + { + coin->numutxos = n; + //printf("LP_privkey_init %s %d\n",coin->symbol,n); + for (iambob=0; iambob<=1; iambob++) + { + if ( iambob == 0 ) + values = calloc(n,sizeof(*values)); + else memset(values,0,n * sizeof(*values)); + used = 0; + for (i=0; isymbol,txid,vout); + if ( satoshis != 0 && satoshis != value ) + printf("%s %s privkey_init value %.8f vs %.8f (%s) %.8f %.8f\n",coin->symbol,coin->smartaddr,dstr(satoshis),dstr(value),jprint(item,0),jdouble(item,"amount"),jdouble(item,"interest")); + if ( coin->electrum != 0 || LP_inventory_prevent(iambob,coin->symbol,txid,vout) == 0 )//&& height > 0 ) + { + values[i] = satoshis; + //flag += LP_address_utxoadd(coin,destaddr,txid,vout,satoshis,height,-1); + } else used++; + } + //printf("array.%d\n",n); + while ( used < n-1 ) + { + //for (i=0; i= 0 ) + { + item = jitem(array,i); + if ( coin->electrum == 0 ) + { + deposittxid = jbits256(item,"txid"); + depositvout = juint(item,"vout"); + script = jstr(item,"scriptPubKey"); + } + else + { + deposittxid = jbits256(item,"tx_hash"); + depositvout = juint(item,"tx_pos"); + script = coin->smartaddr; + } + biggerval = values[i]; + values[i] = 0, used++; + if ( iambob == 0 ) + targetval = (biggerval / 776) + txfee; + else targetval = (biggerval / 9) * 8 + 2*txfee; + if ( targetval < txfee*2 ) + targetval = txfee*2; + //printf("iambob.%d i.%d deposit %.8f min %.8f target %.8f\n",iambob,i,dstr(biggerval),dstr((1+LP_MINSIZE_TXFEEMULT)*txfee),dstr(targetval)); + if ( biggerval < (1+LP_MINSIZE_TXFEEMULT)*txfee ) + continue; + i = -1; + if ( iambob != 0 ) + { + if ( (i= LP_nearestvalue(iambob,values,n,targetval)) < 0 ) + targetval /= 4; + if ( targetval < txfee*(1+LP_MINSIZE_TXFEEMULT) ) + continue; + } + if ( i >= 0 || (i= LP_nearestvalue(iambob,values,n,targetval)) >= 0 ) + { + //printf("iambob.%d i.%d %.8f target %.8f\n",iambob,i,dstr(biggerval),dstr(targetval)); + item = jitem(array,i); + cmpflag = 0; + if ( coin->electrum == 0 ) + { + txid = jbits256(item,"txid"); + vout = juint(item,"vout"); + if ( jstr(item,"scriptPubKey") != 0 && strcmp(script,jstr(item,"scriptPubKey")) == 0 ) + cmpflag = 1; + } + else + { + txid = jbits256(item,"tx_hash"); + vout = juint(item,"tx_pos"); + cmpflag = 1; + } + if ( cmpflag != 0 ) + { + value = values[i]; + values[i] = 0, used++; + /*portable_mutex_lock(&LP_UTXOmutex); + if ( iambob != 0 ) + { + if ( (utxo= LP_utxoadd(1,coin->symbol,txid,vout,value,deposittxid,depositvout,biggerval,coin->smartaddr,mypub,LP_gui,G.LP_sessionid,value)) != 0 ) + { + } + } + else + { + //printf("call utxoadd\n"); + if ( (utxo= LP_utxoadd(0,coin->symbol,deposittxid,depositvout,biggerval,txid,vout,value,coin->smartaddr,mypub,LP_gui,G.LP_sessionid,biggerval)) != 0 ) + { + } + } + portable_mutex_unlock(&LP_UTXOmutex);*/ + total += value; + } // else printf("scriptmismatch.(%s) vs %s\n",script,jprint(item,0)); + } //else printf("nothing near i.%d\n",i); + } else break; + } + if ( enable_utxos == 0 ) + break; + } + } + free_json(array); + if ( 0 && flag != 0 ) + LP_postutxos(coin->symbol,coin->smartaddr); + } + if ( values != 0 ) + free(values); + if ( coin->privkeydepth > 0 ) + coin->privkeydepth--; + //printf("privkey.%s %.8f\n",symbol,dstr(total)); + return(flag); +} + +char *LP_secretaddresses(void *ctx,char *prefix,char *passphrase,int32_t n,uint8_t taddr,uint8_t pubtype) +{ + int32_t i; uint8_t tmptype,pubkey33[33],rmd160[20]; char output[777*45],str[65],str2[65],buf[8192],wifstr[128],coinaddr[64]; bits256 checkprivkey,privkey,pubkey; cJSON *retjson; + retjson = cJSON_CreateObject(); + if ( prefix == 0 || prefix[0] == 0 ) + prefix = "secretaddress"; + if ( passphrase == 0 || passphrase[0] == 0 ) + passphrase = "password"; + if ( n <= 0 ) + n = 16; + else if ( n > 777 ) + n = 777; + conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); + bitcoin_priv2pub(ctx,pubkey33,coinaddr,privkey,taddr,pubtype); + printf("generator (%s) secrets.[%d] <%s> t.%u p.%u\n",coinaddr,n,passphrase,taddr,pubtype); + sprintf(output,"\"addresses\":["); + for (i=0; i %s vs %s?\n",wifstr,bits256_str(str,privkey),bits256_str(str2,checkprivkey)); + free_json(retjson); + return(clonestr("{\"error\":\"couldnt validate wifstr\"}")); + } + else if ( tmptype != pubtype ) + { + printf("checktype.%d != pubtype.%d\n",tmptype,pubtype); + free_json(retjson); + return(clonestr("{\"error\":\"couldnt validate pubtype\"}")); + } + jaddstr(retjson,coinaddr,wifstr); + sprintf(output+strlen(output),"\\\"%s\\\"%c ",coinaddr,ibytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); + //vcalc_sha256(0,checkkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); + //printf("SHA256.(%s) ",bits256_str(pstr,checkkey)); + //printf("privkey.(%s)\n",bits256_str(pstr,privkey)); + } + else + { + bitcoin_wif2priv(coin->wiftaddr,&tmptype,&privkey,wifstr); + if ( 0 ) + { + char str[65],str2[65]; + checkkey = iguana_wif2privkey(wifstr); + if ( bits256_cmp(checkkey,privkey) != 0 ) + printf("WIF.(%s) -> %s or %s?\n",wifstr,bits256_str(str,privkey),bits256_str(str2,checkkey)); + } + } + privkey.bytes[0] &= 248, privkey.bytes[31] &= 127, privkey.bytes[31] |= 64; + bitcoin_priv2pub(ctx,coin->pubkey33,coin->smartaddr,privkey,coin->taddr,coin->pubtype); + if ( coin->counter == 0 ) + { + coin->counter++; + memcpy(G.LP_pubsecp,coin->pubkey33,33); + bitcoin_priv2wif(coin->wiftaddr,tmpstr,privkey,coin->wiftype); + bitcoin_addr2rmd160(coin->taddr,&tmptype,G.LP_myrmd160,coin->smartaddr); + LP_privkeyadd(privkey,G.LP_myrmd160); + G.LP_privkey = privkey; + if ( 0 && (coin->pubtype != 60 || strcmp(coin->symbol,"KMD") == 0) ) + printf("%s (%s) %d wif.(%s) (%s)\n",coin->symbol,coin->smartaddr,coin->pubtype,tmpstr,passphrase); + if ( G.counter++ == 0 ) + { + bitcoin_priv2wif(coin->wiftaddr,G.USERPASS_WIFSTR,privkey,188); + bitcoin_wif2priv(coin->wiftaddr,&tmptype,&checkkey,G.USERPASS_WIFSTR); + if ( bits256_cmp(checkkey,privkey) != 0 ) + { + char str[65],str2[65]; + printf("FATAL ERROR converting USERPASS_WIFSTR %s -> %s != %s\n",G.USERPASS_WIFSTR,bits256_str(str,checkkey),bits256_str(str2,privkey)); + exit(-1); + } + conv_NXTpassword(userpass.bytes,pubkeyp->bytes,(uint8_t *)G.USERPASS_WIFSTR,(int32_t)strlen(G.USERPASS_WIFSTR)); + userpub = curve25519(userpass,curve25519_basepoint9()); + printf("userpass.(%s)\n",bits256_str(G.USERPASS,userpub)); + } + } + if ( coin->importedprivkey == 0 && coin->electrum == 0 && coin->userpass[0] != 0 && LP_getheight(coin) > 0 ) + { + memset(zero.bytes,0,sizeof(zero)); + LP_listunspent_issue(coin->symbol,coin->smartaddr,0,zero,zero); + if ( (retjson= LP_importprivkey(coin->symbol,tmpstr,coin->smartaddr,-1)) != 0 ) + { + if ( jobj(retjson,"error") != 0 ) + { + printf("cant importprivkey.%s -> (%s), abort session\n",coin->symbol,jprint(retjson,1)); + exit(-1); + } + free_json(retjson); + } + coin->importedprivkey = (uint32_t)time(NULL); + } + vcalc_sha256(0,checkkey.bytes,privkey.bytes,sizeof(privkey)); + checkkey.bytes[0] &= 248, checkkey.bytes[31] &= 127, checkkey.bytes[31] |= 64; + G.LP_mypub25519 = *pubkeyp = curve25519(checkkey,curve25519_basepoint9()); + G.LP_mypriv25519 = checkkey; + LP_pubkeyadd(G.LP_mypub25519); + return(privkey); +} + +void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase) +{ + struct iguana_info *coin,*tmp; bits256 pubkey,privkey; uint8_t pubkey33[33]; int32_t initonly; + initonly = (passphrase != 0); + memset(privkey.bytes,0,sizeof(privkey)); + memset(pubkey.bytes,0,sizeof(pubkey)); + //printf("Total coins: %d\n", HASH_COUNT(LP_coins)); + //int num_iter = 0; + HASH_ITER(hh,LP_coins,coin,tmp) + { + //printf("LP_privkey_updates [%02d / %02d]\n", num_iter++, HASH_COUNT(LP_coins)); + if ( initonly != 0 ) + { + coin->counter = 0; + memset(coin->smartaddr,0,sizeof(coin->smartaddr)); + if ( bits256_nonz(privkey) == 0 || coin->smartaddr[0] == 0 ) + privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,coin,passphrase,""); + } + //printf("i.%d of %d\n",i,LP_numcoins); + else if ( IAMLP == 0 || coin->inactive == 0 ) + { + //printf("from updates %s\n",coin->symbol); + if ( 0 && LP_privkey_init(pubsock,coin,G.LP_privkey,G.LP_mypub25519) == 0 && (LP_rand() % 10) == 0 ) + { + //LP_postutxos(coin->symbol,coin->smartaddr); + } + } + } +} + +int32_t LP_passphrase_init(char *passphrase,char *gui) +{ + static void *ctx; int32_t counter; //iambob,; struct LP_utxoinfo *utxo,*tmp; + if ( ctx == 0 ) + ctx = bitcoin_ctx(); + if ( G.LP_pendingswaps != 0 ) + return(-1); + G.initializing = 1; + if ( gui == 0 ) + gui = "cli"; + counter = G.USERPASS_COUNTER; + while ( G.waiting == 0 ) + { + printf("waiting for G.waiting\n"); + sleep(5); + } + /*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/LP_remember.c b/iguana/exchanges/LP_remember.c index f5ea3229a..0b8264214 100644 --- a/iguana/exchanges/LP_remember.c +++ b/iguana/exchanges/LP_remember.c @@ -255,13 +255,35 @@ bits256 basilisk_swap_privBn_extract(bits256 *bobrefundp,char *bobcoin,bits256 b bits256 basilisk_swap_spendupdate(int32_t iambob,char *symbol,char *spentaddr,int32_t *sentflags,bits256 *txids,int32_t utxoind,int32_t alicespent,int32_t bobspent,int32_t vout,char *aliceaddr,char *bobaddr,char *Adest,char *dest) { - bits256 spendtxid,txid; char destaddr[64],str[65]; struct iguana_info *coin; cJSON *histobj; + bits256 spendtxid,txid; char destaddr[64],str[65]; int32_t i,n,m; struct iguana_info *coin; cJSON *array,*txobj,*vins,*vin; if ( (coin= LP_coinfind(symbol)) != 0 && coin->electrum != 0 ) { - if ( (histobj= electrum_address_gethistory(symbol,coin->electrum,&histobj,spentaddr)) != 0 ) + //printf("spentaddr.%s aliceaddr.%s bobaddr.%s Adest.%s Bdest.%s\n",spentaddr,aliceaddr,bobaddr,Adest,dest); + 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(); @@ -637,6 +660,7 @@ 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; @@ -753,7 +777,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 +797,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 ) @@ -1101,7 +1126,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 +1151,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,8 +1178,11 @@ 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); } - } - return(item); + } else item = LP_swap_json(&rswap); + for (i=0; i 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)); } diff --git a/iguana/exchanges/LP_rpc.c b/iguana/exchanges/LP_rpc.c index 8639646ee..03d71fd25 100644 --- a/iguana/exchanges/LP_rpc.c +++ b/iguana/exchanges/LP_rpc.c @@ -206,6 +206,93 @@ cJSON *LP_NXT_decrypt(uint64_t txnum,char *account,char *data,char *nonce,char * return(retjson); } +int64_t NXTventure_qty(uint64_t assetid) +{ + char url[1024],*retstr; uint64_t qty=0; cJSON *retjson; + sprintf(url,"http://127.0.0.1:7876/nxt?requestType=getAccountAssets&account=NXT-XRK4-5HYK-5965-9FH4Z&includeAssetInfo=true"); + if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 ) + { + printf("NXT_venture_qty(%s)\n",retstr); + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + free_json(retjson); + } + free(retstr); + } + //NXT_venture_qty({"accountAssets":[{"quantityQNT":"3900000000","unconfirmedQuantityQNT":"3900000000","decimals":4,"name":"ATOMIC","asset":"11694807213441909013"},{"quantityQNT":"2900000000","unconfirmedQuantityQNT":"2900000000","decimals":8,"name":"NSC","asset":"6775372232354238105"},{"quantityQNT":"750000000","unconfirmedQuantityQNT":"750000000","decimals":4,"name":"omnigames","asset":"7441230892853180965"},{"quantityQNT":"607438148","unconfirmedQuantityQNT":"607438148","decimals":4,"name":"ARDR","asset":"12422608354438203866"},{"quantityQNT":"451991779","unconfirmedQuantityQNT":"451991779","decimals":4,"name":"SuperNET","asset":"12071612744977229797"},{"quantityQNT":"146960000","unconfirmedQuantityQNT":"146960000","decimals":4,"name":"Privatebet","asset":"17083334802666450484"},{"quantityQNT":"79500188","unconfirmedQuantityQNT":"79500188","decimals":3,"name":"crypto777","asset":"13476425053110940554"},{"quantityQNT":"1495473","unconfirmedQuantityQNT":"1495473","decimals":0,"name":"jl777hodl","asset":"6932037131189568014"},{"quantityQNT":"500000","unconfirmedQuantityQNT":"500000","decimals":0,"name":"Boost","asset":"9719950459730291994"},{"quantityQNT":"200000","unconfirmedQuantityQNT":"200000","decimals":0,"name":"NXTforex","asset":"15245281832566929110"},{"quantityQNT":"150000","unconfirmedQuantityQNT":"150000","decimals":0,"name":"NXTsharks","asset":"8049009002993773168"},{"quantityQNT":"100000","unconfirmedQuantityQNT":"100000","decimals":5,"name":"solarweb","asset":"13604572534081373849"},{"quantityQNT":"75000","unconfirmedQuantityQNT":"75000","decimals":0,"name":"SNN","asset":"15113552914305929842"},{"quantityQNT":"57299","unconfirmedQuantityQNT":"57299","decimals":2,"name":"SLEUTH","asset":"4174874835406708311"},{"quantityQNT":"18801","unconfirmedQuantityQNT":"18801","decimals":2,"name":"BTCDdev","asset":"15131486578879082754"},{"quantityQNT":"18767","unconfirmedQuantityQNT":"18767","decimals":2,"name":"longzai","asset":"10955830010602647139"},{"quantityQNT":"13000","unconfirmedQuantityQNT":"13000","decimals":0,"name":"NXTventure","asset":"16212446818542881180"},{"quantityQNT":"7250","unconfirmedQuantityQNT":"7250","decimals":0,"name":"InstantDEX","asset":"15344649963748848799"},{"quantityQNT":"2873","unconfirmedQuantityQNT":"2873","decimals":4,"name":"EDinar","asset":"17740527756732147253"},{"quantityQNT":"39","unconfirmedQuantityQNT":"39","decimals":0,"name":"JebBush","asset":"1929419574701797581"},{"quantityQNT":"30","unconfirmedQuantityQNT":"30","decimals":0,"name":"Hilary","asset":"11814755740231942504"}],"requestProcessingTime":1}) + return(qty); +} + +void *curl_post(void **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3); + +void NXTventure_liquidation() +{ + /*{"quantityQNT":"607438148","unconfirmedQuantityQNT":"607438148","decimals":4,"name":"ARDR","asset":""}, + {"quantityQNT":"451991779","unconfirmedQuantityQNT":"451991779","decimals":4,"name":"SuperNET","asset":"12071612744977229797"}, + {"quantityQNT":"146960000","unconfirmedQuantityQNT":"146960000","decimals":4,"name":"Privatebet","asset":"17083334802666450484"}, + {"quantityQNT":"79500188","unconfirmedQuantityQNT":"79500188","decimals":3,"name":"crypto777","asset":"13476425053110940554"}, + {"quantityQNT":"1495473","unconfirmedQuantityQNT":"1495473","decimals":0,"name":"jl777hodl","asset":"6932037131189568014"}, + {"quantityQNT":"7250","unconfirmedQuantityQNT":"7250","decimals":0,"name":"InstantDEX","asset":"15344649963748848799"},*/ + char *assetids[][4] = + { + { "12422608354438203866", "607438148", "ARDR", "10000" }, + { "12071612744977229797", "451991779", "SuperNET", "10000" }, + { "17083334802666450484", "146960000", "Privatebet", "10000" }, + { "13476425053110940554", "79500188", "crypto777", "1000" }, + { "6932037131189568014", "1495473", "jl777hodl", "1" }, + { "15344649963748848799", "7250", "InstantDEX", "1" }, + }; + void *cHandle=0; char *retstr,*retstr2,url[1024],*account; uint64_t txid,qty,qtyA,assetid,sum; double ratio; cJSON *array,*retjson2,*item,*retjson; int32_t i,j,decimals,numassetids=(int32_t)(sizeof(assetids)/sizeof(*assetids)),n=0; + char *passphrase = ""; + sprintf(url,"http://127.0.0.1:7876/nxt?requestType=getAssetAccounts&asset=16212446818542881180"); + if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( (array= jarray(&n,retjson,"accountAssets")) != 0 ) + { + for (j=0; j= 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[20],mult,txnum,assetid,qty; int32_t i,ind,numtx,past_marker=0; cJSON *item,*attach,*decjson,*array,*msgjson,*encjson,*retjson=0; @@ -388,7 +475,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 +485,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,7 +497,7 @@ 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; //printf("LP_gettx %s %s\n",symbol,bits256_str(str,txid)); @@ -431,7 +518,8 @@ cJSON *LP_gettx(char *symbol,bits256 txid) { if ( (retjson= electrum_transaction(symbol,coin->electrum,&retjson,txid,0)) != 0 ) return(retjson); - else printf("failed blockchain.transaction.get %s %s\n",coin->symbol,bits256_str(str,txid)); + 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 +527,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); @@ -485,7 +573,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,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 ) @@ -522,7 +610,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 ) @@ -586,7 +675,7 @@ cJSON *LP_validateaddress(char *symbol,char *address) } bitcoin_address(coinaddr,coin->taddr,coin->pubtype,G.LP_myrmd160,20); jadd(retjson,"ismine",strcmp(address,coin->smartaddr) == 0 ? cJSON_CreateTrue() : cJSON_CreateFalse()); - jadd(retjson,"iswatchonly",cJSON_CreateFalse()); + jadd(retjson,"iswatchonly",cJSON_CreateTrue()); jadd(retjson,"isscript",addrtype == coin->p2shtype ? cJSON_CreateTrue() : cJSON_CreateFalse()); return(retjson); } @@ -599,12 +688,30 @@ 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)); + } + //printf("%s\n",jprint(retjson,0)); + free_json(retjson); + } + return(doneflag); +} + +int32_t LP_address_iswatched(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,"iswatched")) != 0 && is_cJSON_True(obj) != 0 ) { doneflag = 1; //printf("%s ismine (%s)\n",address,jprint(retjson,0)); @@ -633,29 +740,100 @@ 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,symbol)) != 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); + } + } + if ( LP_address_ismine(symbol,coinaddr) > 0 || LP_address_iswatched(symbol,coinaddr) > 0 ) { if ( strcmp(symbol,"BTC") == 0 ) numconfs = 0; else numconfs = 1; sprintf(buf,"[%d, 99999999, [\"%s\"]]",numconfs,coinaddr); - return(bitcoin_json(coin,"listunspent",buf)); + //printf("LP_listunspent.(%s %s)\n",symbol,coinaddr); + retjson = bitcoin_json(coin,"listunspent",buf); + retstr = jprint(retjson,0); + LP_unspents_cache(coin->symbol,coinaddr,retstr,1); + free(retstr); + if ( ap != 0 ) + ap->unspenttime = (uint32_t)time(NULL); + return(retjson); } else return(LP_address_utxos(coin,coinaddr,0)); - } else return(electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,1)); + } else return(electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,1,reftxid,reftxid2)); } -int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag) +cJSON *LP_listreceivedbyaddress(char *symbol,char *coinaddr) +{ + char buf[128],*addr; bits256 zero; cJSON *retjson,*array,*item; int32_t i,n; struct iguana_info *coin; + if ( symbol == 0 || symbol[0] == 0 ) + return(cJSON_Parse("{\"error\":\"null symbol\"}")); + coin = LP_coinfind(symbol); + if ( coin == 0 || (IAMLP == 0 && coin->inactive != 0) ) + return(cJSON_Parse("{\"error\":\"no coin\"}")); + memset(zero.bytes,0,sizeof(zero)); + if ( coin->electrum == 0 ) + { + sprintf(buf,"[1, false, true]"); + if ( (array= bitcoin_json(coin,"listreceivedbyaddress",buf)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; ielectrum,&retjson,coinaddr,zero)); +} + +int64_t LP_listunspent_parseitem(struct iguana_info *coin,bits256 *txidp,int32_t *voutp,int32_t *heightp,cJSON *item) +{ + int64_t satoshis = 0; + if ( coin->electrum == 0 ) + { + *txidp = jbits256(item,"txid"); + *voutp = juint(item,"vout"); + satoshis = LP_value_extract(item,0); + *heightp = LP_txheight(coin,*txidp); + } + else + { + *txidp = jbits256(item,"tx_hash"); + *voutp = juint(item,"tx_pos"); + satoshis = j64bits(item,"value"); + *heightp = jint(item,"height"); + } + return(satoshis); +} + +int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag,bits256 reftxid,bits256 reftxid2) { struct iguana_info *coin; int32_t n = 0; cJSON *retjson=0; char *retstr=0; if ( symbol == 0 || symbol[0] == 0 ) @@ -664,7 +842,7 @@ int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag) { 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 +850,12 @@ 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); - } + 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 } @@ -805,9 +974,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 +1167,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); } @@ -1161,7 +1332,7 @@ const char *Notaries_elected[][2] = int32_t LP_txhasnotarization(struct iguana_info *coin,bits256 txid) { cJSON *txobj,*vins,*vin,*vouts,*vout,*spentobj,*sobj; char *hexstr; uint8_t script[35]; bits256 spenttxid; uint64_t notarymask; int32_t i,j,numnotaries,len,spentvout,numvins,numvouts,hasnotarization = 0; - if ( (txobj= LP_gettx(coin->symbol,txid)) != 0 ) + if ( (txobj= LP_gettx(coin->symbol,txid,0)) != 0 ) { if ( (vins= jarray(&numvins,txobj,"vin")) != 0 ) { @@ -1173,7 +1344,7 @@ 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 ) { diff --git a/iguana/exchanges/LP_scan.c b/iguana/exchanges/LP_scan.c index f3b67476b..90e2f3899 100644 --- a/iguana/exchanges/LP_scan.c +++ b/iguana/exchanges/LP_scan.c @@ -413,10 +413,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 +445,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 +465,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 +484,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 +514,7 @@ int32_t LP_mempool_vinscan(bits256 *spendtxidp,int32_t *spendvinp,char *symbol,c return(-1); if ( time(NULL) > coin->lastmempool+LP_MEMPOOL_TIMEINCR ) { - if ( (array= LP_getmempool(symbol,coinaddr)) != 0 ) + if ( (array= LP_getmempool(symbol,coinaddr,searchtxid,searchtxid2)) != 0 ) { free_json(array); coin->lastmempool = (uint32_t)time(NULL); diff --git a/iguana/exchanges/LP_signatures.c b/iguana/exchanges/LP_signatures.c index 6e99495cb..c73986f46 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; 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,30 @@ 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 ) + jadd(reqjson,"proof",LP_instantdex_txidaddjson()); 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..9126d1dde 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 @@ -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); @@ -558,22 +563,22 @@ int32_t LP_txheight_check(struct iguana_info *coin,char *coinaddr,struct LP_addr 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,up->U.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); } @@ -744,7 +746,7 @@ cJSON *_electrum_transaction(char *symbol,struct electrum_info *ep,cJSON **retjs cJSON *electrum_transaction(char *symbol,struct electrum_info *ep,cJSON **retjsonp,bits256 txid,char *SPVcheck) { - cJSON *retjson,*array; struct LP_transaction *tx; struct iguana_info *coin; + cJSON *retjson,*array; bits256 zero; struct LP_transaction *tx; struct iguana_info *coin; coin = LP_coinfind(symbol); if ( ep != 0 ) portable_mutex_lock(&ep->txmutex); @@ -753,7 +755,8 @@ cJSON *electrum_transaction(char *symbol,struct electrum_info *ep,cJSON **retjso { 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); @@ -779,12 +782,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; 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)); @@ -807,13 +811,13 @@ void electrum_test() if ( (retjson= electrum_transaction(symbol,ep,0,hash,0)) != 0 ) printf("electrum_transaction %s\n",jprint(retjson,1)); addr = "14NeevLME8UAANiTCVNgvDrynUPk1VcQKb"; - if ( (retjson= electrum_address_gethistory(symbol,ep,0,addr)) != 0 ) + 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 +902,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 +976,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 +1008,30 @@ 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"); + break; + } + } + else + { + printf("no more electrum data when expected\n"); + break; + } + } + if ( len > 0 ) { ep->pending = 0; LP_recvfunc(ep,(char *)ep->buf,len); @@ -1041,13 +1068,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); diff --git a/iguana/exchanges/LP_statemachine.c b/iguana/exchanges/LP_statemachine.c index 54d9ddc95..21b8eeaf7 100644 --- a/iguana/exchanges/LP_statemachine.c +++ b/iguana/exchanges/LP_statemachine.c @@ -479,7 +479,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 +1846,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 +1984,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; @@ -1911,6 +2053,90 @@ int32_t bitcoin_coinptrs(bits256 pubkey,struct iguana_info **bobcoinp,struct igu if ( LP_ismine(utxo) > 0 && strcmp(utxo->coin,base) == 0 ) LP_priceping(LP_mypubsock,utxo,rel,price * LP_profitratio); }*/ + +int32_t LP_ismine(struct LP_utxoinfo *utxo) +{ + if ( utxo != 0 && bits256_cmp(utxo->pubkey,G.LP_mypub25519) == 0 ) + return(1); + else return(0); +} + +queue_t utxosQ; +struct LP_utxos_qitem { struct queueitem DL; cJSON *argjson; }; + +char *LP_postutxos_recv(cJSON *argjson) +{ + struct LP_utxos_qitem *uitem; struct iguana_info *coin; char *coinaddr,*symbol; bits256 utxoshash,pubkey; cJSON *obj; struct LP_pubkey_info *pubp; + printf("LP_postutxos_recv deprecated\n"); + pubkey = jbits256(argjson,"pubkey"); + pubp = LP_pubkeyfind(pubkey); + if ( pubp != 0 && pubp->numerrors > LP_MAXPUBKEY_ERRORS ) + return(clonestr("{\"error\":\"blacklisted\"}")); + if ( (coinaddr= jstr(argjson,"coinaddr")) != 0 && (symbol= jstr(argjson,"coin")) != 0 && (coin= LP_coinfind(symbol)) != 0 ) + { + if ( strcmp(coinaddr,coin->smartaddr) == 0 ) + { + //printf("ignore my utxo from external source %s %s\n",symbol,coinaddr); + return(clonestr("{\"result\":\"success\"}")); + } + } + if ( (obj= jobj(argjson,"utxos")) != 0 ) + { + utxoshash = LP_utxoshash_calc(obj); + //char str[65]; //printf("got utxoshash %s\n",bits256_str(str,utxoshash)); + if ( LP_utxos_sigcheck(juint(argjson,"timestamp"),jstr(argjson,"sig"),jstr(argjson,"pubsecp"),pubkey,utxoshash) == 0 ) + { + uitem = calloc(1,sizeof(*uitem)); + uitem->argjson = jduplicate(argjson); + queue_enqueue("utxosQ",&utxosQ,&uitem->DL); + return(clonestr("{\"result\":\"success\"}")); + } //else printf("valid utxos sig %s\n",bits256_str(str,pubp->pubkey)); + } + return(clonestr("{\"error\":\"sig failure\"}")); +} + +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 +2571,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; @@ -2494,6 +2741,466 @@ else 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 ) + { + if ( LP_ismine(utxo) > 0 ) + { + //LP_utxo_clientpublish(utxo); + if ( LP_mypeer != 0 ) + utxo->T.lasttime = (uint32_t)time(NULL); + } + } + return(utxo); +} + +int32_t _LP_utxos_remove(bits256 txid,int32_t vout) +{ + struct LP_utxoinfo *utxo,*utxo2; int32_t retval = 0,iambob = 1; + utxo = utxo2 = 0; + if ( (utxo= _LP_utxofind(iambob,txid,vout)) != 0 ) + { + if ( LP_isavailable(utxo) == 0 ) + retval = -1; + else + { + if ( (utxo2= _LP_utxo2find(iambob,txid,vout)) != 0 ) + { + if ( LP_isavailable(utxo) == 0 ) + retval = -1; + else + { + _LP_utxo_delete(iambob,utxo); + _LP_utxo2_delete(iambob,utxo2); + } + } + } + } + else if ( (utxo2= _LP_utxo2find(iambob,txid,vout)) != 0 ) + { + if ( LP_isavailable(utxo2) == 0 ) + retval = -1; + else _LP_utxo2_delete(iambob,utxo2); + } + return(retval); +} + +int32_t LP_utxos_remove(bits256 txid,int32_t vout) +{ + int32_t retval; + portable_mutex_lock(&LP_utxomutex); + retval = _LP_utxos_remove(txid,vout); + portable_mutex_unlock(&LP_utxomutex); + return(retval); +} + +cJSON *LP_inventory(char *symbol) +{ + struct LP_utxoinfo *utxo,*tmp; struct _LP_utxoinfo u; char *myipaddr; cJSON *array; uint64_t val,val2; int32_t iambob = 0; struct iguana_info *coin; + array = cJSON_CreateArray(); + if ( LP_mypeer != 0 ) + myipaddr = LP_mypeer->ipaddr; + else myipaddr = "127.0.0.1"; + if ( (coin= LP_coinfind(symbol)) != 0 ) + LP_listunspent_both(symbol,coin->smartaddr,0); + HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,tmp) + { + char str[65]; + //printf("iambob.%d iterate %s\n",iambob,bits256_str(str,LP_mypub25519)); + if ( LP_isunspent(utxo) != 0 && strcmp(symbol,utxo->coin) == 0 && utxo->iambob == iambob && LP_ismine(utxo) > 0 ) + { + u = (iambob != 0) ? utxo->deposit : utxo->fee; + if ( LP_iseligible(&val,&val2,iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,u.txid,u.vout) == 0 ) + { + //if ( utxo->T.spentflag == 0 ) + // utxo->T.spentflag = (uint32_t)time(NULL); + //printf("%s %s ineligible %.8f %.8f\n",utxo->coin,bits256_str(str,u.txid),dstr(val),dstr(val2)); + continue; + } + //if ( iambob != 0 ) + // LP_utxo_clientpublish(utxo); + jaddi(array,LP_inventoryjson(cJSON_CreateObject(),utxo)); + } + else if ( 0 && LP_ismine(utxo) > 0 && strcmp(symbol,utxo->coin) == 0 ) + printf("skip %s %s %d %d %d %d\n",utxo->coin,bits256_str(str,utxo->payment.txid),LP_isunspent(utxo) != 0,strcmp(symbol,utxo->coin) == 0,utxo->iambob == iambob,LP_ismine(utxo) > 0); + } + return(array); +} + /*while ( time(NULL) < expiration ) { if ( (price= LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout)) > SMALLVAL ) @@ -2503,6 +3210,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); @@ -3039,6 +3830,36 @@ if ( (0) ) #undef aptr #undef bptr }*/ +/*if ( (utxo= LP_utxoadd(1,coin->symbol,up->U.txid,up->U.vout,up->U.value,up2->U.txid,up2->U.vout,up2->U.value,coinaddr,ap->pubkey,G.gui,0,targetval)) != 0 ) + { + utxo->S.satoshis = targetval; + char str[65],str2[65]; printf("butxo.%p targetval %.8f, found val %.8f %s | targetval2 %.8f val2 %.8f %s\n",utxo,dstr(targetval),dstr(up->U.value),bits256_str(str,utxo->payment.txid),dstr(targetval2),dstr(up2->U.value),bits256_str(str2,utxo->deposit.txid)); + return(butxo); + }*/ + +/*if ( (sobj= jobj(v,"scriptPubKey")) != 0 ) + { + if ( (scriptstr= jstr(sobj,"hex")) != 0 ) + { + printf("amount64 %.8f vout.%d (%s) weeki.%d %.8f (%s)\n",dstr(amount64),vout,jprint(v,0),weeki,dstr(satoshis),scriptstr); + len = (int32_t)strlen(scriptstr) >> 1; + if ( len <= sizeof(spendscript)/sizeof(*spendscript) ) + { + decode_hex(spendscript,len,scriptstr); + if ( spendscript[11] == 33 ) + { + pub33 = &spendscript[12]; + redeemlen = LP_deposit_addr(p2shaddr,redeemscript,coin->taddr,coin->p2shtype,timestamp,pub33); + if ( len == redeemlen && (timestamp % LP_WEEKMULT) == 0 ) + { + bitcoin_address(coinaddr,coin->taddr,coin->pubtype,pub33,33); + printf("%s -> matched %s script t.%u weeki.%d deposit %.8f\n",coinaddr,p2shaddr,timestamp,(timestamp-LP_FIRSTWEEKTIME)/LP_WEEKMULT,dstr(satoshis)); + // add to pubp->credits; + } + } + } + } + }*/ /*portable_mutex_lock(&ep->pendingQ.mutex); if ( ep->pendingQ.list != 0 ) @@ -3059,6 +3880,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..e460c1c6c 100644 --- a/iguana/exchanges/LP_stats.c +++ b/iguana/exchanges/LP_stats.c @@ -20,27 +20,11 @@ #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" }; -uint32_t LP_atomic_locktime(char *base,char *rel) -{ - if ( strcmp(base,"BTC") != 0 && strcmp(rel,"BTC") != 0 ) - return(INSTANTDEX_LOCKTIME); - else return(INSTANTDEX_LOCKTIME * 10); -} - static uint32_t LP_requests,LP_reserveds,LP_connects,LP_connecteds,LP_tradestatuses,LP_parse_errors,LP_unknowns,LP_duplicates,LP_aliceids; void LP_tradecommand_log(cJSON *argjson) @@ -130,18 +114,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 +168,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 +178,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); @@ -222,7 +211,7 @@ int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSO 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; struct LP_pubkey_info *pubp; struct LP_pubswap *ptr; 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,8 +231,11 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj) if ( (sp= LP_swapstats_find(aliceid)) != 0 ) { sp->methodind = methodind; + sp->Q.R.requestid = requestid; + sp->Q.R.quoteid = quoteid; if ( LP_swapstats_update(sp,&Q,lineobj) == 0 ) flag = 1; + //else printf("LP_swapstats_update error\n"); } if ( flag == 0 ) { @@ -253,14 +245,20 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj) { sp->methodind = methodind; if ( LP_swapstats_update(sp,&Q,lineobj) == 0 ) + { flag = 1; - else printf("error after delayed match\n"); - break; + break; + } + printf("error after delayed match\n"); } } } if ( flag == 0 ) - printf("unexpected.%d tradestatus.(%s)\n",unexpected++,jprint(lineobj,0)); + { + static uint32_t counter; + if ( counter++ < 3 ) + printf("unexpected.%d tradestatus aliceid.%llu requestid.%u quoteid.%u\n",unexpected++,(long long)aliceid,requestid,quoteid);//,jprint(lineobj,0)); + } return(0); } if ( LP_quoteparse(&Q,lineobj) < 0 ) @@ -290,6 +288,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,16 +306,31 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj) } else { - if ( (sp= LP_swapstats_add(aliceid)) != 0 ) + //printf("create aliceid.%llu\n",(long long)aliceid); + if ( (sp= LP_swapstats_add(aliceid,RTflag)) != 0 ) { sp->Q = Q; sp->qprice = qprice; sp->methodind = methodind; sp->ind = LP_aliceids++; + sp->lasttime = (uint32_t)time(NULL); strcpy(sp->bobgui,"nogui"); strcpy(sp->alicegui,"nogui"); - //LP_swapstats_line(numtrades,basevols,relvols,line,sp); - //printf("%s\n",line); + if ( sp->finished == 0 && sp->expired == 0 ) + { + if ( (pubp= LP_pubkeyadd(sp->Q.srchash)) != 0 ) + { + ptr = calloc(1,sizeof(*ptr)); + ptr->swap = sp; + DL_APPEND(pubp->bobswaps,ptr); + } + if ( (pubp= LP_pubkeyadd(sp->Q.desthash)) != 0 ) + { + ptr = calloc(1,sizeof(*ptr)); + ptr->swap = sp; + DL_APPEND(pubp->aliceswaps,ptr); + } + } } else printf("unexpected LP_swapstats_add failure\n"); } if ( sp != 0 ) @@ -330,11 +346,103 @@ 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); + 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; int32_t methodind; + //printf("swapstatus.(%s)\n",jprint(argjson,0)); + if ( (sp= LP_swapstats_find(j64bits(argjson,"aliceid"))) != 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"); + } + } + return(clonestr("{\"result\":\"success\"}")); +} + +char *LP_gettradestatus(uint64_t aliceid) +{ + struct LP_swapstats *sp; cJSON *reqjson; bits256 zero; + //printf("gettradestatus.(%llu)\n",(long long)aliceid); + if ( (sp= LP_swapstats_find(aliceid)) != 0 && 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)); + } + } + return(clonestr("{\"error\":\"cant find aliceid\"}")); +} + +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 ( sp->finished != 0 || sp->expired != 0 ) + retval = 1; + dispflag = 0; + if ( starttime == 0 && endtime == 0 ) + dispflag = 1; + else if ( starttime > time(NULL) && endtime == starttime && sp->finished == 0 && sp->expired == 0 ) + dispflag = 1; + else if ( sp->Q.timestamp >= starttime && sp->Q.timestamp <= endtime ) + dispflag = 1; + if ( refbase != 0 && strcmp(refbase,sp->Q.srccoin) != 0 && strcmp(refbase,sp->Q.destcoin) != 0 ) + dispflag = 0; + if ( refrel != 0 && strcmp(refrel,sp->Q.srccoin) != 0 && strcmp(refrel,sp->Q.destcoin) != 0 ) + dispflag = 0; + if ( dispflag != 0 ) + { + dispflag = 0; + if ( refgui == 0 || refgui[0] == 0 || strcmp(refgui,sp->bobgui) == 0 || strcmp(refgui,sp->alicegui) == 0 ) + { + if ( bits256_nonz(refpubkey) == 0 || bits256_cmp(refpubkey,sp->Q.srchash) == 0 || bits256_cmp(refpubkey,sp->Q.desthash) == 0 ) + dispflag = 1; + } + } + if ( dispflag != 0 ) + jaddi(array,LP_swapstats_json(sp)); + return(retval); +} + +cJSON *LP_statslog_disp(uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey,char *refbase,char *refrel) +{ + static int32_t rval; + cJSON *retjson,*array,*item,*reqjson; struct LP_pubkey_info *pubp,*ptmp; bits256 zero; uint32_t now; struct LP_swapstats *sp,*tmp; int32_t i,n,numtrades[LP_MAXPRICEINFOS]; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS]; + if ( rval == 0 ) + rval = (LP_rand() % 300) + 60; if ( starttime > endtime ) starttime = endtime; + n = LP_statslog_parse(); memset(basevols,0,sizeof(basevols)); memset(relvols,0,sizeof(relvols)); memset(numtrades,0,sizeof(numtrades)); @@ -342,45 +450,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 ) + if ( LP_stats_dispiter(array,sp,starttime,endtime,refbase,refrel,refgui,refpubkey) > 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; - } + 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(pubp->pubkey,0); + } + //printf("RT.%d completed.%d\n",LP_RTcount,LP_swapscount); jadd(retjson,"swaps",array); + jaddnum(retjson,"RTcount",LP_RTcount); + jaddnum(retjson,"swapscount",LP_swapscount); array = cJSON_CreateArray(); for (i=0; i-timescale*1024, endtime=, timescale=60) -> [timestamp, high, low, open, close, relvolume, basevolume, aveprice, numtrades] + +struct LP_ohlc +{ + uint32_t timestamp,firsttime,lasttime,numtrades; + double high,low,open,close,relsum,basesum; +}; + +cJSON *LP_ohlc_json(struct LP_ohlc *bar,struct LP_ohlc *prevbar) +{ + cJSON *item; struct LP_ohlc tmp; + memset(&tmp,0,sizeof(tmp)); + if ( bar->numtrades == 0 ) + { + tmp = *prevbar; + tmp.timestamp = bar->timestamp; + 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 *base,char *rel,uint32_t starttime,uint32_t endtime,int32_t timescale) +{ + struct LP_ohlc *bars,nonz; cJSON *array,*item,*statsjson,*swaps; uint32_t timestamp; bits256 zero; 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; + LP_ohlc_update(&bars[bari],timestamp,jdouble(item,"basevol"),jdouble(item,"relvol")); + } 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..fe905c424 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 ) @@ -125,18 +132,21 @@ void basilisk_swap_finished(struct basilisk_swap *swap) 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); @@ -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,11 +742,11 @@ 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 ) @@ -746,8 +756,11 @@ int32_t LP_swapwait(uint32_t requestid,uint32_t quoteid,int32_t duration,int32_t 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)) != 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"); @@ -831,7 +844,7 @@ void LP_bobloop(void *_swap) 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); } } } @@ -851,7 +864,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,41 +880,53 @@ 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_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); + } } } } @@ -1029,7 +1054,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 +1101,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 +1114,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 ) { @@ -1151,20 +1180,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 +1215,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 +1234,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..7f3742304 100644 --- a/iguana/exchanges/LP_tradebots.c +++ b/iguana/exchanges/LP_tradebots.c @@ -195,7 +195,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 +413,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 +456,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 +472,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 +482,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 +494,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 +519,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..cc74a6229 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 ) @@ -402,24 +402,26 @@ int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype, vpnstr[0] = 0; *signedtx = 0; memset(signedtxidp,0,sizeof(*signedtxidp)); + //printf("bitcoin_verifyvins numvins.%d numvouts.%d\n",msgtx->tx_in,numvouts); for (vini=0; vinitx_in; vini++) { if ( V->p2shscript[0] != 0 && V->p2shlen != 0 ) { script = V->p2shscript; scriptlen = V->p2shlen; - //for (j=0; jp2shlen.%d\n",V->p2shlen); } else { script = msgtx->vins[vini].spendscript; scriptlen = msgtx->vins[vini].spendlen; } - if ( zcash == LP_IS_BITCOINCASH ) - sighash |= SIGHASH_FORKID; - sigtxid = bitcoin_sigtxid(taddr,pubtype,p2shtype,isPoS,height,serialized,maxlen,msgtx,vini,script,scriptlen,sighash,vpnstr,suppress_pubkeys,zcash); + //for (j=0; jvins[vini].prev_hash,msgtx->vins[vini].prev_vout); + sigtxid = bitcoin_sigtxid(symbol,taddr,pubtype,p2shtype,isPoS,height,serialized,maxlen,msgtx,vini,script,scriptlen,V[vini].amount,sighash,vpnstr,suppress_pubkeys,zcash); + //printf("bitcoin_verifyvins scriptlen.%d siglen.%d\n",scriptlen,V[vini].signers[0].siglen); if ( bits256_nonz(sigtxid) != 0 ) { vp = &V[vini]; @@ -447,6 +449,7 @@ int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype, if ( sig == 0 || siglen == 0 ) { memset(vp->signers[j].pubkey,0,sizeof(vp->signers[j].pubkey)); + printf("no sig.%p or siglen.%d zero\n",sig,siglen); continue; } if ( bitcoin_verify(ctx,sig,siglen-1,sigtxid,vp->signers[j].pubkey,bitcoin_pubkeylen(vp->signers[j].pubkey)) < 0 ) @@ -465,7 +468,7 @@ int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype, printf(" <- sig[%d]\n",j); for (z=0; z<33; z++) printf("%02x",vp->signers[j].pubkey[z]); - bitcoin_address(tmpaddr,60,vp->signers[j].pubkey,33); + bitcoin_address(tmpaddr,0,0,vp->signers[j].pubkey,33); printf(" <- pub, SIG.%d.%d VERIFIED numsigs.%d vs M.%d %s\n",vini,j,numsigs,vp->M,tmpaddr);*/ } } @@ -475,7 +478,7 @@ int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype, } iguana_msgtx_Vset(serialized,maxlen,msgtx,V); cJSON *txobj = cJSON_CreateObject(); - *signedtx = iguana_rawtxbytes(taddr,pubtype,p2shtype,isPoS,height,txobj,msgtx,suppress_pubkeys,zcash); + *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 +494,7 @@ int64_t iguana_lockval(int32_t finalized,int64_t locktime) int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,struct iguana_msgtx *msgtx,char **signedtxp,bits256 *signedtxidp,struct vin_info *V,int32_t numinputs,char *rawtx,cJSON *vins,cJSON *privkeysjson,int32_t zcash) { - uint8_t *serialized,*serialized2,*serialized3,*serialized4,*extraspace,pubkeys[64][33]; int32_t finalized,i,len,n,z,plen,maxsize,complete = 0,extralen = 100000; char *privkeystr,*signedtx = 0; bits256 privkeys[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 +506,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_ extraspace = malloc(extralen); memset(msgtx,0,sizeof(*msgtx)); decode_hex(serialized,len,rawtx); - if ( (txobj= bitcoin_hex2json(taddr,pubtype,p2shtype,isPoS,height,&txid,msgtx,rawtx,extraspace,extralen,serialized4,vins,V->suppress_pubkeys,zcash)) != 0 ) + if ( (txobj= bitcoin_hex2json(symbol,taddr,pubtype,p2shtype,isPoS,height,&txid,msgtx,rawtx,extraspace,extralen,serialized4,vins,V->suppress_pubkeys,zcash)) != 0 ) { //printf("back from bitcoin_hex2json (%s)\n",jprint(vins,0)); } else printf("no txobj from bitcoin_hex2json\n"); @@ -512,7 +515,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_ { //printf("numinputs.%d (%s) msgtx.%d\n",numinputs,jprint(vins,0),msgtx->tx_in); memset(msgtx,0,sizeof(*msgtx)); - if ( iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,0,0,serialized,maxsize,msgtx,&txid,"",extraspace,extralen,vins,V->suppress_pubkeys,zcash) > 0 && numinputs == msgtx->tx_in ) + if ( iguana_rwmsgtx(symbol,taddr,pubtype,p2shtype,isPoS,height,0,0,serialized,maxsize,msgtx,&txid,"",extraspace,extralen,vins,V->suppress_pubkeys,zcash) > 0 && numinputs == msgtx->tx_in ) { memset(pubkeys,0,sizeof(pubkeys)); memset(privkeys,0,sizeof(privkeys)); @@ -540,7 +543,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 +602,8 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_ } finalized = iguana_vininfo_create(taddr,pubtype,p2shtype,isPoS,serialized2,maxsize,msgtx,vins,numinputs,V); //printf("finalized.%d ignore_cltverr.%d suppress.%d\n",finalized,V[0].ignore_cltverr,V[0].suppress_pubkeys); - if ( (complete= bitcoin_verifyvins(ctx,symbol,taddr,pubtype,p2shtype,isPoS,height,signedtxidp,&signedtx,msgtx,serialized3,maxsize,V,SIGHASH_ALL,1,V->suppress_pubkeys,zcash)) > 0 && signedtx != 0 ) + sighash = LP_sighash(symbol,zcash); + if ( (complete= bitcoin_verifyvins(ctx,symbol,taddr,pubtype,p2shtype,isPoS,height,signedtxidp,&signedtx,msgtx,serialized3,maxsize,V,sighash,1,V->suppress_pubkeys,zcash)) > 0 && signedtx != 0 ) { /*int32_t tmp; //char str[65]; if ( (tmp= iguana_interpreter(ctx,cJSON_CreateArray(),iguana_lockval(finalized,jint(txobj,"locktime")),V,numinputs)) < 0 ) @@ -621,7 +625,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 +641,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; ivins[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); + //for (j=0; jvins[i].spendlen; j++) + // printf("%02x",msgtx->vins[i].spendscript[j]); + //printf(" spendscript, vin.%d (%s) scriptlen.%d spendlen.%d:%d finalize.%d\n",i,jprint(item,0),msgtx->vins[i].scriptlen,V[i].spendlen,msgtx->vins[i].spendlen,finalized); } - 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); + jadd(retjson,"complete",complete!=0?jtrue():jfalse()); free(serialized), free(serialized2); if ( signedtx != 0 ) free(signedtx); @@ -709,7 +752,7 @@ char *iguana_validaterawtx(void *ctx,struct iguana_info *coin,struct iguana_msgt void test_validate(char *signedtx) { char *retstr; uint8_t extraspace[8192]; int32_t mempool=0; struct iguana_msgtx msgtx; struct iguana_info *coin = LP_coinfind("BTC"); - retstr = iguana_validaterawtx(bitcoin_ctx(),coin,&msgtx,extraspace,sizeof(extraspace),signedtx,mempool,0,coin->zcash); + retstr = iguana_validaterawtx(bitcoin_ctx(),coin,&msgtx,extraspace,sizeof(extraspace),signedtx,mempool,0,LP_IS_BITCOINCASH); printf("validate test.(%s)\n",retstr); } @@ -730,7 +773,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 ) { @@ -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*16]; 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); @@ -1165,13 +1211,8 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf return(0); } } - //if ( bits256_nonz(utxotxid) == 0 ) - { - if ( (ap= LP_address_utxo_reset(coin)) == 0 ) - return(0); - } - //else if ( (ap= LP_address(coin,coin->smartaddr)) == 0 ) - // return(0); + 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 ) { @@ -1202,11 +1243,6 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf txobj = bitcoin_txcreate(coin->symbol,coin->isPoS,locktime,1,timestamp); jdelete(txobj,"vin"); jadd(txobj,"vin",jduplicate(vins)); - if ( change < 6000 ) - { - adjust = change / numvouts; - change = 0; - } printf("change %.8f = total %.8f - amount %.8f, adjust %.8f numvouts.%d\n",dstr(change),dstr(total),dstr(amount),dstr(adjust),numvouts); for (i=0; ipubtype ) 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 @@ -1230,19 +1272,25 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf 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,6 +1319,8 @@ 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 ) + return(0); privkeys = cJSON_CreateArray(); vins = cJSON_CreateArray(); memset(V,0,sizeof(*V) * maxV); @@ -1293,7 +1343,13 @@ char *LP_withdraw(struct iguana_info *coin,cJSON *argjson) if ( 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; 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 ) diff --git a/iguana/exchanges/LP_utxo.c b/iguana/exchanges/LP_utxo.c index 8ea1d2db5..0c2ecd81e 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,22 @@ 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 ) + return(0); 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("added %d from listunspents\n",n); + //printf("added %d from listunspents\n",m); } free_json(array); } @@ -555,10 +577,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; if ( coin->electrum == 0 ) { - if ( (array= LP_listunspent(coin->symbol,coinaddr)) != 0 ) + memset(zero.bytes,0,sizeof(zero)); + if ( (array= LP_listunspent(coin->symbol,coinaddr,zero,zero)) != 0 ) { if ( (n= cJSON_GetArraySize(array)) > 0 ) { @@ -573,9 +596,9 @@ cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electr } else { - if ( strcmp(coin->smartaddr,coinaddr) == 0 ) + //if ( strcmp(coin->smartaddr,coinaddr) == 0 ) balance = LP_unspents_load(coin->symbol,coinaddr); - else + /*else { if ( (array= LP_address_utxos(coin,coinaddr,1)) != 0 ) { @@ -589,7 +612,7 @@ cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electr } free_json(array); } - } + }*/ } retjson = cJSON_CreateObject(); jaddstr(retjson,"result","success"); @@ -642,66 +665,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 +704,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); @@ -803,7 +766,7 @@ int32_t LP_txheight(struct iguana_info *coin,bits256 txid) 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"); @@ -829,7 +792,7 @@ int32_t LP_txheight(struct iguana_info *coin,bits256 txid) 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,numconfirms = 100; cJSON *txobj; if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) return(-1); @@ -843,7 +806,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,7 +814,8 @@ 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); else if ( mempool != 0 ) @@ -964,6 +928,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 +970,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 +978,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 +1034,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 +1052,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/claim b/iguana/exchanges/claim new file mode 100755 index 000000000..20ec10c44 --- /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\":\"zeroconf_claim\",\"address\":\"$1\",\"expiration\":$2}" diff --git a/iguana/exchanges/deposit b/iguana/exchanges/deposit new file mode 100755 index 000000000..1fe7c6138 --- /dev/null +++ b/iguana/exchanges/deposit @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"zeroconf_deposit\",\"weeks\":0,\"amount\":10.0,\"broadcast\":1}" diff --git a/iguana/exchanges/deposit1 b/iguana/exchanges/deposit1 new file mode 100755 index 000000000..c82178e79 --- /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\":\"zeroconf_deposit\",\"weeks\":1,\"amount\":10.0,\"broadcast\":1}" 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/install b/iguana/exchanges/install index efb2c7a2e..7bbc5535d 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 dynamictrust getcoin kickstart tradesarray claim deposit 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/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.c b/iguana/exchanges/mm.c index a87481f15..f4d147131 100644 --- a/iguana/exchanges/mm.c +++ b/iguana/exchanges/mm.c @@ -881,6 +881,18 @@ int main(int argc, const char * argv[]) 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]); + bitcoin_address(coinaddr,0,60,rmd160,20); + bitcoin_addr2rmd160(0,&addrtype,rmd160b,coinaddr); + bitcoin_address(coinaddr2,0,0,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); diff --git a/iguana/exchanges/sell b/iguana/exchanges/sell index a48ffaac1..ddbff6118 100755 --- a/iguana/exchanges/sell +++ b/iguana/exchanges/sell @@ -1,3 +1,3 @@ #!/bin/bash source userpass -curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"sell\",\"base\":\"KMD\",\"rel\":\"BTC\",\"basevolume\":10.0\",\"price\":0.0005}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"sell\",\"base\":\"KMD\",\"rel\":\"BTC\",\"basevolume\":10.0,\"price\":0.0005}" diff --git a/iguana/exchanges/stats.c b/iguana/exchanges/stats.c index 681da52d2..69d6435ab 100644 --- a/iguana/exchanges/stats.c +++ b/iguana/exchanges/stats.c @@ -33,7 +33,7 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t mypubsock,cJSON *argjson,char char *stats_validmethods[] = { "psock", "getprices", "notify", "getpeers", // from issue_ "uitem", "listunspent", - "orderbook", "help", "getcoins", "pricearray", "balance", "tradestatus" + "orderbook", "help", "getcoins", "pricearray", "balance", "tradesarray" }; int32_t LP_valid_remotemethod(cJSON *argjson) @@ -310,7 +310,7 @@ cJSON *SuperNET_urlconv(char *value,int32_t bufsize,char *urlstr) jaddstr(json,key,value); else jaddistr(array,key); len += (n + 1); - if ( strcmp(key,"Content-Length") == 0 && (datalen= atoi(value)) > 0 ) + if ( (strcmp(key,"Content-Length") == 0 || strcmp(key,"content-length") == 0) && (datalen= atoi(value)) > 0 ) { data = &urlstr[totallen - datalen]; data[-1] = 0; @@ -329,8 +329,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 +568,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 +605,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 +633,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 +705,23 @@ void LP_rpc_processreq(void *_ptr) //printf("RETURN.(%s) jsonflag.%d postflag.%d\n",retstr,jsonflag,postflag); if ( jsonflag != 0 || postflag != 0 ) { - if ( retstr == 0 ) - retstr = clonestr("{}"); - response = malloc(strlen(retstr)+1024+1+1); + if ( strlen(retstr)+1024+1+1 < sizeof(space2) ) + response = space2; + else + { + response = malloc(strlen(retstr)+1024+1+1); + //printf("alloc response.%p\n",response); + } sprintf(hdrs,"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Credentials: true\r\nAccess-Control-Allow-Methods: GET, POST\r\nCache-Control : no-cache, no-store, must-revalidate\r\n%sContent-Length : %8d\r\n\r\n",content_type,(int32_t)strlen(retstr)); response[0] = '\0'; strcat(response,hdrs); strcat(response,retstr); strcat(response,"\n"); if ( retstr != space ) + { + //printf("free retstr0.%p\n",retstr); free(retstr); + } retstr = response; //printf("RET.(%s)\n",retstr); } @@ -727,16 +745,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; @@ -787,10 +817,12 @@ void stats_rpcloop(void *args) memcpy(&ipbits,&cli_addr.sin_addr.s_addr,sizeof(ipbits)); 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/tradesarray b/iguana/exchanges/tradesarray new file mode 100755 index 000000000..982bdca7c --- /dev/null +++ b/iguana/exchanges/tradesarray @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"tradesarray\",\"base\":\"REVS\",\"rel\":\"KMD\",\"timescale\":3600}" diff --git a/iguana/iguana777.h b/iguana/iguana777.h index 74412e6f0..843ed9c77 100755 --- a/iguana/iguana777.h +++ b/iguana/iguana777.h @@ -18,6 +18,17 @@ copy that into basilisk as coin, changing RELAY -> 0 */ +/* + To add a new dPoW'ed assetchain with DEX* API support: + 1. add to komodo/src: assetchains, assetchains.old, dpowassets, fiat-cli + 2. add to end of NOTARY_CURRENCIES[] array in fundnotaries (iguana_notary.c) + 3. create fiat/ + 4. add to m_notary coins/ get gen_acname from where komodod was launched, change RELAY:-1 and port to 7776 and make _7776 variant + 5. make coins/basilisk/ + 6. launch from a single node with -gen, launch a second node using -addnode= but without -gen + 7. from a single node, fundnotaries to get notaries able to dPoW + */ + #ifndef iguana777_net_h #define iguana777_net_h diff --git a/iguana/iguana_init.c b/iguana/iguana_init.c index 8abd4e50d..bb3c92135 100755 --- a/iguana/iguana_init.c +++ b/iguana/iguana_init.c @@ -15,17 +15,6 @@ #include "iguana777.h" -/* - To add a new dPoW'ed assetchain with DEX* API support: - 1. add to komodo/src: assetchains, dpowassets, fiat-cli - 2. add to end of NOTARY_CURRENCIES[] array in fundnotaries (iguana_notary.c) - 3. create fiat/ - 4. add to m_notary coins/ get gen_acname from where komodod was launched, change RELAY:-1 and port to 7776 and make _7776 variant - 5. make coins/basilisk/ - 6. launch from a single node with -gen, launch a second node using -addnode= but without -gen - 7. from a single node, fundnotaries to get notaries able to dPoW - */ - void iguana_initQ(queue_t *Q,char *name) { struct stritem *tst,*item; diff --git a/iguana/iguana_notary.c b/iguana/iguana_notary.c index c8808191b..eb36de1e1 100755 --- a/iguana/iguana_notary.c +++ b/iguana/iguana_notary.c @@ -558,7 +558,7 @@ STRING_ARG(iguana,addnotary,ipaddr) char NOTARY_CURRENCIES[][16] = { "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", "CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", - "REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "SHARK", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "MNZ", "CHIPS" }; // "LTC", + "REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "SHARK", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "MNZ", "CHIPS", "MSHARK" }; // "LTC", ZERO_ARGS(dpow,notarychains) { diff --git a/iguana/m_notary b/iguana/m_notary index 9a4fbb305..c88989065 100755 --- a/iguana/m_notary +++ b/iguana/m_notary @@ -32,6 +32,7 @@ coins/bet_7776 coins/bots_7776 coins/hodl_7776 coins/shark_7776 +coins/mshark_7776 coins/jumblr_7776 coins/crypto_7776 coins/pangea_7776 diff --git a/iguana/main.c b/iguana/main.c index 85510c3fb..b89521a04 100755 --- a/iguana/main.c +++ b/iguana/main.c @@ -793,7 +793,7 @@ void iguana_launchdaemons(struct supernet_info *myinfo) if ( COMMANDLINE_ARGFILE == 0 ) iguana_launch(0,"rpcloop",iguana_rpcloop,myinfo,IGUANA_PERMTHREAD); // limit to oneprocess printf("launch mainloop\n"); - OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)DEX_explorerloop,(void *)myinfo); + // disable basilisk: OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)DEX_explorerloop,(void *)myinfo); OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)jumblr_loop,(void *)myinfo); OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)dpow_psockloop,(void *)myinfo); mainloop(myinfo);