diff --git a/.gitignore b/.gitignore index c68d66ed4..ca8b97239 100755 --- a/.gitignore +++ b/.gitignore @@ -465,3 +465,9 @@ iguana/DB/SWAPS/3085356347-2346291696 iguana/DB/SWAPS/1819165332-1507632737 iguana/DB/SWAPS/283982730-556239841 + +iguana/marketmaker.dSYM/Contents/Info.plist + +iguana/client + +iguana/marketmaker.dSYM/Contents/Resources/DWARF/marketmaker diff --git a/basilisk/basilisk_tradebot.c b/basilisk/basilisk_tradebot.c index e98a64509..2635cde97 100755 --- a/basilisk/basilisk_tradebot.c +++ b/basilisk/basilisk_tradebot.c @@ -316,7 +316,6 @@ double basilisk_request_listprocess(struct supernet_info *myinfo,struct basilisk } } else noquoteflag++; } - // MVP -> USD myrequest.0 pendingid.0 noquoteflag.1 havequoteflag.0 maxi.-1 0.00000000 struct iguana_info *coin; char coinaddr[64]; double retvals[4],refprice=0.,profitmargin,aveprice,destvolume; destvolume = dstr(maxamount); //printf("destvolume <- %.8f\n",dstr(destvolume)); diff --git a/basilisk/jumblr.c b/basilisk/jumblr.c index e7144fb57..9618a9421 100755 --- a/basilisk/jumblr.c +++ b/basilisk/jumblr.c @@ -642,16 +642,18 @@ void jumblr_utxoupdate(struct supernet_info *myinfo,char *dest,struct iguana_inf void jumblr_iteration(struct supernet_info *myinfo,struct iguana_info *coin,int32_t selector,int32_t modval) { //static uint32_t lasttime; - char BTCaddr[64],KMDaddr[64],*zaddr,*retstr; bits256 privkey; uint64_t amount=0,total=0; double fee; struct jumblr_item *ptr,*tmp; uint8_t r; + char BTCaddr[64],KMDaddr[64],*zaddr,*retstr; int32_t iter,counter,chosen_one,n; bits256 privkey; uint64_t amount=0,total=0; double fee; struct jumblr_item *ptr,*tmp; uint8_t r,s; if ( myinfo->IAMNOTARY != 0 ) return; fee = JUMBLR_INCR * JUMBLR_FEE; OS_randombytes(&r,sizeof(r)); //r = 0; + // randomize size chosen and order of chunks if ( strcmp(coin->symbol,"KMD") == 0 && coin->FULLNODE < 0 ) { + s = (selector + (r>>1)) % 3; //printf("JUMBLR selector.%d modval.%d r.%d\n",selector,modval,r&7); - switch ( selector ) + switch ( s ) { case 0: // public -> z, need to importprivkey jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,JUMBLR_DEPOSITPREFIX); @@ -661,12 +663,14 @@ void jumblr_iteration(struct supernet_info *myinfo,struct iguana_info *coin,int3 { if ( (zaddr= jumblr_zgetnewaddress(myinfo,coin)) != 0 ) { + amount = 0; if ( total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE) ) amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE); - else if ( total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE) ) + if ( (r & 2) != 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE) ) amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE); - else amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE); - if ( (retstr= jumblr_sendt_to_z(myinfo,coin,KMDaddr,zaddr,dstr(amount))) != 0 ) + if ( (r & 4) != 0 ) + amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE); + if ( amount > 0 && (retstr= jumblr_sendt_to_z(myinfo,coin,KMDaddr,zaddr,dstr(amount))) != 0 ) { printf("sendt_to_z.(%s)\n",retstr); free(retstr); @@ -678,24 +682,44 @@ void jumblr_iteration(struct supernet_info *myinfo,struct iguana_info *coin,int3 break; case 1: // z -> z jumblr_opidsupdate(myinfo,coin); - HASH_ITER(hh,myinfo->jumblrs,ptr,tmp) + chosen_one = -1; + for (iter=counter=0; iter<2; iter++) { - if ( jumblr_addresstype(myinfo,coin,ptr->src) == 't' && jumblr_addresstype(myinfo,coin,ptr->dest) == 'z' ) + counter = n = 0; + HASH_ITER(hh,myinfo->jumblrs,ptr,tmp) { - if ( (r & 1) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) + if ( jumblr_addresstype(myinfo,coin,ptr->src) == 't' && jumblr_addresstype(myinfo,coin,ptr->dest) == 'z' ) { - if ( (zaddr= jumblr_zgetnewaddress(myinfo,coin)) != 0 ) + if ( (r & 1) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) { - if ( (retstr= jumblr_sendz_to_z(myinfo,coin,ptr->dest,zaddr,dstr(total))) != 0 ) + if ( iter == 1 && counter == chosen_one ) { - printf("sendz_to_z.(%s)\n",retstr); - free(retstr); + if ( (zaddr= jumblr_zgetnewaddress(myinfo,coin)) != 0 ) + { + if ( (retstr= jumblr_sendz_to_z(myinfo,coin,ptr->dest,zaddr,dstr(total))) != 0 ) + { + printf("n.%d counter.%d chosen_one.%d sendz_to_z.(%s)\n",n,counter,chosen_one,retstr); + free(retstr); + } + ptr->spent = (uint32_t)time(NULL); + free(zaddr); + break; + } } - ptr->spent = (uint32_t)time(NULL); - free(zaddr); - break; + counter++; } } + n++; + } + if ( counter == 0 ) + break; + if ( iter == 0 ) + { + OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); + if ( chosen_one < 0 ) + chosen_one = -chosen_one; + chosen_one %= counter; + printf("jumblr z->z chosen_one.%d of %d, from %d\n",chosen_one,counter,n); } } break; @@ -703,21 +727,41 @@ void jumblr_iteration(struct supernet_info *myinfo,struct iguana_info *coin,int3 if ( myinfo->runsilent == 0 ) { jumblr_opidsupdate(myinfo,coin); - HASH_ITER(hh,myinfo->jumblrs,ptr,tmp) + chosen_one = -1; + for (iter=0; iter<2; iter++) { - if ( jumblr_addresstype(myinfo,coin,ptr->src) == 'z' && jumblr_addresstype(myinfo,coin,ptr->dest) == 'z' ) + counter = n = 0; + HASH_ITER(hh,myinfo->jumblrs,ptr,tmp) { - if ( (r & 1) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) + if ( jumblr_addresstype(myinfo,coin,ptr->src) == 'z' && jumblr_addresstype(myinfo,coin,ptr->dest) == 'z' ) { - privkey = jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,""); - if ( (retstr= jumblr_sendz_to_t(myinfo,coin,ptr->dest,KMDaddr,dstr(total))) != 0 ) + if ( (r & 1) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) { - printf("sendz_to_t.(%s)\n",retstr); - free(retstr); + if ( iter == 1 && n == chosen_one ) + { + privkey = jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,""); + if ( (retstr= jumblr_sendz_to_t(myinfo,coin,ptr->dest,KMDaddr,dstr(total))) != 0 ) + { + printf("sendz_to_t.(%s)\n",retstr); + free(retstr); + } + ptr->spent = (uint32_t)time(NULL); + break; + } + counter++; } - ptr->spent = (uint32_t)time(NULL); - break; } + n++; + } + if ( counter == 0 ) + break; + if ( iter == 0 ) + { + OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); + if ( chosen_one < 0 ) + chosen_one = -chosen_one; + chosen_one %= counter; + printf("jumblr z->t chosen_one.%d of %d, from %d\n",chosen_one,counter,n); } } } diff --git a/crypto777/OS_portable.h b/crypto777/OS_portable.h index 23a051b01..5229414a6 100755 --- a/crypto777/OS_portable.h +++ b/crypto777/OS_portable.h @@ -129,7 +129,8 @@ int32_t hseek(HUFF *hp,int32_t offset,int32_t mode); #define portable_mutex_unlock pthread_mutex_unlock #define OS_thread_create pthread_create -#define issue_curl(cmdstr) bitcoind_RPC(0,"curl",cmdstr,0,0,0) +#define issue_curl(cmdstr) bitcoind_RPC(0,"curl",cmdstr,0,0,0,0) +#define issue_curlt(cmdstr,timeout) bitcoind_RPC(0,"curl",cmdstr,0,0,0,timeout) struct allocitem { uint32_t allocsize,type; } PACKED; struct queueitem { struct queueitem *next,*prev; uint32_t allocsize,type; } PACKED; diff --git a/crypto777/bitcoind_RPC.c b/crypto777/bitcoind_RPC.c index 975208ddd..8d864e38d 100755 --- a/crypto777/bitcoind_RPC.c +++ b/crypto777/bitcoind_RPC.c @@ -115,7 +115,7 @@ char *Jay_NXTrequest(char *command,char *params) return(retstr); } -char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params) +char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params,int32_t timeout) { static int didinit,count,count2; static double elapsedsum,elapsedsum2; extern int32_t USE_JAY; struct curl_slist *headers = NULL; struct return_string s; CURLcode res; CURL *curl_handle; @@ -153,7 +153,8 @@ try_again: curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback - //curl_easy_setopt(curl_handle,CURLOPT_TIMEOUT, 60L); // causes problems with iguana timeouts + if ( timeout > 0 ) + curl_easy_setopt(curl_handle,CURLOPT_TIMEOUT, timeout); // causes problems with iguana timeouts if ( strncmp(url,"https",5) == 0 ) { curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0); @@ -201,7 +202,7 @@ try_again: if ( res != CURLE_OK ) { numretries++; - if ( specialcase != 0 ) + if ( specialcase != 0 || timeout != 0 ) { printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res); free(s.ptr); diff --git a/crypto777/nanosrc/aio/worker_posix.c b/crypto777/nanosrc/aio/worker_posix.c index a2662d078..070a87a86 100755 --- a/crypto777/nanosrc/aio/worker_posix.c +++ b/crypto777/nanosrc/aio/worker_posix.c @@ -103,7 +103,7 @@ int nn_worker_init(struct nn_worker *self) { int32_t rc; PNACL_message("nn_worker_init %p\n",self); - sleep(1); + //sleep(1); rc = nn_efd_init(&self->efd); PNACL_message("efd init: rc.%d\n",rc); if ( rc < 0 ) diff --git a/crypto777/nanosrc/core/global.c b/crypto777/nanosrc/core/global.c index 51ab91709..e8f750f88 100755 --- a/crypto777/nanosrc/core/global.c +++ b/crypto777/nanosrc/core/global.c @@ -240,7 +240,7 @@ PNACL_message("list init\n"); // Initialise other parts of the global state. nn_list_init(&SELF.transports); nn_list_init(&SELF.socktypes); - sleep(1); + //sleep(1); PNACL_message("transports init\n"); // Plug in individual transports. //nn_global_add_transport(nn_ipc); @@ -248,36 +248,36 @@ PNACL_message("transports init\n"); //nn_global_add_transport(nn_inproc); //nn_global_add_transport(nn_ws); //nn_global_add_transport(nn_tcpmux); - sleep(1); + //sleep(1); PNACL_message("socktypes init\n"); // Plug in individual socktypes nn_global_add_socktype(nn_pair_socktype); - sleep(1); + //sleep(1); PNACL_message("nn_xpair_socktype init\n"); nn_global_add_socktype(nn_xpair_socktype); PNACL_message("did nn_xpair_socktype init\n"); - //nn_global_add_socktype(nn_rep_socktype); - //nn_global_add_socktype(nn_req_socktype); - //nn_global_add_socktype(nn_xrep_socktype); - //nn_global_add_socktype(nn_xreq_socktype); - //nn_global_add_socktype(nn_respondent_socktype); - //nn_global_add_socktype(nn_surveyor_socktype); - //nn_global_add_socktype(nn_xrespondent_socktype); - //nn_global_add_socktype(nn_xsurveyor_socktype); - //nn_global_add_socktype(nn_pub_socktype); - //nn_global_add_socktype(nn_sub_socktype); - //nn_global_add_socktype(nn_xpub_socktype); - //nn_global_add_socktype(nn_xsub_socktype); - //nn_global_add_socktype(nn_push_socktype); - //nn_global_add_socktype(nn_xpush_socktype); - //nn_global_add_socktype(nn_pull_socktype); - //nn_global_add_socktype(nn_xpull_socktype); - //nn_global_add_socktype(nn_bus_socktype); - //nn_global_add_socktype(nn_xbus_socktype); - sleep(1); + nn_global_add_socktype(nn_rep_socktype); + nn_global_add_socktype(nn_req_socktype); + nn_global_add_socktype(nn_xrep_socktype); + nn_global_add_socktype(nn_xreq_socktype); + nn_global_add_socktype(nn_respondent_socktype); + nn_global_add_socktype(nn_surveyor_socktype); + nn_global_add_socktype(nn_xrespondent_socktype); + nn_global_add_socktype(nn_xsurveyor_socktype); + nn_global_add_socktype(nn_pub_socktype); + nn_global_add_socktype(nn_sub_socktype); + nn_global_add_socktype(nn_xpub_socktype); + nn_global_add_socktype(nn_xsub_socktype); + nn_global_add_socktype(nn_push_socktype); + nn_global_add_socktype(nn_xpush_socktype); + nn_global_add_socktype(nn_pull_socktype); + nn_global_add_socktype(nn_xpull_socktype); + nn_global_add_socktype(nn_bus_socktype); + nn_global_add_socktype(nn_xbus_socktype); + //sleep(1); PNACL_message("do pool init\n"); nn_pool_init(&SELF.pool); // Start the worker threads - sleep(1); + //sleep(1); PNACL_message("do FSM init\n"); nn_fsm_init_root(&SELF.fsm,nn_global_handler,nn_global_shutdown,&SELF.ctx); // Start FSM SELF.state = NN_GLOBAL_STATE_IDLE; diff --git a/crypto777/nanosrc/utils/efd_pipe.c b/crypto777/nanosrc/utils/efd_pipe.c index ddce06119..4df5fd3b3 100755 --- a/crypto777/nanosrc/utils/efd_pipe.c +++ b/crypto777/nanosrc/utils/efd_pipe.c @@ -34,14 +34,14 @@ int nn_efd_init(struct nn_efd *self) { int rc,flags,p[2]; PNACL_message("inside efd_init: pipe\n"); - sleep(1); + //sleep(1); #if defined NN_HAVE_PIPE2 rc = pipe2(p, O_NONBLOCK | O_CLOEXEC); #else rc = pipe(p); #endif PNACL_message("rc efd_init: %d\n",rc); - sleep(1); + //sleep(1); if (rc != 0 && (errno == EMFILE || errno == ENFILE)) return -EMFILE; errno_assert (rc == 0); diff --git a/iguana/coins/basilisk/coqui b/iguana/coins/basilisk/coqui new file mode 100755 index 000000000..cc86f422a --- /dev/null +++ b/iguana/coins/basilisk/coqui @@ -0,0 +1,2 @@ +curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"COQUI.conf\",\"path\":\"${HOME#"/"}/.komodo/COQUI\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":0,\"VALIDATE\":1,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"COQUI\",\"name\":\"COQUI\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"dd5ce076\",\"p2p\":12455,\"rpc\":12456,\"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/coqui_7776 b/iguana/coins/coqui_7776 new file mode 100755 index 000000000..7233677cf --- /dev/null +++ b/iguana/coins/coqui_7776 @@ -0,0 +1 @@ +curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"COQUI.conf\",\"path\":\"${HOME#"/"}/.komodo/COQUI\",\"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\":\"COQUI\",\"name\":\"COQUI\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"fa05f107\",\"p2p\":12455,\"rpc\":12456,\"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/genltc b/iguana/coins/genltc index 9994529e0..ea034ed80 100755 --- a/iguana/coins/genltc +++ b/iguana/coins/genltc @@ -1,4 +1,4 @@ #!/bin/bash -curl --url "http://127.0.0.1:7776" --data "{\"RELAY\":1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":10,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":68,\"endpend\":68,\"services\":129,\"maxpeers\":256,\"newcoin\":\"LTC\",\"name\":\"Litecoin\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"fbc0b6db\",\"p2p\":9333,\"rpc\":9332,\"pubval\":48,\"p2shval\":5,\"wifval\":176,\"txfee_satoshis\":\"100000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2\",\"genesis\":{\"version\":1,\"timestamp\":1317972665,\"nBits\":\"1e0ffff0\",\"nonce\":2084524493,\"merkle_root\":\"97ddfbbae6be97fd6cdf3e7ca13232a3afff2353e29badfab7f73011edd4ced9\"},\"alertpubkey\":\"040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9\",\"protover\":70002}" +curl --url "http://127.0.0.1:7778" --data "{\"RELAY\":1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":10,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":68,\"endpend\":68,\"services\":129,\"maxpeers\":256,\"newcoin\":\"LTC\",\"name\":\"Litecoin\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"fbc0b6db\",\"p2p\":9333,\"rpc\":9332,\"pubval\":48,\"p2shval\":5,\"wifval\":176,\"txfee_satoshis\":\"100000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2\",\"genesis\":{\"version\":1,\"timestamp\":1317972665,\"nBits\":\"1e0ffff0\",\"nonce\":2084524493,\"merkle_root\":\"97ddfbbae6be97fd6cdf3e7ca13232a3afff2353e29badfab7f73011edd4ced9\"},\"alertpubkey\":\"040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9\",\"protover\":70002}" diff --git a/iguana/coins/revs b/iguana/coins/revs index f2cf9ef72..23f4948b2 100755 --- a/iguana/coins/revs +++ b/iguana/coins/revs @@ -1,3 +1,3 @@ -./komodod -ac_name=REVS -ac_supply=1300000 -addnode=78.47.196.146 & +~/komodo/src/komodod -ac_name=REVS -ac_supply=1300000 -addnode=78.47.196.146 & curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"REVS.conf\",\"path\":\"${HOME#"/"}/.komodo/REVS\",\"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\":\"REVS\",\"name\":\"REVS\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"905c3498\",\"p2p\":10195,\"rpc\":10196,\"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_rpc.c b/iguana/dpow/dpow_rpc.c index 3a7c83aea..0e294f4d9 100755 --- a/iguana/dpow/dpow_rpc.c +++ b/iguana/dpow/dpow_rpc.c @@ -13,7 +13,7 @@ * * ******************************************************************************/ -#define issue_curl(cmdstr) bitcoind_RPC(0,"curl",cmdstr,0,0,0) +#define issue_curl(cmdstr) bitcoind_RPC(0,"curl",cmdstr,0,0,0,0) cJSON *dpow_getinfo(struct supernet_info *myinfo,struct iguana_info *coin) { @@ -839,7 +839,7 @@ char *dpow_issuemethod(char *userpass,char *method,char *params,uint16_t port) sprintf(url,(char *)"http://127.0.0.1:%u",port); sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params); //printf("postdata.(%s) USERPASS.(%s)\n",postdata,KMDUSERPASS); - retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,userpass,method,params); + retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,userpass,method,params,0); } return(retstr2); } diff --git a/iguana/exchanges/DEXstats.h b/iguana/exchanges/DEXstats.h index 6982cb64d..dec43b0cc 100644 --- a/iguana/exchanges/DEXstats.h +++ b/iguana/exchanges/DEXstats.h @@ -927,7 +927,7 @@ char *stats_prices(char *symbol,char *dest,struct DEXstats_disp *prices,int32_t } #ifndef FROM_MARKETMAKER -char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port) +char *stats_JSON(char *myipaddr,int32_t mypubsock,double profitmargin,cJSON *argjson,char *remoteaddr,uint16_t port) { char *method,*agent,*retstr,*source,*dest; struct tai T; uint32_t endtimestamp; struct DEXstats_disp prices[365]; int32_t leftdatenum,seconds,numdates; if ( (method= jstr(argjson,"method")) == 0 ) diff --git a/iguana/exchanges/LP_bitcoin.c b/iguana/exchanges/LP_bitcoin.c index c7ee8b218..168b728ec 100644 --- a/iguana/exchanges/LP_bitcoin.c +++ b/iguana/exchanges/LP_bitcoin.c @@ -2025,22 +2025,23 @@ int32_t bitcoin_p2shscript(uint8_t *script,int32_t n,const uint8_t *p2shscript,c char *bitcoind_passthru(char *coinstr,char *serverport,char *userpass,char *method,char *params) { - return(bitcoind_RPC(0,coinstr,serverport,userpass,method,params)); + return(bitcoind_RPC(0,coinstr,serverport,userpass,method,params,0)); } -int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr) +int32_t bitcoin_addr2rmd160(uint8_t taddr,uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr) { - bits256 hash; uint8_t *buf,_buf[25]; int32_t len; + bits256 hash; uint8_t *buf,_buf[26]; int32_t len,offset; + offset = 1 + (taddr != 0); memset(rmd160,0,20); *addrtypep = 0; buf = _buf; if ( (len= bitcoin_base58decode(buf,coinaddr)) >= 4 ) { // validate with trailing hash, then remove hash - hash = bits256_doublesha256(0,buf,21); - *addrtypep = *buf; - memcpy(rmd160,buf+1,20); - if ( (buf[21]&0xff) == hash.bytes[31] && (buf[22]&0xff) == hash.bytes[30] &&(buf[23]&0xff) == hash.bytes[29] && (buf[24]&0xff) == hash.bytes[28] ) + hash = bits256_doublesha256(0,buf,20+offset); + *addrtypep = (taddr == 0) ? *buf : buf[1]; + memcpy(rmd160,buf+offset,20); + if ( (buf[20+offset]&0xff) == hash.bytes[31] && (buf[21+offset]&0xff) == hash.bytes[30] &&(buf[22+offset]&0xff) == hash.bytes[29] && (buf[23+offset]&0xff) == hash.bytes[28] ) { //printf("coinaddr.(%s) valid checksum addrtype.%02x\n",coinaddr,*addrtypep); return(20); @@ -2054,61 +2055,94 @@ int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr } for (i=0; i "); - hash = bits256_doublesha256(0,data,(int32_t)data_len+1); + hash = bits256_doublesha256(0,data,(int32_t)data_len+offset); //for (i=0; i<32; i++) // printf("%02x",hash.bytes[i]); //printf(" checkhash\n"); for (i=0; i<4; i++) - data[data_len+i+1] = hash.bytes[31-i]; - return(data_len + 5); + data[data_len+i+offset] = hash.bytes[31-i]; + return(data_len + 4 + offset); } int32_t bitcoin_wif2priv(uint8_t *addrtypep,bits256 *privkeyp,char *wifstr) @@ -2146,7 +2180,7 @@ int32_t bitcoin_priv2wif(char *wifstr,bits256 privkey,uint8_t addrtype) uint8_t data[128]; int32_t len = 32; memcpy(data+1,privkey.bytes,sizeof(privkey)); data[1 + len++] = 1; - len = base58encode_checkbuf(addrtype,data,len); + len = base58encode_checkbuf(0,addrtype,data,len); if ( bitcoin_base58encode(wifstr,data,len) == 0 ) return(-1); if ( 1 ) @@ -2165,7 +2199,7 @@ int32_t bitcoin_priv2wiflong(char *wifstr,bits256 privkey,uint8_t addrtype) { uint8_t data[128]; int32_t len = 32; memcpy(data+1,privkey.bytes,sizeof(privkey)); - len = base58encode_checkbuf(addrtype,data,len); + len = base58encode_checkbuf(0,addrtype,data,len); if ( bitcoin_base58encode(wifstr,data,len) == 0 ) return(-1); if ( 1 ) @@ -2180,10 +2214,10 @@ int32_t bitcoin_priv2wiflong(char *wifstr,bits256 privkey,uint8_t addrtype) return((int32_t)strlen(wifstr)); } -bits256 LP_privkey(char *coinaddr) +bits256 LP_privkey(char *coinaddr,uint8_t taddr) { bits256 privkey; uint8_t addrtype,rmd160[20]; - bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr); + bitcoin_addr2rmd160(taddr,&addrtype,rmd160,coinaddr); privkey = LP_privkeyfind(rmd160); return(privkey); } @@ -2216,7 +2250,7 @@ uint8_t iguana_addrtype(uint8_t pubtype,uint8_t p2shtype,uint8_t script_type) } } -int32_t iguana_scriptgen(uint8_t pubtype,uint8_t p2shtype,int32_t *Mp,int32_t *nump,char *coinaddr,uint8_t *script,char *asmstr,uint8_t rmd160[20],uint8_t type,const struct vin_info *vp,int32_t txi) +int32_t iguana_scriptgen(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,int32_t *Mp,int32_t *nump,char *coinaddr,uint8_t *script,char *asmstr,uint8_t rmd160[20],uint8_t type,const struct vin_info *vp,int32_t txi) { uint8_t addrtype; char rmd160str[41],pubkeystr[256]; int32_t plen,i,m,n,flag = 0,scriptlen = 0; m = n = 0; @@ -2226,7 +2260,7 @@ int32_t iguana_scriptgen(uint8_t pubtype,uint8_t p2shtype,int32_t *Mp,int32_t *n if ( type == IGUANA_SCRIPT_76A988AC || type == IGUANA_SCRIPT_AC || type == IGUANA_SCRIPT_76AC || type == IGUANA_SCRIPT_P2SH ) { init_hexbytes_noT(rmd160str,rmd160,20); - bitcoin_address(coinaddr,addrtype,rmd160,20); + bitcoin_address(coinaddr,taddr,addrtype,rmd160,20); } switch ( type ) { @@ -2265,7 +2299,7 @@ int32_t iguana_scriptgen(uint8_t pubtype,uint8_t p2shtype,int32_t *Mp,int32_t *n case IGUANA_SCRIPT_OPRETURN: if ( asmstr != 0 ) strcpy(asmstr,"OP_RETURN "); - bitcoin_address(coinaddr,addrtype,(uint8_t *)&vp->spendscript[0],vp->spendlen); + bitcoin_address(coinaddr,taddr,addrtype,(uint8_t *)&vp->spendscript[0],vp->spendlen); flag++; break; case IGUANA_SCRIPT_3of3: m = 3, n = 3; break; @@ -2278,13 +2312,13 @@ int32_t iguana_scriptgen(uint8_t pubtype,uint8_t p2shtype,int32_t *Mp,int32_t *n case IGUANA_SCRIPT_DATA: if ( asmstr != 0 ) strcpy(asmstr,"DATA ONLY"); - bitcoin_address(coinaddr,addrtype,(uint8_t *)&vp->spendscript[0],vp->spendlen); + bitcoin_address(coinaddr,taddr,addrtype,(uint8_t *)&vp->spendscript[0],vp->spendlen); flag++; break; case IGUANA_SCRIPT_STRANGE: if ( asmstr != 0 ) strcpy(asmstr,"STRANGE SCRIPT "); - bitcoin_address(coinaddr,addrtype,(uint8_t *)&vp->spendscript[0],vp->spendlen); + bitcoin_address(coinaddr,taddr,addrtype,(uint8_t *)&vp->spendscript[0],vp->spendlen); flag++; break; default: break;//printf("unexpected script type.%d\n",type); break; @@ -2292,7 +2326,7 @@ int32_t iguana_scriptgen(uint8_t pubtype,uint8_t p2shtype,int32_t *Mp,int32_t *n if ( n > 0 ) { scriptlen = bitcoin_MofNspendscript(rmd160,script,0,vp); - bitcoin_address(coinaddr,p2shtype,script,scriptlen); + bitcoin_address(coinaddr,taddr,p2shtype,script,scriptlen); if ( asmstr != 0 ) { sprintf(asmstr,"%d ",m); @@ -2319,7 +2353,7 @@ int32_t iguana_scriptgen(uint8_t pubtype,uint8_t p2shtype,int32_t *Mp,int32_t *n return(scriptlen); } -int32_t bitcoin_scriptget(uint8_t pubtype,uint8_t p2shtype,int32_t *hashtypep,uint32_t *sigsizep,uint32_t *pubkeysizep,uint8_t **userdatap,uint32_t *userdatalenp,struct vin_info *vp,uint8_t *scriptsig,int32_t len,int32_t spendtype) +int32_t bitcoin_scriptget(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,int32_t *hashtypep,uint32_t *sigsizep,uint32_t *pubkeysizep,uint8_t **userdatap,uint32_t *userdatalenp,struct vin_info *vp,uint8_t *scriptsig,int32_t len,int32_t spendtype) { int32_t j,n,siglen,plen; uint8_t *p2shscript; j = n = 0; @@ -2393,12 +2427,12 @@ int32_t bitcoin_scriptget(uint8_t pubtype,uint8_t p2shtype,int32_t *hashtypep,ui decode_hex(vp->rmd160,20,"010966776006953d5567439e5e39f86a0d273bee");//3564a74f9ddb4372301c49154605573d7d1a88fe"); vp->type = IGUANA_SCRIPT_76A988AC; }*/ - vp->spendlen = iguana_scriptgen(pubtype,p2shtype,&vp->M,&vp->N,vp->coinaddr,vp->spendscript,0,vp->rmd160,vp->type,(const struct vin_info *)vp,vp->vin.prev_vout); + 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); } -int32_t _iguana_calcrmd160(uint8_t pubtype,uint8_t p2shtype,struct vin_info *vp) +int32_t _iguana_calcrmd160(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,struct vin_info *vp) { static uint8_t zero_rmd160[20]; char hexstr[8192]; uint8_t *script,type; int32_t i,n,m,plen; @@ -2473,7 +2507,7 @@ int32_t _iguana_calcrmd160(uint8_t pubtype,uint8_t p2shtype,struct vin_info *vp) } memcpy(vp->signers[i].pubkey,script,plen); calc_rmd160_sha256(vp->signers[i].rmd160,vp->signers[i].pubkey,plen); - bitcoin_address(vp->signers[i].coinaddr,pubtype,vp->signers[i].pubkey,plen); + bitcoin_address(vp->signers[i].coinaddr,taddr,pubtype,vp->signers[i].pubkey,plen); } if ( (int32_t)((long)script - (long)vp->spendscript) == vp->spendlen-2 ) { @@ -2526,7 +2560,7 @@ int32_t _iguana_calcrmd160(uint8_t pubtype,uint8_t p2shtype,struct vin_info *vp) return(type); } -int32_t iguana_calcrmd160(uint8_t pubtype,uint8_t p2shtype,char *asmstr,struct vin_info *vp,uint8_t *pk_script,int32_t pk_scriptlen,bits256 debugtxid,int32_t vout,uint32_t sequence) +int32_t iguana_calcrmd160(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,char *asmstr,struct vin_info *vp,uint8_t *pk_script,int32_t pk_scriptlen,bits256 debugtxid,int32_t vout,uint32_t sequence) { int32_t scriptlen; uint8_t script[IGUANA_MAXSCRIPTSIZE]; memset(vp,0,sizeof(*vp)); @@ -2534,9 +2568,9 @@ int32_t iguana_calcrmd160(uint8_t pubtype,uint8_t p2shtype,char *asmstr,struct v vp->spendlen = pk_scriptlen; vp->vin.sequence = sequence; memcpy(vp->spendscript,pk_script,pk_scriptlen); - if ( (vp->type= _iguana_calcrmd160(pubtype,p2shtype,vp)) >= 0 ) + if ( (vp->type= _iguana_calcrmd160(taddr,pubtype,p2shtype,vp)) >= 0 ) { - scriptlen = iguana_scriptgen(pubtype,p2shtype,&vp->M,&vp->N,vp->coinaddr,script,asmstr,vp->rmd160,vp->type,(const struct vin_info *)vp,vout); + scriptlen = iguana_scriptgen(taddr,pubtype,p2shtype,&vp->M,&vp->N,vp->coinaddr,script,asmstr,vp->rmd160,vp->type,(const struct vin_info *)vp,vout); if ( vp->M == 0 && vp->N == 0 ) { vp->M = vp->N = 1; @@ -2578,11 +2612,11 @@ cJSON *bitcoin_txscript(char *asmstr,char **vardata,int32_t numvars) return(scriptjson); } -cJSON *iguana_scriptpubkeys(uint8_t pubtype,uint8_t p2shtype,uint8_t *script,int32_t scriptlen,bits256 txid,int16_t vout,uint32_t sequenceid) +cJSON *iguana_scriptpubkeys(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t *script,int32_t scriptlen,bits256 txid,int16_t vout,uint32_t sequenceid) { int32_t type,i,n,plen; struct vin_info V; cJSON *pubkeys; char pubkeystr[256]; pubkeys = cJSON_CreateArray(); - if ( (type= iguana_calcrmd160(pubtype,p2shtype,0,&V,script,scriptlen,txid,vout,sequenceid)) >= 0 ) + if ( (type= iguana_calcrmd160(taddr,pubtype,p2shtype,0,&V,script,scriptlen,txid,vout,sequenceid)) >= 0 ) { if ( (n= V.N) == 0 ) n = 1; @@ -2634,7 +2668,7 @@ cJSON *iguana_pubkeysjson(uint8_t *pubkeyptrs[],int32_t numpubkeys) return(pubkeysjson); } -cJSON *bitcoin_txinput(uint8_t pubtype,uint8_t p2shtype,cJSON *txobj,bits256 txid,int32_t vout,uint32_t sequenceid,uint8_t *spendscript,int32_t spendlen,uint8_t *redeemscript,int32_t p2shlen,uint8_t *pubkeys[],int32_t numpubkeys,uint8_t *sig,int32_t siglen) +cJSON *bitcoin_txinput(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,cJSON *txobj,bits256 txid,int32_t vout,uint32_t sequenceid,uint8_t *spendscript,int32_t spendlen,uint8_t *redeemscript,int32_t p2shlen,uint8_t *pubkeys[],int32_t numpubkeys,uint8_t *sig,int32_t siglen) { cJSON *item,*vins; char p2shscriptstr[IGUANA_MAXSCRIPTSIZE*2+1]; uint8_t *script,len=0; vins = jduplicate(jobj(txobj,"vin")); @@ -2654,7 +2688,7 @@ cJSON *bitcoin_txinput(uint8_t pubtype,uint8_t p2shtype,cJSON *txobj,bits256 txi script = redeemscript, len = p2shlen; } else script = 0; if ( script != 0 && numpubkeys == 0 ) - jadd(item,"pubkeys",iguana_scriptpubkeys(pubtype,p2shtype,script,len,txid,vout,sequenceid)); + jadd(item,"pubkeys",iguana_scriptpubkeys(taddr,pubtype,p2shtype,script,len,txid,vout,sequenceid)); else if ( pubkeys != 0 && numpubkeys > 0 ) jadd(item,"pubkeys",iguana_pubkeysjson(pubkeys,numpubkeys)); jaddbits256(item,"txid",txid); @@ -2698,12 +2732,12 @@ cJSON *bitcoin_txoutput(cJSON *txobj,uint8_t *paymentscript,int32_t len,uint64_t return(txobj); } -int32_t bitcoin_txaddspend(uint8_t pubtype,uint8_t p2shtype,cJSON *txobj,char *destaddress,uint64_t satoshis) +int32_t bitcoin_txaddspend(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,cJSON *txobj,char *destaddress,uint64_t satoshis) { uint8_t outputscript[128],addrtype,rmd160[20]; int32_t scriptlen; - if ( bitcoin_validaddress(pubtype,p2shtype,destaddress) == 0 && satoshis != 0 ) + if ( bitcoin_validaddress(taddr,pubtype,p2shtype,destaddress) == 0 && satoshis != 0 ) { - bitcoin_addr2rmd160(&addrtype,rmd160,destaddress); + bitcoin_addr2rmd160(taddr,&addrtype,rmd160,destaddress); scriptlen = bitcoin_standardspend(outputscript,0,rmd160); bitcoin_txoutput(txobj,outputscript,scriptlen,satoshis); return(0); @@ -3130,7 +3164,7 @@ int32_t iguana_parsevoutobj(uint8_t *serialized,int32_t maxsize,struct iguana_ms return(len); } -cJSON *iguana_voutjson(uint8_t pubtype,uint8_t p2shtype,struct iguana_msgvout *vout,int32_t txi,bits256 txid) +cJSON *iguana_voutjson(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,struct iguana_msgvout *vout,int32_t txi,bits256 txid) { // 035f1321ed17d387e4433b2fa229c53616057964af065f98bfcae2233c5108055e OP_CHECKSIG char scriptstr[IGUANA_MAXSCRIPTSIZE+1],asmstr[2*IGUANA_MAXSCRIPTSIZE+1]; int32_t i,m,n,scriptlen,asmtype; struct vin_info *vp; @@ -3143,10 +3177,10 @@ cJSON *iguana_voutjson(uint8_t pubtype,uint8_t p2shtype,struct iguana_msgvout *v if ( vout->pk_script != 0 && vout->pk_scriptlen*2+1 < sizeof(scriptstr) ) { memset(vp,0,sizeof(*vp)); - if ( (asmtype= iguana_calcrmd160(pubtype,p2shtype,asmstr,vp,vout->pk_script,vout->pk_scriptlen,txid,txi,0xffffffff)) >= 0 ) + if ( (asmtype= iguana_calcrmd160(taddr,pubtype,p2shtype,asmstr,vp,vout->pk_script,vout->pk_scriptlen,txid,txi,0xffffffff)) >= 0 ) { skey = cJSON_CreateObject(); - scriptlen = iguana_scriptgen(pubtype,p2shtype,&m,&n,vp->coinaddr,space,asmstr,vp->rmd160,asmtype,vp,txi); + scriptlen = iguana_scriptgen(taddr,pubtype,p2shtype,&m,&n,vp->coinaddr,space,asmstr,vp->rmd160,asmtype,vp,txi); if ( asmstr[0] != 0 ) jaddstr(skey,"asm",asmstr); addrs = cJSON_CreateArray(); @@ -3223,9 +3257,9 @@ int32_t iguana_vinarray_check(cJSON *vinarray,bits256 txid,int32_t vout) return(-1); } -int32_t iguana_rwmsgtx(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,int32_t rwflag,cJSON *json,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,bits256 *txidp,char *vpnstr,uint8_t *extraspace,int32_t extralen,cJSON *vins,int32_t suppress_pubkeys); +int32_t iguana_rwmsgtx(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,int32_t rwflag,cJSON *json,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,bits256 *txidp,char *vpnstr,uint8_t *extraspace,int32_t extralen,cJSON *vins,int32_t suppress_pubkeys); -bits256 bitcoin_sigtxid(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,uint8_t *serialized,int32_t maxlen,struct iguana_msgtx *msgtx,int32_t vini,uint8_t *spendscript,int32_t spendlen,int32_t hashtype,char *vpnstr,int32_t suppress_pubkeys) +bits256 bitcoin_sigtxid(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,uint8_t *serialized,int32_t maxlen,struct iguana_msgtx *msgtx,int32_t vini,uint8_t *spendscript,int32_t spendlen,int32_t hashtype,char *vpnstr,int32_t suppress_pubkeys) { int32_t i,len; bits256 sigtxid,txid,revsigtxid; struct iguana_msgtx dest; dest = *msgtx; @@ -3259,7 +3293,7 @@ bits256 bitcoin_sigtxid(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t h dest.vins[i].userdata = 0; dest.vins[i].userdatalen = 0; } - len = iguana_rwmsgtx(pubtype,p2shtype,isPoS,height,1,0,serialized,maxlen,&dest,&txid,vpnstr,0,0,0,suppress_pubkeys); + len = iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,1,0,serialized,maxlen,&dest,&txid,vpnstr,0,0,0,suppress_pubkeys); //for (i=0; iversion),&msg->version); @@ -3366,7 +3400,7 @@ int32_t iguana_rwmsgtx(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t he return(-1); } if ( voutarray != 0 ) - jaddi(voutarray,iguana_voutjson(pubtype,p2shtype,&msg->vouts[i],i,*txidp)); + jaddi(voutarray,iguana_voutjson(taddr,pubtype,p2shtype,&msg->vouts[i],i,*txidp)); } len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->lock_time),&msg->lock_time); //printf("lock_time.%08x len.%d\n",msg->lock_time,len); @@ -3398,7 +3432,7 @@ int32_t iguana_rwmsgtx(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t he if ( vins != 0 && jitem(vins,i) != 0 ) { iguana_vinobjset(&msg->vins[i],jitem(vins,i),spendscript,sizeof(spendscript)); - sigtxid = bitcoin_sigtxid(pubtype,p2shtype,isPoS,height,sigser,maxsize*2,msg,i,msg->vins[i].spendscript,msg->vins[i].spendlen,SIGHASH_ALL,vpnstr,suppress_pubkeys); + sigtxid = bitcoin_sigtxid(taddr,pubtype,p2shtype,isPoS,height,sigser,maxsize*2,msg,i,msg->vins[i].spendscript,msg->vins[i].spendlen,SIGHASH_ALL,vpnstr,suppress_pubkeys); //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)); @@ -3495,13 +3529,13 @@ bits256 iguana_parsetxobj(uint8_t isPoS,int32_t *txstartp,uint8_t *serialized,in return(txid); } -char *iguana_rawtxbytes(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,cJSON *json,struct iguana_msgtx *msgtx,int32_t suppress_pubkeys) +char *iguana_rawtxbytes(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,cJSON *json,struct iguana_msgtx *msgtx,int32_t suppress_pubkeys) { int32_t 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(pubtype,p2shtype,isPoS,height,1,json,serialized,IGUANA_MAXPACKETSIZE,msgtx,&msgtx->txid,vpnstr,0,0,0,suppress_pubkeys)) > 0 ) + if ( (n= iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,1,json,serialized,IGUANA_MAXPACKETSIZE,msgtx,&msgtx->txid,vpnstr,0,0,0,suppress_pubkeys)) > 0 ) { txbytes = malloc(n*2+1); init_hexbytes_noT(txbytes,serialized,n); @@ -3529,7 +3563,7 @@ char *bitcoin_json2hex(uint8_t isPoS,bits256 *txidp,cJSON *txjson,struct vin_inf return(txbytes); } -cJSON *bitcoin_data2json(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys) +cJSON *bitcoin_data2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys) { int32_t n; char vpnstr[64]; struct iguana_msgtx M; cJSON *txobj; if ( serialized == 0 ) @@ -3540,7 +3574,7 @@ cJSON *bitcoin_data2json(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t memset(msgtx,0,sizeof(M)); vpnstr[0] = 0; memset(txidp,0,sizeof(*txidp)); - if ( (n= iguana_rwmsgtx(pubtype,p2shtype,isPoS,height,0,txobj,serialized,len,msgtx,txidp,vpnstr,extraspace,extralen,vins,suppress_pubkeys)) <= 0 ) + if ( (n= iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,0,txobj,serialized,len,msgtx,txidp,vpnstr,extraspace,extralen,vins,suppress_pubkeys)) <= 0 ) { printf("errortxobj.(%s)\n",jprint(txobj,0)); free_json(txobj); @@ -3558,7 +3592,7 @@ cJSON *bitcoin_data2json(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t return(txobj); } -cJSON *bitcoin_hex2json(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) +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 len; uint8_t *serialized; cJSON *txobj; if ( txbytes == 0 ) @@ -3567,7 +3601,7 @@ cJSON *bitcoin_hex2json(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t h if ( (serialized= origserialized) == 0 ) serialized = calloc(1,len+4096); decode_hex(serialized,len,txbytes); - txobj = bitcoin_data2json(pubtype,p2shtype,isPoS,height,txidp,msgtx,extraspace,extralen,serialized,len,vins,suppress_pubkeys); + txobj = bitcoin_data2json(taddr,pubtype,p2shtype,isPoS,height,txidp,msgtx,extraspace,extralen,serialized,len,vins,suppress_pubkeys); if ( serialized != origserialized ) free(serialized); return(txobj); diff --git a/iguana/exchanges/LP_coins.c b/iguana/exchanges/LP_coins.c index f397ee075..73a77a3df 100644 --- a/iguana/exchanges/LP_coins.c +++ b/iguana/exchanges/LP_coins.c @@ -18,7 +18,16 @@ // marketmaker // -char *portstrs[][2] = { { "BTC", "8332" }, { "KMD", "7771" }, { "LTC", "9332" }, { "REVS", "10196" }, { "JUMBLR", "15106" }, }; +char *portstrs[][2] = { { "BTC", "8332" }, { "KMD", "7771" } }; + +uint16_t LP_rpcport(char *symbol) +{ + int32_t i; + for (i=0; isymbol); + if ( coin->inactive != 0 ) + jaddstr(item,"status","inactive"); + else jaddstr(item,"status","active"); + if ( coin->isPoS != 0 ) + jaddstr(item,"type","PoS"); + jaddstr(item,"smartaddress",coin->smartaddr); + jaddstr(item,"rpc",coin->serverport); + jaddnum(item,"pubtype",coin->pubtype); + jaddnum(item,"p2shtype",coin->p2shtype); + jaddnum(item,"wiftype",coin->wiftype); + jaddnum(item,"estimatedrate",coin->estimatedrate); + jaddnum(item,"txfee",coin->txfee); + return(item); } -struct iguana_info *LP_coinfind(char *symbol) +static struct iguana_info *LP_coins; static int32_t LP_numcoins; +cJSON *LP_coinsjson() +{ + int32_t i; cJSON *array = cJSON_CreateArray(); + for (i=0; isymbol,symbol,sizeof(coin->symbol)); + sprintf(coin->serverport,"127.0.0.1:%u",port); + coin->isPoS = isPoS; + coin->taddr = taddr; + coin->longestchain = longestchain; + coin->txfee = txfee; + coin->estimatedrate = estimatedrate; + coin->pubtype = pubtype; + coin->p2shtype = p2shtype; + coin->wiftype = wiftype; + coin->inactive = (uint32_t)time(NULL); + if ( strcmp(symbol,"KMD") == 0 || (assetname != 0 && assetname[0] != 0) ) + name2 = 0; + else name2 = name; + LP_userpass(coin->userpass,symbol,assetname,name,name2); +} + +struct iguana_info *LP_coinadd(struct iguana_info *cdata) +{ + struct iguana_info *coin; + //printf("%s: (%s) (%s)\n",symbol,cdata.serverport,cdata.userpass); + LP_coins = realloc(LP_coins,sizeof(*LP_coins) * (LP_numcoins+1)); + coin = &LP_coins[LP_numcoins]; + *coin = *cdata; + LP_numcoins++; + return(coin); +} + +struct iguana_info *LP_coinsearch(char *symbol) { - static struct iguana_info *LP_coins; static int32_t LP_numcoins; - struct iguana_info *coin,cdata; int32_t i; uint16_t port; + int32_t i; for (i=0; iinactive != 0 ) + return(1); + else if ( rel != 0 && (coin= LP_coinsearch(rel)) != 0 && coin->inactive != 0 ) + return(1); + else return(0); +} + +struct iguana_info *LP_coinfind(char *symbol) +{ + struct iguana_info *coin,cdata; int32_t isPoS,longestchain = 1000000; uint16_t port; uint64_t txfee; double estimatedrate; uint8_t pubtype,p2shtype,wiftype; char *name,*assetname; + if ( (coin= LP_coinsearch(symbol)) != 0 ) + return(coin); + if ( (port= LP_rpcport(symbol)) == 0 ) + return(0); + isPoS = 0; + txfee = 10000; + estimatedrate = 20; + pubtype = 60; + p2shtype = 85; + wiftype = 188; + assetname = ""; if ( strcmp(symbol,"BTC") == 0 ) { - cdata.txfee = 50000; - cdata.estimatedrate = 300; - cdata.p2shtype = 5; - cdata.wiftype = 128; - LP_userpass(cdata.userpass,symbol,"","bitcoin"); - } - else if ( strcmp(symbol,"LTC") == 0 ) - { - cdata.pubtype = 48; - cdata.p2shtype = 5; - cdata.wiftype = 176; - LP_userpass(cdata.userpass,symbol,"","litecoin"); + txfee = 50000; + estimatedrate = 300; + pubtype = 0; + p2shtype = 5; + wiftype = 128; + name = "bitcoin"; } - else - { - cdata.pubtype = 60; - cdata.p2shtype = 85; - cdata.wiftype = 188; - LP_userpass(cdata.userpass,symbol,symbol,strcmp(symbol,"KMD") == 0 ? "komodo" : symbol); - } - //printf("%s: (%s) (%s)\n",symbol,cdata.serverport,cdata.userpass); - LP_coins = realloc(LP_coins,sizeof(*LP_coins) * (LP_numcoins+1)); - coin = &LP_coins[LP_numcoins++]; - *coin = cdata; + else if ( strcmp(symbol,"KMD") == 0 ) + name = "komodo"; + else return(0); + LP_coininit(&cdata,symbol,name,assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,0); + if ( (coin= LP_coinadd(&cdata)) != 0 && strcmp(symbol,"KMD") == 0 ) + coin->inactive = 0; return(coin); } +// "coins":[{"coin":"", "rpcport":pppp}, {"coin":"LTC", "name":"litecoin", "rpcport":9332, "pubtype":48, "p2shtype":5, "wiftype":176, "txfee":100000 }] +// {"coin":"HUSH", "name":"hush", "rpcport":8822, "taddr":28, "pubtype":184, "p2shtype":189, "wiftype":128, "txfee":10000 } +struct iguana_info *LP_coincreate(cJSON *item) +{ + struct iguana_info cdata,*coin=0; int32_t isPoS,longestchain = 1000000; uint16_t port; uint64_t txfee; double estimatedrate; uint8_t pubtype,p2shtype,wiftype; char *name,*symbol,*assetname; + if ( (symbol= jstr(item,"coin")) != 0 && symbol[0] != 0 && strlen(symbol) < 16 && LP_coinfind(symbol) == 0 && (port= juint(item,"rpcport")) != 0 ) + { + isPoS = jint(item,"isPoS"); + if ( (txfee= j64bits(item,"txfee")) == 0 ) + txfee = 10000; + if ( (estimatedrate= jdouble(item,"estimatedrate")) == 0. ) + estimatedrate = 20; + if ( (pubtype= juint(item,"pubtype")) == 0 ) + pubtype = 60; + if ( (p2shtype= juint(item,"p2shtype")) == 0 ) + p2shtype = 85; + if ( (wiftype= juint(item,"wiftype")) == 0 ) + wiftype = 188; + if ( (assetname= jstr(item,"asset")) != 0 ) + name = assetname; + else if ( (name= jstr(item,"name")) == 0 ) + name = symbol; + LP_coininit(&cdata,symbol,name,assetname==0?"":assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,jint(item,"taddr")); + coin = LP_coinadd(&cdata); + } + if ( coin != 0 && item != 0 ) + coin->inactive = (strcmp("KMD",coin->symbol) == 0) ? 0 : !jint(item,"active"); + return(0); +} diff --git a/iguana/exchanges/LP_commands.c b/iguana/exchanges/LP_commands.c index 8b7eac1a6..5d9dfb80a 100644 --- a/iguana/exchanges/LP_commands.c +++ b/iguana/exchanges/LP_commands.c @@ -18,526 +18,74 @@ // marketmaker // -struct basilisk_request *LP_requestinit(struct basilisk_request *rp,bits256 srchash,bits256 desthash,char *src,uint64_t srcsatoshis,char *dest,uint64_t destsatoshis,uint32_t timestamp,uint32_t quotetime,int32_t DEXselector) -{ - struct basilisk_request R; - memset(rp,0,sizeof(*rp)); - rp->srchash = srchash; - rp->srcamount = srcsatoshis; - rp->timestamp = timestamp; - rp->DEXselector = DEXselector; - safecopy(rp->src,src,sizeof(rp->src)); - safecopy(rp->dest,dest,sizeof(rp->dest)); - R = *rp; - rp->requestid = basilisk_requestid(rp); - rp->quotetime = quotetime; - rp->desthash = desthash; - rp->destamount = destsatoshis; - rp->quoteid = basilisk_quoteid(rp); - return(rp); -} - -cJSON *LP_quotejson(struct LP_quoteinfo *qp) -{ - double price; cJSON *retjson = cJSON_CreateObject(); - jaddstr(retjson,"base",qp->srccoin); - jaddstr(retjson,"rel",qp->destcoin); - if ( qp->coinaddr[0] != 0 ) - jaddstr(retjson,"address",qp->coinaddr); - if ( qp->timestamp != 0 ) - jaddnum(retjson,"timestamp",qp->timestamp); - if ( bits256_nonz(qp->txid) != 0 ) - { - jaddbits256(retjson,"txid",qp->txid); - jaddnum(retjson,"vout",qp->vout); - } - if ( bits256_nonz(qp->srchash) != 0 ) - jaddbits256(retjson,"srchash",qp->srchash); - if ( qp->txfee != 0 ) - jadd64bits(retjson,"txfee",qp->txfee); - if ( qp->quotetime != 0 ) - jaddnum(retjson,"quotetime",qp->quotetime); - if ( qp->satoshis != 0 ) - { - jadd64bits(retjson,"satoshis",qp->satoshis); - price = (double)(qp->destsatoshis+qp->desttxfee) / qp->satoshis; - jaddnum(retjson,"price",price); - } - if ( bits256_nonz(qp->desthash) != 0 ) - jaddbits256(retjson,"desthash",qp->desthash); - if ( bits256_nonz(qp->txid2) != 0 ) - { - jaddbits256(retjson,"txid2",qp->txid2); - jaddnum(retjson,"vout2",qp->vout2); - if ( qp->satoshis2 != 0 ) - jadd64bits(retjson,"satoshis2",qp->satoshis2); - } - if ( bits256_nonz(qp->desttxid) != 0 ) - { - if ( qp->destaddr[0] != 0 ) - jaddstr(retjson,"destaddr",qp->destaddr); - jaddbits256(retjson,"desttxid",qp->desttxid); - jaddnum(retjson,"destvout",qp->destvout); - } - if ( bits256_nonz(qp->feetxid) != 0 ) - { - jaddbits256(retjson,"feetxid",qp->feetxid); - jaddnum(retjson,"feevout",qp->feevout); - } - if ( qp->destsatoshis != 0 ) - jadd64bits(retjson,"destsatoshis",qp->destsatoshis); - if ( qp->desttxfee != 0 ) - jadd64bits(retjson,"desttxfee",qp->desttxfee); - if ( qp->change != 0 ) - jaddnum(retjson,"change",dstr(qp->change)); - return(retjson); -} -int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson) +char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port { - safecopy(qp->srccoin,jstr(argjson,"base"),sizeof(qp->srccoin)); - safecopy(qp->coinaddr,jstr(argjson,"address"),sizeof(qp->coinaddr)); - safecopy(qp->destcoin,jstr(argjson,"rel"),sizeof(qp->destcoin)); - safecopy(qp->destaddr,jstr(argjson,"destaddr"),sizeof(qp->destaddr)); - qp->timestamp = juint(argjson,"timestamp"); - qp->quotetime = juint(argjson,"quotetime"); - qp->txid = jbits256(argjson,"txid"); - qp->txid2 = jbits256(argjson,"txid2"); - qp->vout = jint(argjson,"vout"); - qp->vout2 = jint(argjson,"vout2"); - qp->feevout = jint(argjson,"feevout"); - qp->srchash = jbits256(argjson,"srchash"); - qp->desttxid = jbits256(argjson,"desttxid"); - qp->feetxid = jbits256(argjson,"feetxid"); - qp->destvout = jint(argjson,"destvout"); - qp->desthash = jbits256(argjson,"desthash"); - if ( (qp->satoshis= j64bits(argjson,"satoshis")) == 0 ) - qp->satoshis = j64bits(argjson,"value"); - if ( (qp->satoshis2= j64bits(argjson,"satoshis2")) == 0 ) - qp->satoshis2 = j64bits(argjson,"value2"); - qp->destsatoshis = j64bits(argjson,"destsatoshis"); - qp->change = SATOSHIDEN * jdouble(argjson,"change"); - qp->txfee = j64bits(argjson,"txfee"); - qp->desttxfee = j64bits(argjson,"desttxfee"); - return(0); -} - -int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char *destcoin,double price) -{ - memset(qp,0,sizeof(*qp)); - qp->timestamp = (uint32_t)time(NULL); - safecopy(qp->destcoin,destcoin,sizeof(qp->destcoin)); - if ( (qp->txfee= LP_getestimatedrate(utxo->coin)*LP_AVETXSIZE) < 10000 ) - qp->txfee = 10000; - if ( qp->txfee >= utxo->satoshis || qp->txfee >= utxo->satoshis2 ) - return(-1); - qp->txid = utxo->txid; - qp->vout = utxo->vout; - qp->txid2 = utxo->txid2; - qp->vout2 = utxo->vout2; - qp->satoshis2 = utxo->satoshis2 - qp->txfee; - qp->satoshis = utxo->satoshis - qp->txfee; - qp->destsatoshis = qp->satoshis * price; - if ( (qp->desttxfee= LP_getestimatedrate(qp->destcoin) * LP_AVETXSIZE) < 10000 ) - qp->desttxfee = 10000; - if ( qp->desttxfee >= qp->destsatoshis ) - return(-2); - qp->destsatoshis -= qp->desttxfee; - safecopy(qp->srccoin,utxo->coin,sizeof(qp->srccoin)); - safecopy(qp->coinaddr,utxo->coinaddr,sizeof(qp->coinaddr)); - qp->srchash = LP_pubkey(LP_privkey(utxo->coinaddr)); - return(0); -} - -int32_t LP_quoteinfoset(struct LP_quoteinfo *qp,uint32_t timestamp,uint32_t quotetime,uint64_t value,uint64_t txfee,uint64_t destsatoshis,uint64_t desttxfee,bits256 desttxid,int32_t destvout,bits256 desthash,char *destaddr) -{ - if ( txfee != qp->txfee ) - { - if ( txfee >= value ) - return(-1); - qp->txfee = txfee; - qp->satoshis = value - txfee; - } - qp->timestamp = timestamp; - qp->quotetime = quotetime; - qp->destsatoshis = destsatoshis; - qp->desttxfee = desttxfee; - qp->desttxid = desttxid; - qp->destvout = destvout; - qp->desthash = desthash; - safecopy(qp->destaddr,destaddr,sizeof(qp->destaddr)); - return(0); -} - -char *LP_quotereceived(cJSON *argjson) -{ - struct LP_cacheinfo *ptr; double price; struct LP_quoteinfo Q; - LP_quoteparse(&Q,argjson); - price = (double)(Q.destsatoshis + Q.desttxfee) / (Q.satoshis + Q.txfee); - if ( (ptr= LP_cacheadd(Q.srccoin,Q.destcoin,Q.txid,Q.vout,price,&Q)) != 0 ) - { - ptr->Q = Q; - return(clonestr("{\"result\":\"updated\"}")); - } else return(clonestr("{\"error\":\"nullptr\"}")); -} - -double LP_query(char *method,struct LP_quoteinfo *qp,char *ipaddr,uint16_t port,char *base,char *rel,bits256 mypub) -{ - cJSON *reqjson; struct LP_peerinfo *peer; int32_t i,flag = 0,pushsock = -1; double price = 0.; - if ( ipaddr != 0 && port >= 1000 ) - { - if ( (peer= LP_peerfind((uint32_t)calc_ipbits(ipaddr),port)) == 0 ) - peer = LP_addpeer(1,0,-1,ipaddr,port,port+1,port+2,0,0,0); - if ( peer != 0 ) - { - if ( (pushsock= peer->pushsock) >= 0 ) - { - qp->desthash = mypub; - strcpy(qp->srccoin,base); - strcpy(qp->destcoin,rel); - if ( strcmp(method,"request") == 0 ) - qp->quotetime = (uint32_t)time(NULL); - reqjson = LP_quotejson(qp); - if ( bits256_nonz(qp->desthash) != 0 ) - flag = 1; - jaddstr(reqjson,"method",method); - LP_send(pushsock,jprint(reqjson,1),1); - for (i=0; i<30; i++) - { - if ( (price= LP_pricecache(qp,base,rel,qp->txid,qp->vout)) != 0. ) - { - if ( flag == 0 || bits256_nonz(qp->desthash) != 0 ) - { - //printf("break out of loop.%d price %.8f\n",i,price); - break; - } - } - usleep(100000); - } - } else printf("no pushsock for peer.%s:%u\n",ipaddr,port); - } else printf("cant find/create peer.%s:%u\n",ipaddr,port); - } - return(price); -} - -int32_t LP_sizematch(uint64_t mysatoshis,uint64_t othersatoshis) -{ - if ( mysatoshis >= othersatoshis ) - return(0); - else return(-1); -} - -cJSON *LP_tradecandidates(struct LP_utxoinfo *myutxo,char *base) -{ - struct LP_peerinfo *peer,*tmp; struct LP_quoteinfo Q; char *utxostr,coinstr[16]; cJSON *array,*icopy,*retarray=0,*item; int32_t i,n; double price; int64_t estimatedbase; - if ( (price= LP_price(base,myutxo->coin)) == .0 ) - { - printf("no LP_price (%s -> %s)\n",base,myutxo->coin); - return(0); - } - estimatedbase = myutxo->satoshis / price; - printf("%s -> %s price %.8f mysatoshis %llu estimated base %llu\n",base,myutxo->coin,price,(long long)myutxo->satoshis,(long long)estimatedbase); - if ( estimatedbase <= 0 ) - return(0); - HASH_ITER(hh,LP_peerinfos,peer,tmp) - { - if ( (utxostr= issue_LP_clientgetutxos(peer->ipaddr,peer->port,base,100)) != 0 ) - { - //printf("%s:%u %s\n",peer->ipaddr,peer->port,utxostr); - if ( (array= cJSON_Parse(utxostr)) != 0 ) - { - if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) - { - retarray = cJSON_CreateArray(); - for (i=0; icoin,jbits256(item,"txid"),jint(item,"vout"))) != 0. ) - { - if ( LP_sizematch(myutxo->satoshis,Q.destsatoshis) == 0 ) - icopy = jduplicate(item); - } else icopy = jduplicate(item); - if ( icopy != 0 ) - { - if ( price != 0. ) - jaddnum(icopy,"price",price); - jaddi(retarray,icopy); - } - } else printf("skip %s estimated %.8f vs %.8f\n",coinstr,dstr(estimatedbase),dstr(j64bits(item,"satoshis"))); - } - } - free_json(array); - } - free(utxostr); - } - if ( retarray != 0 ) - break; - } - return(retarray); -} - -cJSON *LP_autotrade(struct LP_utxoinfo *myutxo,char *base,double maxprice) -{ - static bits256 zero; - int32_t i,n,besti,DEXselector=0; cJSON *array,*item,*bestitem=0; struct basilisk_request R; double bestmetric,metric,bestprice=0.,price,prices[100]; struct LP_quoteinfo Q[sizeof(prices)/sizeof(*prices)]; - bestprice = 0.; - if ( maxprice == 0. ) - maxprice = LP_price(base,myutxo->coin) / 0.975; - if ( (array= LP_tradecandidates(myutxo,base)) != 0 ) + char *method,*ipaddr,*userpass,*base,*rel,*coin,*retstr = 0; uint16_t argport=0,pushport,subport; int32_t otherpeers,othernumutxos,flag = 0; struct LP_peerinfo *peer; cJSON *retjson; struct iguana_info *ptr; + //printf("stats_JSON(%s)\n",jprint(argjson,0)); + if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 ) { - printf("candidates.(%s)\n",jprint(array,0)); - if ( (n= cJSON_GetArraySize(array)) > 0 ) + if ( strcmp(ipaddr,"127.0.0.1") != 0 && argport >= 1000 ) { - memset(prices,0,sizeof(prices)); - memset(Q,0,sizeof(Q)); - for (i=0; icoin,zero); - if ( Q[i].destsatoshis != 0 && (double)j64bits(item,"satoshis")/Q[i].destsatoshis > price ) - { - printf("adjustprice %.8f -> %.8f\n",price,(double)j64bits(item,"satoshis")/Q[i].destsatoshis); - price = (double)j64bits(item,"satoshis")/Q[i].destsatoshis; - } - } - if ( (prices[i]= price) != 0. && (bestprice == 0. || price < bestprice) ) - bestprice = price; - char str[65]; printf("i.%d of %d: (%s) -> txid.%s price %.8f best %.8f\n",i,n,jprint(item,0),bits256_str(str,Q[i].txid),price,bestprice); - } - if ( bestprice != 0. ) + flag = 1; + if ( (pushport= juint(argjson,"push")) == 0 ) + pushport = argport + 1; + if ( (subport= juint(argjson,"sub")) == 0 ) + subport = argport + 2; + if ( (peer= LP_peerfind((uint32_t)calc_ipbits(ipaddr),argport)) != 0 ) { - bestmetric = 0.; - besti = -1; - for (i=0; i 0.9 ) - { - metric = Q[i].destsatoshis / metric * metric * metric; - printf("%f, ",metric); - if ( metric > bestmetric ) - { - besti = i; - bestmetric = metric; - } - } - } - } - printf("metrics, best %f\n",bestmetric); - if ( besti >= 0 )//&& bits256_cmp(myutxo->mypub,otherpubs[besti]) == 0 ) + if ( 0 && (otherpeers= jint(argjson,"numpeers")) > peer->numpeers ) + peer->numpeers = otherpeers; + if ( 0 && (othernumutxos= jint(argjson,"numutxos")) > peer->numutxos ) { - i = besti; - bestprice = prices[i]; - item = jitem(array,i); - bestitem = LP_quotejson(&Q[i]); - printf("bestprice %f vs maxprice %f\n",bestprice,maxprice); - if ( maxprice == 0. || bestprice <= maxprice ) - { - Q[i].desttxid = myutxo->txid; - Q[i].destvout = myutxo->vout; - Q[i].feetxid = myutxo->txid2; - Q[i].feevout = myutxo->vout2; - strcpy(Q[i].destaddr,myutxo->coinaddr); - price = LP_query("request",&Q[i],jstr(item,"ipaddr"),jint(item,"port"),base,myutxo->coin,myutxo->mypub); - if ( jobj(bestitem,"price") != 0 ) - jdelete(bestitem,"price"); - jaddnum(bestitem,"price",prices[i]); - if ( price <= maxprice ) - { - Q[i].desttxid = myutxo->txid; - Q[i].destvout = myutxo->vout; - Q[i].feetxid = myutxo->txid2; - Q[i].feevout = myutxo->vout2; - strcpy(Q[i].destaddr,myutxo->coinaddr); - price = LP_query("connect",&Q[i],jstr(item,"ipaddr"),jint(item,"port"),base,myutxo->coin,myutxo->mypub); - LP_requestinit(&R,Q[i].srchash,Q[i].desthash,base,Q[i].satoshis,Q[i].destcoin,Q[i].destsatoshis,Q[i].timestamp,Q[i].quotetime,DEXselector); - jaddstr(bestitem,"status","connected"); - jaddnum(bestitem,"requestid",R.requestid); - jaddnum(bestitem,"quoteid",R.quoteid); - printf("Alice r.%u q.%u\n",R.requestid,R.quoteid); - } else jaddstr(bestitem,"status","too expensive"); - } + printf("change.(%s) numutxos.%d -> %d mynumutxos.%d\n",peer->ipaddr,peer->numutxos,othernumutxos,LP_mypeer != 0 ? LP_mypeer->numutxos:0); + peer->numutxos = othernumutxos; } - } - free_json(array); + //printf("peer.(%s) found (%d %d) (%d %d) (%s)\n",peer->ipaddr,peer->numpeers,peer->numutxos,otherpeers,othernumutxos,jprint(argjson,0)); + } else LP_addpeer(LP_mypeer,LP_mypubsock,ipaddr,argport,pushport,subport,jdouble(argjson,"profit"),jint(argjson,"numpeers"),jint(argjson,"numutxos")); } } - if ( bestitem == 0 ) - return(cJSON_Parse("{\"error\":\"no match found\"}")); - return(bestitem); -} - -int32_t LP_priceping(int32_t pubsock,struct LP_utxoinfo *utxo,char *rel,double profitmargin) -{ - double price; uint32_t now; cJSON *retjson; struct LP_quoteinfo Q; char *retstr; - if ( (now= (uint32_t)time(NULL)) > utxo->swappending ) - utxo->swappending = 0; - if ( now > utxo->published+60 && utxo->swappending == 0 && utxo->pair < 0 && utxo->swap == 0 && (price= LP_price(utxo->coin,rel)) != 0. ) + if ( (method= jstr(argjson,"method")) == 0 ) { - price *= (1. + profitmargin); - if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 ) - return(-1); - Q.timestamp = (uint32_t)time(NULL); - retjson = LP_quotejson(&Q); - jaddstr(retjson,"method","quote"); - retstr = jprint(retjson,1); - LP_send(pubsock,retstr,1); - utxo->published = now; + if ( flag == 0 || jobj(argjson,"result") != 0 ) + printf("stats_JSON no method: (%s) (%s:%u)\n",jprint(argjson,0),ipaddr,argport); return(0); } - return(-1); -} - -int32_t LP_command(struct LP_peerinfo *mypeer,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin) -{ - char *method,*base,*rel,*retstr,pairstr[512]; cJSON *retjson; double price; bits256 privkey,txid; struct LP_utxoinfo *utxo; int32_t retval = -1,DEXselector = 0; uint64_t destvalue; struct basilisk_request R; struct LP_quoteinfo Q; - if ( IAMCLIENT == 0 && (method= jstr(argjson,"method")) != 0 ) + if ( strcmp(method,"hello") == 0 ) { - txid = jbits256(argjson,"txid"); - if ( (utxo= LP_utxofind(txid,jint(argjson,"vout"))) != 0 && strcmp(utxo->ipaddr,mypeer->ipaddr) == 0 && utxo->port == mypeer->port && (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 && strcmp(base,utxo->coin) == 0 ) - { - //printf("LP_command.(%s)\n",jprint(argjson,0)); - if ( time(NULL) > utxo->swappending ) - utxo->swappending = 0; - if ( strcmp(method,"price") == 0 || strcmp(method,"request") == 0 ) - { - retval = 1; - if ( utxo->swappending == 0 ) - { - if ( strcmp(method,"request") == 0 && utxo->pair >= 0 ) - nn_close(utxo->pair), utxo->pair = -1; - if ( (price= LP_price(base,rel)) != 0. ) - { - price *= (1. + profitmargin); - if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 ) - return(-1); - if ( strcmp(method,"price") == 0 ) - Q.timestamp = (uint32_t)time(NULL); - retjson = LP_quotejson(&Q); - if ( strcmp(method,"request") == 0 ) - { - retval |= 2; - utxo->swappending = (uint32_t)(time(NULL) + LP_RESERVETIME); - utxo->otherpubkey = jbits256(argjson,"desthash"); - jaddnum(retjson,"quotetime",juint(argjson,"quotetime")); - jaddnum(retjson,"pending",utxo->swappending); - jaddbits256(retjson,"desthash",utxo->otherpubkey); - jaddstr(retjson,"method","reserved"); - } - else jaddstr(retjson,"method","quote"); - retstr = jprint(retjson,1); - LP_send(pubsock,retstr,1); - utxo->published = (uint32_t)time(NULL); - } else printf("null price\n"); - } else printf("swappending.%u pair.%d\n",utxo->swappending,utxo->pair); - } - else if ( strcmp(method,"connect") == 0 ) - { - retval = 4; - if ( utxo->pair < 0 ) - { - if ( (price= LP_price(base,rel)) != 0. ) - { - price *= (1. + profitmargin); - if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 ) - return(-1); - if ( LP_quoteparse(&Q,argjson) < 0 ) - return(-2); - //printf("connect with.(%s)\n",jprint(argjson,0)); - privkey = LP_privkey(utxo->coinaddr); - if ( bits256_nonz(utxo->mypub) == 0 ) - utxo->mypub = LP_pubkey(privkey); - if ( bits256_nonz(privkey) != 0 && Q.quotetime >= Q.timestamp-3 && Q.quotetime < utxo->swappending && bits256_cmp(utxo->mypub,Q.srchash) == 0 && (destvalue= LP_txvalue(rel,Q.desttxid,Q.destvout)) >= price*Q.satoshis+Q.desttxfee && destvalue >= Q.destsatoshis+Q.desttxfee ) - { - Q.change = destvalue - (Q.destsatoshis+Q.desttxfee); - nanomsg_tcpname(pairstr,mypeer->ipaddr,10000+(rand() % 10000)); - if ( (utxo->pair= nn_socket(AF_SP,NN_PAIR)) < 0 ) - printf("error creating utxo->pair\n"); - else if ( nn_bind(utxo->pair,pairstr) >= 0 ) - { - //char str[65]; printf("destsatoshis %.8f %s t%u\n",dstr(Q.destsatoshis),bits256_str(str,Q.desthash),Q.quotetime); - LP_requestinit(&R,Q.srchash,Q.desthash,base,Q.satoshis,rel,Q.destsatoshis,Q.timestamp,Q.quotetime,DEXselector); - if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_bobloop,(void *)utxo) == 0 ) - { - retjson = LP_quotejson(&Q); - jaddstr(retjson,"method","connected"); - jaddstr(retjson,"pair",pairstr); - jaddnum(retjson,"requestid",R.requestid); - jaddnum(retjson,"quoteid",R.quoteid); - retstr = jprint(retjson,1); - LP_send(pubsock,retstr,1); - utxo->swap = LP_swapinit(1,0,privkey,&R,&Q); - } - else - { - printf("error launching swaploop\n"); - free(utxo->swap); - utxo->swap = 0; - nn_close(utxo->pair); - utxo->pair = -1; - } - } - else - { - printf("printf error nn_connect to %s\n",pairstr); - nn_close(utxo->pair); - utxo->pair = -1; - } - } else printf("dest %.8f < required %.8f (%d %d %d %d %d %d) %.8f %.8f\n",dstr(Q.satoshis),dstr(price*(utxo->satoshis-Q.txfee)),bits256_nonz(privkey) != 0 ,Q.timestamp == utxo->swappending-LP_RESERVETIME ,Q.quotetime >= Q.timestamp ,Q.quotetime < utxo->swappending ,bits256_cmp(utxo->mypub,Q.srchash) == 0 , LP_txvalue(rel,Q.desttxid,Q.destvout) >= price*Q.satoshis+Q.desttxfee,dstr(LP_txvalue(rel,Q.desttxid,Q.destvout)),dstr(price*Q.satoshis+Q.desttxfee)); - } else printf("no price for %s/%s\n",base,rel); - } else printf("utxo->pair.%d when connect came in (%s)\n",utxo->pair,jprint(argjson,0)); - } - } - } - return(retval); -} - -char *LP_connected(cJSON *argjson) -{ - cJSON *retjson; int32_t pairsock = -1; char *pairstr; struct LP_quoteinfo *qp; int32_t DEXselector = 0; - retjson = cJSON_CreateObject(); - if ( IAMCLIENT == 0 ) - jaddstr(retjson,"result","update stats"); - else - { - if ( (pairstr= jstr(argjson,"pair")) == 0 || (pairsock= nn_socket(AF_SP,NN_PAIR)) < 0 ) - jaddstr(retjson,"error","couldnt create pairsock"); - else if ( nn_connect(pairsock,pairstr) >= 0 ) - { - qp = calloc(1,sizeof(*qp)); - LP_quoteparse(qp,argjson); - qp->pair = pairsock; - qp->privkey = LP_privkey(qp->destaddr); - LP_requestinit(&qp->R,qp->srchash,qp->desthash,qp->srccoin,qp->satoshis,qp->destcoin,qp->destsatoshis,qp->timestamp,qp->quotetime,DEXselector); - printf("alice pairstr.(%s)\n",pairstr); - if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_aliceloop,(void *)qp) == 0 ) - { - jaddstr(retjson,"result","success"); - jadd(retjson,"trade",LP_quotejson(qp)); - } else jaddstr(retjson,"error","couldnt aliceloop"); - } + //printf("got hello from %s:%u\n",ipaddr!=0?ipaddr:"",argport); + return(0); } - return(jprint(retjson,1)); -} - -// addcoin api - -char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port -{ - char *method,*ipaddr,*userpass,*base,*rel,*coin,*retstr = 0; uint16_t argport,pushport,subport; int32_t amclient,otherpeers,othernumutxos; struct LP_peerinfo *peer; cJSON *retjson; - if ( (method= jstr(argjson,"method")) == 0 ) - return(clonestr("{\"error\":\"need method in request\"}")); + else if ( strcmp(method,"nn_tests") == 0 ) + return(clonestr("{\"result\":\"success\"}")); + else if ( strcmp(method,"help") == 0 ) + return(clonestr("{\"result\":\" \ +available localhost RPC commands:\n \ +setprice(base, rel, price)\n\ +myprice(base, rel)\n\ +enable(coin)\n\ +disable(coin)\n\ +inventory(coin)\n\ +autotrade(base, rel, price, volume, timeout)\n\ +swapstatus()\n\ +swapstatus(requestid, quoteid)\n\ +public API:\n \ +getcoins()\n\ +getpeers()\n\ +getutxos()\n\ +getutxos(coin, lastn)\n\ +orderbook(base, rel)\n\ +getprices(base, rel)\n\ +trust(pubkey, trust)\n\ +register(pubkey,pushaddr)\n\ +registerall(numnodes)\n\ +lookup(pubkey)\n\ +forward(pubkey,method2,)\n\ +forward(pubkey,method2=publish,)\n\ +forwardhex(pubkey,hex)\n\ +\"}")); + base = jstr(argjson,"base"); + rel = jstr(argjson,"rel"); if ( USERPASS[0] != 0 && strcmp(remoteaddr,"127.0.0.1") == 0 && port != 0 ) { if ( USERPASS_COUNTER == 0 ) @@ -545,24 +93,31 @@ char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port USERPASS_COUNTER = 1; retjson = cJSON_CreateObject(); jaddstr(retjson,"userpass",USERPASS); - jaddstr(retjson,"BTC",BTCADDR); - jaddstr(retjson,"KMD",KMDADDR); + jaddbits256(retjson,"mypubkey",LP_mypubkey); + jadd(retjson,"coins",LP_coinsjson()); return(jprint(retjson,1)); } if ( (userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,USERPASS) != 0 ) return(clonestr("{\"error\":\"authentication error\"}")); - if ( (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 ) + if ( base != 0 && rel != 0 ) { + double price; + if ( LP_isdisabled(base,rel) != 0 ) + return(clonestr("{\"error\":\"at least one of coins disabled\"}")); + price = jdouble(argjson,"price"); if ( strcmp(method,"setprice") == 0 ) { - if ( LP_mypriceset(base,rel,jdouble(argjson,"price")) < 0 ) - return(clonestr("{\"error\":\"couldnt set price\"}")); - else return(clonestr("{\"result\":\"success\"}")); + if ( price > SMALLVAL ) + { + if ( LP_mypriceset(base,rel,price) < 0 ) + return(clonestr("{\"error\":\"couldnt set price\"}")); + else return(LP_pricepings(ctx,myipaddr,LP_mypubsock,profitmargin,base,rel,price * LP_profitratio)); + } else return(clonestr("{\"error\":\"no price\"}")); } else if ( strcmp(method,"myprice") == 0 ) { double bid,ask; - if ( LP_myprice(&bid,&ask,base,rel) != 0. ) + if ( LP_myprice(&bid,&ask,base,rel) > SMALLVAL ) { retjson = cJSON_CreateObject(); jaddstr(retjson,"base",base); @@ -572,78 +127,142 @@ char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port return(jprint(retjson,1)); } else return(clonestr("{\"error\":\"no price set\"}")); } + else if ( strcmp(method,"autotrade") == 0 ) + { + if ( price > SMALLVAL ) + { + printf("price set (%s/%s) <- %.8f\n",rel,base,1./price); + LP_mypriceset(rel,base,1./price); + return(LP_autotrade(ctx,myipaddr,pubsock,profitmargin,base,rel,price,jdouble(argjson,"volume"),jint(argjson,"timeout"))); + } else return(clonestr("{\"error\":\"no price set\"}")); + } } else if ( (coin= jstr(argjson,"coin")) != 0 ) { - if ( strcmp(method,"inventory") == 0 ) + if ( strcmp(method,"enable") == 0 ) { - LP_privkey_init(0,-1,coin,0,USERPASS_WIFSTR,1); - return(LP_inventory(coin)); + if ( (ptr= LP_coinsearch(coin)) != 0 ) + ptr->inactive = 0; + return(jprint(LP_coinsjson(),1)); } - else if ( IAMCLIENT != 0 && (strcmp(method,"candidates") == 0 || strcmp(method,"autotrade") == 0) ) + else if ( strcmp(method,"disable") == 0 ) { - bits256 txid; int32_t vout; struct LP_utxoinfo *utxo; - txid = jbits256(argjson,"txid"); - if ( bits256_nonz(txid) == 0 ) - return(clonestr("{\"error\":\"invalid or missing txid\"}")); - if ( jobj(argjson,"vout") == 0 ) - return(clonestr("{\"error\":\"missing vout\"}")); - vout = jint(argjson,"vout"); - if ( (utxo= LP_utxofind(txid,vout)) == 0 ) - return(clonestr("{\"error\":\"txid/vout not found\"}")); - if ( strcmp(method,"candidates") == 0 ) - return(jprint(LP_tradecandidates(utxo,coin),1)); - else return(jprint(LP_autotrade(utxo,coin,jdouble(argjson,"maxprice")),1)); + if ( (ptr= LP_coinsearch(coin)) != 0 ) + ptr->inactive = (uint32_t)time(NULL); + return(jprint(LP_coinsjson(),1)); } - } - } - amclient = (LP_mypeer == 0); - if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 ) - { - if ( strcmp(ipaddr,"127.0.0.1") != 0 && port >= 1000 ) - { - if ( (pushport= juint(argjson,"push")) == 0 ) - pushport = argport + 1; - if ( (subport= juint(argjson,"sub")) == 0 ) - subport = argport + 2; - if ( (peer= LP_peerfind((uint32_t)calc_ipbits(ipaddr),argport)) != 0 ) + if ( LP_isdisabled(coin,0) != 0 ) + return(clonestr("{\"error\":\"coin is disabled\"}")); + if ( strcmp(method,"inventory") == 0 ) { - if ( 0 && (otherpeers= jint(argjson,"numpeers")) > peer->numpeers ) - peer->numpeers = otherpeers; - if ( 0 && (othernumutxos= jint(argjson,"numutxos")) > peer->numutxos ) + struct iguana_info *ptr; bits256 privkey,pubkey; uint8_t pubkey33[33]; + if ( (ptr= LP_coinfind(coin)) != 0 ) { - printf("change.(%s) numutxos.%d -> %d mynumutxos.%d\n",peer->ipaddr,peer->numutxos,othernumutxos,LP_mypeer != 0 ? LP_mypeer->numutxos:0); - peer->numutxos = othernumutxos; + privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,ptr,"",USERPASS_WIFSTR); + //LP_utxopurge(0); + LP_privkey_init(-1,ptr,privkey,pubkey,pubkey33); + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jaddstr(retjson,"coin",coin); + jaddnum(retjson,"timestamp",time(NULL)); + jadd(retjson,"alice",LP_inventory(coin,0)); + jadd(retjson,"bob",LP_inventory(coin,1)); + return(jprint(retjson,1)); } - //printf("peer.(%s) found (%d %d) (%d %d) (%s)\n",peer->ipaddr,peer->numpeers,peer->numutxos,otherpeers,othernumutxos,jprint(argjson,0)); - } else LP_addpeer(amclient,LP_mypeer,LP_mypubsock,ipaddr,argport,pushport,subport,jdouble(argjson,"profit"),jint(argjson,"numpeers"),jint(argjson,"numutxos")); + } + } + else if ( strcmp(method,"swapstatus") == 0 ) + { + uint32_t requestid,quoteid; + if ( (requestid= juint(argjson,"requestid")) != 0 && (quoteid= juint(argjson,"quoteid")) != 0 ) + return(basilisk_swapentry(requestid,quoteid)); + else return(basilisk_swaplist()); } + else if ( strcmp(method,"myprices") == 0 ) + return(LP_myprices()); + else if ( strcmp(method,"trust") == 0 ) + return(LP_pubkey_trustset(jbits256(argjson,"pubkey"),jint(argjson,"trust"))); } - //printf("CMD.(%s)\n",jprint(argjson,0)); - if ( strcmp(method,"quote") == 0 || strcmp(method,"reserved") == 0 ) + if ( LP_isdisabled(base,rel) != 0 ) + retstr = clonestr("{\"error\":\"at least one of coins disabled\"}"); + else if ( LP_isdisabled(jstr(argjson,"coin"),0) != 0 ) + retstr = clonestr("{\"error\":\"coin is disabled\"}"); + else if ( strcmp(method,"reserved") == 0 ) retstr = LP_quotereceived(argjson); else if ( strcmp(method,"connected") == 0 ) - retstr = LP_connected(argjson); - else if ( strcmp(method,"getprice") == 0 ) - retstr = LP_pricestr(jstr(argjson,"base"),jstr(argjson,"rel")); + retstr = LP_connectedalice(argjson); + else if ( strcmp(method,"checktxid") == 0 ) + retstr = LP_spentcheck(argjson); + else if ( strcmp(method,"getcoins") == 0 ) + return(jprint(LP_coinsjson(),1)); + else if ( strcmp(method,"postprice") == 0 ) + retstr = LP_postedprice(argjson); + else if ( strcmp(method,"broadcast") == 0 ) + retstr = LP_broadcasted(argjson); + else if ( strcmp(method,"getprices") == 0 ) + return(LP_prices()); else if ( strcmp(method,"orderbook") == 0 ) - retstr = LP_orderbook(jstr(argjson,"base"),jstr(argjson,"rel")); + return(LP_orderbook(base,rel)); + else if ( strcmp(method,"registerall") == 0 ) + return(LP_registerall(jint(argjson,"numnodes"))); + else if ( strcmp(method,"forward") == 0 ) + { + cJSON *reqjson; + if ( (reqjson= LP_dereference(argjson,"forward")) != 0 ) + { + //printf("FORWARDED.(%s)\n",jprint(argjson,0)); + if ( LP_forward(ctx,myipaddr,pubsock,profitmargin,jbits256(argjson,"pubkey"),jprint(reqjson,1),1) > 0 ) + retstr = clonestr("{\"result\":\"success\"}"); + else retstr = clonestr("{\"error\":\"error forwarding\"}"); + } else retstr = clonestr("{\"error\":\"cant recurse forwards\"}"); + + } + else if ( strcmp(method,"keepalive") == 0 ) + { + printf("got keepalive lag.%d switch.%u\n",(int32_t)time(NULL) - LP_deadman_switch,LP_deadman_switch); + LP_deadman_switch = (uint32_t)time(NULL); + return(clonestr("{\"result\":\"success\"}")); + } else if ( strcmp(method,"getpeers") == 0 ) - retstr = LP_peers(); - else if ( IAMCLIENT == 0 && strcmp(method,"getutxos") == 0 && (coin= jstr(argjson,"coin")) != 0 ) - retstr = LP_utxos(LP_mypeer,coin,jint(argjson,"lastn")); - else if ( IAMCLIENT == 0 && strcmp(method,"notify") == 0 ) - retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}"); - else if ( IAMCLIENT == 0 && strcmp(method,"notifyutxo") == 0 ) + return(LP_peers()); + else if ( strcmp(method,"getutxos") == 0 ) + return(LP_utxos(1,LP_mypeer,jstr(argjson,"coin"),jint(argjson,"lastn"))); + else if ( strcmp(method,"notified") == 0 ) { - printf("utxonotify.(%s)\n",jprint(argjson,0)); - LP_addutxo(amclient,LP_mypeer,LP_mypubsock,jstr(argjson,"coin"),jbits256(argjson,"txid"),jint(argjson,"vout"),SATOSHIDEN * jdouble(argjson,"value"),jbits256(argjson,"txid2"),jint(argjson,"vout2"),SATOSHIDEN * jdouble(argjson,"value2"),jstr(argjson,"script"),jstr(argjson,"address"),jstr(argjson,"ipaddr"),juint(argjson,"port"),jdouble(argjson,"profit")); - retstr = clonestr("{\"result\":\"success\",\"notifyutxo\":\"received\"}"); + if ( LP_utxoaddjson(1,LP_mypubsock,argjson) != 0 ) + return(clonestr("{\"result\":\"success\",\"notifyutxo\":\"received\"}")); + else return(clonestr("{\"error\":\"couldnt add utxo\"}")); + } + else if ( IAMLP != 0 ) + { + if ( strcmp(method,"register") == 0 ) + { + retstr = LP_register(jbits256(argjson,"client"),jstr(argjson,"pushaddr"),juint(argjson,"pushport")); + //printf("got (%s) from register\n",retstr!=0?retstr:""); + return(retstr); + } + else if ( strcmp(method,"lookup") == 0 ) + return(LP_lookup(jbits256(argjson,"client"))); + else if ( strcmp(method,"forwardhex") == 0 ) + retstr = LP_forwardhex(ctx,pubsock,jbits256(argjson,"pubkey"),jstr(argjson,"hex")); + else if ( strcmp(method,"psock") == 0 ) + { + if ( myipaddr == 0 || myipaddr[0] == 0 || strcmp(myipaddr,"127.0.0.1") == 0 ) + { + if ( LP_mypeer != 0 ) + myipaddr = LP_mypeer->ipaddr; + else printf("LP_psock dont have actual ipaddr?\n"); + } + return(LP_psock(myipaddr,jint(argjson,"ispaired"))); + } + else if ( strcmp(method,"notify") == 0 ) + retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}"); } if ( retstr != 0 ) - return(retstr); - retjson = cJSON_CreateObject(); - jaddstr(retjson,"error","unrecognized command"); + { + free(retstr); + return(0); + } printf("ERROR.(%s)\n",jprint(argjson,0)); - return(clonestr(jprint(retjson,1))); + return(0); } diff --git a/iguana/exchanges/LP_forwarding.c b/iguana/exchanges/LP_forwarding.c new file mode 100644 index 000000000..cbde40d71 --- /dev/null +++ b/iguana/exchanges/LP_forwarding.c @@ -0,0 +1,349 @@ + +/****************************************************************************** + * 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_forwarding.c +// marketmaker +// + +struct LP_forwardinfo +{ + UT_hash_handle hh; + bits256 pubkey; + char pushaddr[64]; + int32_t pushsock; + uint32_t lasttime,hello; +} *LP_forwardinfos; +#define LP_KEEPALIVE (3600 * 24) + +struct LP_forwardinfo *LP_forwardfind(bits256 pubkey) +{ + struct LP_forwardinfo *ptr=0; + portable_mutex_lock(&LP_forwardmutex); + HASH_FIND(hh,LP_forwardinfos,&pubkey,sizeof(pubkey),ptr); + portable_mutex_unlock(&LP_forwardmutex); + if ( ptr != 0 && ptr->lasttime > time(NULL)-LP_KEEPALIVE ) + return(ptr); + else return(0); +} + +char *LP_lookup(bits256 pubkey) +{ + if ( bits256_nonz(pubkey) == 0 ) + return(clonestr("{\"error\":\"illegal pubkey\"}")); + if ( LP_forwardfind(pubkey) != 0 ) + return(clonestr("{\"result\":\"success\",\"forwarding\":1}")); + else return(clonestr("{\"error\":\"notfound\"}")); +} + +int32_t LP_hello(struct LP_forwardinfo *ptr) +{ + int32_t i,n=10; char msg[512]; struct nn_pollfd pfd; + if ( bits256_cmp(ptr->pubkey,LP_mypubkey) != 0 ) + { + pfd.fd = ptr->pushsock; + pfd.events = NN_POLLOUT; + for (i=0; i 0 ) + { + sprintf(msg,"{\"method\":\"hello\",\"from\":\"%s\"}",LP_mypeer != 0 ? LP_mypeer->ipaddr : ""); + //printf("HELLO sent.%d bytes to %s on i.%d\n",LP_send(ptr->pushsock,msg,0),ptr->pushaddr,i); + ptr->hello = (uint32_t)time(NULL); + return(i); + } + } + //printf("%d iterations on nn_poll and %s pushsock still not ready\n",i,ptr->pushaddr); + return(-1); + } + return(0); +} + +int32_t LP_hellos() +{ + struct LP_forwardinfo *ptr,*tmp; int32_t nonz = 0; + HASH_ITER(hh,LP_forwardinfos,ptr,tmp) + { + if ( ptr->hello == 0 && LP_hello(ptr) >= 0 ) + nonz++; + } + return(nonz); +} + +int32_t LP_pushsock_create(struct LP_forwardinfo *ptr,char *pushaddr) +{ + int32_t pushsock,timeout; + if ( (pushsock= nn_socket(AF_SP,LP_COMMAND_SENDSOCK)) < 0 ) + { + printf("LP_pushsock_create couldnt allocate socket for %s\n",pushaddr); + return(-1); + } + else if ( nn_connect(pushsock,pushaddr) < 0 ) + { + nn_close(pushsock); + printf("LP_pushsock_create couldnt connect to %s\n",pushaddr); + return(-1); + } + timeout = 1; + nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); + nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); + if ( ptr != 0 ) + LP_hello(ptr); + return(pushsock); +} + +char *LP_register(bits256 pubkey,char *ipaddr,uint16_t port) +{ + struct LP_forwardinfo *ptr=0; int32_t pushsock; char pushaddr[64]; + if ( ipaddr == 0 || ipaddr[0] == 0 || is_ipaddr(ipaddr) == 0 || bits256_nonz(pubkey) == 0 ) + return(clonestr("{\"error\":\"illegal ipaddr or null pubkey\"}")); + nanomsg_transportname(0,pushaddr,ipaddr,port); + char str[65]; printf("register.(%s) %s\n",pushaddr,bits256_str(str,pubkey)); + if ( (ptr= LP_forwardfind(pubkey)) != 0 ) + { + ptr->lasttime = (uint32_t)time(NULL); + if ( ptr->pushsock >= 0 ) + { + if ( strcmp(pushaddr,ptr->pushaddr) != 0 ) + { + nn_close(ptr->pushsock); + if ( LP_psockmark(ptr->pushaddr) < 0 ) + { + //printf("cant mark (%s)\n",ptr->pushaddr); + } + char str[65]; printf("%u recreate pushsock for %s <- %s\n",(uint32_t)time(NULL),pushaddr,bits256_str(str,pubkey)); + strcpy(ptr->pushaddr,pushaddr); + if ( (ptr->pushsock= LP_pushsock_create(ptr,pushaddr)) < 0 ) + return(clonestr("{\"error\":\"couldnt recreate pushsock\",\"registered\":0}")); + } //else printf("no need to create identical endpoint\n"); + } + return(clonestr("{\"error\":\"already registered\",\"registered\":1}")); + } + else if ( (pushsock= LP_pushsock_create(0,pushaddr)) < 0 ) + return(clonestr("{\"error\":\"couldnt create pushsock\"}")); + else + { + ptr = calloc(1,sizeof(*ptr)); + ptr->pubkey = pubkey; + strcpy(ptr->pushaddr,pushaddr); + ptr->pushsock = pushsock; + ptr->lasttime = (uint32_t)time(NULL); + portable_mutex_lock(&LP_forwardmutex); + HASH_ADD_KEYPTR(hh,LP_forwardinfos,&ptr->pubkey,sizeof(ptr->pubkey),ptr); + portable_mutex_unlock(&LP_forwardmutex); + char str[65]; printf("registered (%s) -> (%s) pushsock.%d\n",bits256_str(str,pubkey),pushaddr,ptr->pushsock); + LP_hello(ptr); + return(LP_lookup(pubkey)); + } +} + +int32_t LP_forwarding_register(bits256 pubkey,char *publicaddr,uint16_t publicport,int32_t max) +{ + char *retstr,ipaddr[64]; cJSON *retjson; struct LP_peerinfo *peer,*tmp; int32_t j,n=0,retval = -1; + if ( publicaddr == 0 || publicaddr[0] == 0 || bits256_nonz(pubkey) == 0 ) + { + char str[65]; printf("LP_forwarding_register illegal publicaddr.(%s):%u or null pubkey (%s)\n",publicaddr,publicport,bits256_str(str,pubkey)); + return(0); + } + for (j=0; publicaddr[j]!=0; j++) + if ( publicaddr[j] >= '0' && publicaddr[j] <= '9' ) + break; + parse_ipaddr(ipaddr,publicaddr+j); + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + //printf("register.(%s) %s %u with (%s)\n",publicaddr,ipaddr,publicport,peer->ipaddr); + if ( (retstr= issue_LP_register(peer->ipaddr,peer->port,pubkey,ipaddr,publicport)) != 0 ) + { + //printf("[%s] LP_register.(%s) returned.(%s)\n",publicaddr,peer->ipaddr,retstr); + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( jint(retjson,"registered") != 0 && ++n >= max ) + retval = 0; + free_json(retjson); + } + free(retstr); + } else printf("timeout registering with %s errs.%d good.%d\n",peer->ipaddr,peer->errors,peer->good); + if ( retval == 0 ) + break; + } + return(n); +} + +char *LP_registerall(int32_t numnodes) +{ + int32_t i,maxnodes,n=0; cJSON *retjson; + if ( numnodes < sizeof(default_LPnodes)/sizeof(*default_LPnodes) ) + numnodes = (int32_t)(sizeof(default_LPnodes)/sizeof(*default_LPnodes)); + if ( (maxnodes= LP_numpeers()) < numnodes ) + numnodes = maxnodes; + for (i=0; i= numnodes ) + break; + retjson = cJSON_CreateObject(); + if ( i == numnodes ) + jaddstr(retjson,"error","not enough nodes"); + jaddnum(retjson,"numnodes",numnodes); + jaddnum(retjson,"registered",n); + jaddnum(retjson,"iters",i); + return(jprint(retjson,1)); +} + +cJSON *LP_dereference(cJSON *argjson,char *excludemethod) +{ + cJSON *reqjson = 0; + if ( jstr(argjson,"method2") != 0 && strncmp(excludemethod,jstr(argjson,"method2"),strlen(excludemethod)) != 0 ) + { + reqjson = jduplicate(argjson); + jdelete(reqjson,"method"); + jaddstr(reqjson,"method",jstr(argjson,"method2")); + } + return(reqjson); +} + +char *LP_forwardhex(void *ctx,int32_t pubsock,bits256 pubkey,char *hexstr) +{ + struct LP_forwardinfo *ptr=0; uint8_t *data; int32_t datalen=0,sentbytes=0; char *msg,*retstr=0; cJSON *retjson=0,*argjson=0,*reqjson=0; + if ( hexstr == 0 || hexstr[0] == 0 ) + return(clonestr("{\"error\":\"nohex\"}")); + datalen = (int32_t)strlen(hexstr) >> 1; + data = malloc(datalen); + decode_hex(data,datalen,hexstr); + if ( (argjson= cJSON_Parse((char *)data)) != 0 ) + reqjson = LP_dereference(argjson,"forward"); + if ( bits256_nonz(pubkey) == 0 || bits256_cmp(pubkey,LP_mypubkey) == 0 ) + { + if ( reqjson != 0 ) + { + retstr = LP_command_process(ctx,LP_mypeer != 0 ? LP_mypeer->ipaddr : "127.0.0.1",LP_mypubsock,reqjson,0,0,LP_profitratio - 1.); + printf("LP_forwardhex.(%s) -> (%s)\n",jprint(reqjson,0),retstr!=0?retstr:""); + if ( pubsock >= 0 ) + { + msg = jprint(reqjson,0); + LP_send(pubsock,msg,(int32_t)strlen(msg)+1,0); + } + } else printf("LP_forwardhex couldnt parse (%s)\n",(char *)data); + } + else if ( (ptr= LP_forwardfind(pubkey)) != 0 ) + { + if ( ptr->pushsock >= 0 )//&& ptr->hello != 0 ) + { + printf("%s forwardhex.(%s)\n",ptr->pushaddr,(char *)data); + sentbytes = LP_send(ptr->pushsock,(char *)data,datalen,0); + } + retjson = cJSON_CreateObject(); + if ( sentbytes == datalen ) + { + jaddstr(retjson,"result","success"); + jaddnum(retjson,"forwarded",sentbytes); + retstr = jprint(retjson,1); + } + else + { + jaddstr(retjson,"error","send error"); + jaddnum(retjson,"sentbytes",sentbytes); + jaddnum(retjson,"datalen",datalen); + jaddnum(retjson,"hello",ptr->hello); + retstr = jprint(retjson,1); + } + } + else + { + char str[65]; printf("couldnt find %s to forward to\n",bits256_str(str,pubkey)); + if ( pubsock >= 0 ) + { + msg = jprint(reqjson,0); + LP_send(pubsock,msg,(int32_t)strlen(msg)+1,1); + } + retstr = clonestr("{\"error\":\"notfound\"}"); + } + free(data); + if ( reqjson != 0 ) + free_json(reqjson); + if ( argjson != 0 ) + free_json(argjson); + return(retstr); +} + +int32_t LP_forward(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,bits256 pubkey,char *jsonstr,int32_t freeflag) +{ + struct LP_forwardinfo *ptr; struct LP_peerinfo *peer,*tmp; char *msg,*hexstr,*retstr; int32_t len,retval = -1; cJSON *retjson,*reqjson,*argjson; + if ( jsonstr == 0 || jsonstr[0] == 0 ) + return(-1); + if ( bits256_nonz(pubkey) != 0 ) + { + if ( bits256_cmp(pubkey,LP_mypubkey) == 0 ) + { + printf("GOT FORWARDED.(%s)\n",myipaddr); + if ( (argjson= cJSON_Parse(jsonstr)) != 0 ) + { + if ( (retstr= LP_command_process(ctx,myipaddr,pubsock,argjson,0,0,profitmargin)) != 0 ) + free(retstr); + free_json(argjson); + } + return(1); + } + else if ( IAMLP != 0 && (ptr= LP_forwardfind(pubkey)) != 0 && ptr->pushsock >= 0 && ptr->lasttime > time(NULL)-LP_KEEPALIVE ) + { + printf("GOT FORWARDED.(%s) -> pushsock.%d\n",jsonstr,ptr->pushsock); + len = (int32_t)strlen(jsonstr); + if ( LP_send(ptr->pushsock,jsonstr,(int32_t)strlen(jsonstr)+1,0) == len+1 ) + return(1); + } + } + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + if ( bits256_nonz(pubkey) != 0 ) + { + if ( (retstr= issue_LP_lookup(peer->ipaddr,peer->port,pubkey)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( jint(retjson,"forwarding") != 0 && peer->pushsock >= 0 ) + retval = 0; + free_json(retjson); + } + free(retstr); + } + } else retval = 0; + if ( retval >= 0 && peer->pushsock >= 0 ) + { + printf("found LPnode.(%s) forward.(%s)\n",peer->ipaddr,jsonstr); + len = (int32_t)strlen(jsonstr) + 1; + hexstr = malloc(len*2 + 1); + init_hexbytes_noT(hexstr,(uint8_t *)jsonstr,len); + if ( freeflag != 0 ) + free(jsonstr); + reqjson = cJSON_CreateObject(); + jaddstr(reqjson,"method","forwardhex"); + jaddstr(reqjson,"hex",hexstr); + jaddbits256(reqjson,"pubkey",pubkey); + free(hexstr); + msg = jprint(reqjson,1); + return(LP_send(peer->pushsock,msg,(int32_t)strlen(msg)+1,1)); + } else retval = -1; + } + if ( freeflag != 0 ) + free(jsonstr); + return(-1); +} + + +char *LP_broadcasted(cJSON *argjson) +{ + printf("RECV BROADCAST.(%s)\n",jprint(argjson,0)); + return(clonestr("{\"result\":\"need to update broadcast messages\"}")); +} + + diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index 9dc21ab9b..41c5286c8 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -21,6 +21,29 @@ #ifndef LP_INCLUDE_H #define LP_INCLUDE_H +#define LP_COMMAND_SENDSOCK NN_PUSH +#define LP_COMMAND_RECVSOCK NN_PULL + +#define LP_MAXPUBKEY_ERRORS 3 +#define PSOCK_KEEPALIVE 3600 +#define MAINLOOP_PERSEC 10 +#define MAX_PSOCK_PORT 60000 +#define MIN_PSOCK_PORT 10000 + +#define LP_HTTP_TIMEOUT 2 // 1 is too small due to edge cases of time(NULL) +#define LP_MAXPEER_ERRORS 3 +#define LP_MINPEER_GOOD 20 +#define LP_PEERGOOD_ERRORDECAY 0.9 + +#define LP_SWAPSTEP_TIMEOUT 3 +#define LP_AUTOTRADE_TIMEOUT 3 +#define LP_MIN_TXFEE 10000 +#define LP_MINVOL 3 +#define LP_MINCLIENTVOL 6 + +#define LP_DEXFEE(destsatoshis) ((destsatoshis) / INSTANTDEX_INSURANCEDIV) +#define LP_DEPOSITSATOSHIS(satoshis) ((satoshis) + (satoshis >> 3)) + #define INSTANTDEX_DECKSIZE 1000 #define INSTANTDEX_LOCKTIME (3600*2 + 300*2) #define INSTANTDEX_INSURANCEDIV 777 @@ -31,19 +54,19 @@ #define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu" #define INSTANTDEX_BTCD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf" -#define BASILISK_DISABLEWAITTX -#define BASILISK_DISABLESENDTX +//#define BASILISK_DISABLEWAITTX +//#define BASILISK_DISABLESENDTX -#define LP_PROPAGATION_SLACK 10 // txid ordering is not enforced, so getting extra recent txid +#define LP_PROPAGATION_SLACK 100 // txid ordering is not enforced, so getting extra recent txid #define LP_RESERVETIME 60 #define LP_AVETXSIZE 200 #define LP_CACHEDURATION 60 -#define BASILISK_DEFAULT_NUMCONFIRMS 5 +#define BASILISK_DEFAULT_NUMCONFIRMS 1 #define DEX_SLEEP 3 #define BASILISK_KEYSIZE ((int32_t)(2*sizeof(bits256)+sizeof(uint32_t)*2)) extern char GLOBAL_DBDIR[],USERPASS[],USERPASS_WIFSTR[]; -extern int32_t IAMCLIENT,USERPASS_COUNTER; +extern int32_t IAMLP,USERPASS_COUNTER; struct iguana_msgvin { bits256 prev_hash; uint8_t *vinscript,*userdata,*spendscript,*redeemscript; uint32_t prev_vout,sequence; uint16_t scriptlen,p2shlen,userdatalen,spendlen; }; @@ -136,41 +159,34 @@ struct basilisk_swapinfo struct iguana_info { - uint64_t txfee; double estimatedrate; - int32_t longestchain; - uint8_t pubtype,p2shtype,isPoS,wiftype; - char symbol[16],changeaddr[64],userpass[1024],serverport[128]; + uint64_t txfee; double estimatedrate,profitmargin; + int32_t longestchain; uint32_t counter,inactive; + uint8_t pubtype,p2shtype,isPoS,wiftype,taddr; + char symbol[16],smartaddr[64],userpass[1024],serverport[128]; }; -struct basilisk_swap -{ - void *ctx; struct iguana_info bobcoin,alicecoin; - void (*balancingtrade)(struct basilisk_swap *swap,int32_t iambob); - int32_t subsock,pushsock,connected,aliceunconf,depositunconf,paymentunconf; uint32_t lasttime,aborted; - FILE *fp; - bits256 persistent_privkey,persistent_pubkey; - struct basilisk_swapinfo I; - struct basilisk_rawtx bobdeposit,bobpayment,alicepayment,myfee,otherfee,aliceclaim,alicespend,bobreclaim,bobspend,bobrefund,alicereclaim; - bits256 privkeys[INSTANTDEX_DECKSIZE]; - struct basilisk_swapmessage *messages; int32_t nummessages; - char Bdeposit[64],Bpayment[64]; - uint64_t otherdeck[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2]; - uint8_t persistent_pubkey33[33],changermd160[20],pad[15],verifybuf[65536]; - -}; +struct _LP_utxoinfo { bits256 txid; uint64_t value; int32_t vout; }; + +struct LP_utxostats { uint32_t lasttime,errors,swappending,spentflag,lastspentcheck,bestflag; }; + +struct LP_utxobob { struct _LP_utxoinfo utxo,deposit; }; + +struct LP_utxoalice { struct _LP_utxoinfo utxo,fee; }; + +struct LP_utxoswap { bits256 otherpubkey; void *swap; uint64_t satoshis; double profitmargin; }; struct LP_utxoinfo { - UT_hash_handle hh; - bits256 txid,txid2,feetxid,otherpubkey,mypub; - void *swap; - uint64_t satoshis,satoshis2; + UT_hash_handle hh,hh2; + bits256 pubkey; + struct _LP_utxoinfo payment,deposit,fee; + struct LP_utxostats T; + struct LP_utxoswap S; + //struct LP_utxonetwork N; + int32_t iambob,iamlp; uint8_t key[sizeof(bits256) + sizeof(int32_t)]; - int32_t vout,vout2,pair; - uint32_t lasttime,errors,swappending,published; - double profitmargin; - char ipaddr[64],coinaddr[64],spendscript[256],coin[16]; - uint16_t port; + uint8_t key2[sizeof(bits256) + sizeof(int32_t)]; + char coin[16],coinaddr[64],spendscript[256],gui[16]; }; struct LP_peerinfo @@ -178,7 +194,7 @@ struct LP_peerinfo UT_hash_handle hh; uint64_t ip_port; double profitmargin; - uint32_t ipbits,errortime,errors,numpeers,numutxos,lasttime,connected; + uint32_t ipbits,errortime,errors,numpeers,numutxos,lasttime,connected,lastutxos,lastpeers,diduquery,good; int32_t pushsock,subsock; uint16_t port; char ipaddr[64]; @@ -188,16 +204,49 @@ struct LP_quoteinfo { struct basilisk_request R; bits256 srchash,desthash,txid,txid2,desttxid,feetxid,privkey; - uint64_t satoshis,satoshis2,txfee,destsatoshis,desttxfee,change; + uint64_t satoshis,txfee,destsatoshis,desttxfee; uint32_t timestamp,quotetime; int32_t vout,vout2,destvout,feevout,pair; char srccoin[16],coinaddr[64],destcoin[16],destaddr[64]; }; +struct LP_endpoint { int32_t pair; char ipaddr[64]; uint16_t port; }; + +struct basilisk_swap +{ + void *ctx; struct iguana_info bobcoin,alicecoin; struct LP_utxoinfo *utxo; + struct LP_endpoint N; + void (*balancingtrade)(struct basilisk_swap *swap,int32_t iambob); + int32_t subsock,pushsock,connected,aliceunconf,depositunconf,paymentunconf; uint32_t lasttime,aborted; + FILE *fp; + bits256 persistent_privkey,persistent_pubkey; + struct basilisk_swapinfo I; + struct basilisk_rawtx bobdeposit,bobpayment,alicepayment,myfee,otherfee,aliceclaim,alicespend,bobreclaim,bobspend,bobrefund,alicereclaim; + bits256 privkeys[INSTANTDEX_DECKSIZE]; + struct basilisk_swapmessage *messages; int32_t nummessages,sentflag; + char Bdeposit[64],Bpayment[64]; + uint64_t otherdeck[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2]; + uint8_t persistent_pubkey33[33],changermd160[20],pad[15],verifybuf[65536]; + +}; + 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); 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,double profitmargin,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); +char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin); +void LP_availableset(struct LP_utxoinfo *utxo); +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,bits256 pubkey); +int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsock,int32_t pullsock,double profitmargin); +uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired); + #endif diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index dbda8d683..78903fd2a 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -17,33 +17,32 @@ // LP_nativeDEX.c // marketmaker // -// jl777: fix price calcs based on specific txfees #include #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; +int32_t LP_canbind; #include "LP_network.c" -struct LP_utxoinfo *LP_utxoinfos; +struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2]; struct LP_peerinfo *LP_peerinfos,*LP_mypeer; +struct LP_forwardinfo *LP_forwardinfos; -char *activecoins[] = { "BTC", "KMD", "REVS", "JUMBLR" };//"LTC", "USD", }; +char *activecoins[] = { "BTC", "KMD" }; char GLOBAL_DBDIR[] = { "DB" }; -char USERPASS[65],USERPASS_WIFSTR[64],BTCADDR[64],KMDADDR[64],USERHOME[512] = { "/root" }; +char USERPASS[65],USERPASS_WIFSTR[64],LP_myipaddr[64],LP_publicaddr[64],USERHOME[512] = { "/root" }; +char LP_gui[16] = { "cli" }; -char *default_LPnodes[] = { "5.9.253.196", "5.9.253.197", "5.9.253.198", "5.9.253.199", "5.9.253.200", "5.9.253.201", "5.9.253.202", "5.9.253.203", "5.9.253.204" }; //"5.9.253.195", +char *default_LPnodes[] = { "5.9.253.195", "5.9.253.196", "5.9.253.197", "5.9.253.198", "5.9.253.199", "5.9.253.200", "5.9.253.201", "5.9.253.202", "5.9.253.203", };//"5.9.253.204" }; // -portable_mutex_t LP_peermutex,LP_utxomutex,LP_commandmutex,LP_cachemutex; +uint32_t LP_deadman_switch; +uint16_t LP_fixed_pairport,LP_publicport; int32_t LP_mypubsock = -1; -int32_t Client_connections; -int32_t USERPASS_COUNTER,IAMCLIENT = 0; +int32_t USERPASS_COUNTER,IAMLP = 0; double LP_profitratio = 1.; +bits256 LP_mypubkey; // stubs -int32_t basilisk_istrustedbob(struct basilisk_swap *swap) -{ - // for BTC and if trusted LP - return(0); -} void tradebot_swap_balancingtrade(struct basilisk_swap *swap,int32_t iambob) { @@ -54,6 +53,7 @@ void tradebot_pendingadd(cJSON *tradejson,char *base,double basevolume,char *rel { // add to trades } + char *LP_getdatadir() { return(USERHOME); @@ -74,229 +74,451 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_ #include "LP_swap.c" #include "LP_peers.c" #include "LP_utxos.c" +#include "LP_forwarding.c" +#include "LP_ordermatch.c" #include "LP_commands.c" -void LP_mainloop(struct LP_peerinfo *mypeer,uint16_t mypubport,int32_t pubsock,int32_t pullsock,uint16_t myport,int32_t amclient,char *passphrase,double profitmargin) +char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin) { - //static uint16_t tmpport; - char *retstr; uint8_t r; int32_t i,n,j,len,recvsize,counter=0,nonz,lastn; struct LP_peerinfo *peer,*tmp; struct LP_utxoinfo *utxo,*utmp; void *ptr; cJSON *argjson; - if ( amclient == 0 ) + char *retstr=0; + if ( jobj(argjson,"result") != 0 || jobj(argjson,"error") != 0 ) + return(0); + if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,data,datalen,profitmargin) <= 0 ) { - for (i=0; i 25 ) - continue; - LP_peersquery(amclient,mypeer,pubsock,default_LPnodes[i],myport,mypeer->ipaddr,myport,profitmargin); + //printf("%s PULL.[%d]-> (%s)\n",myipaddr != 0 ? myipaddr : "127.0.0.1",datalen,retstr); + if ( pubsock >= 0 ) //strncmp("{\"error\":",retstr,strlen("{\"error\":")) != 0 && + LP_send(pubsock,retstr,(int32_t)strlen(retstr)+1,0); } } - else + return(retstr); +} + +char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock,double profitmargin,void *ptr,int32_t recvlen,int32_t recvsock) +{ + int32_t len,datalen=0; char *msg,*retstr=0,*jsonstr=0; cJSON *argjson,*reqjson; + if ( (datalen= is_hexstr((char *)ptr,0)) > 0 ) { - OS_randombytes((void *)&r,sizeof(r)); - for (j=0; j>= 1; + jsonstr = malloc(datalen + 1); + decode_hex((void *)jsonstr,datalen,(char *)ptr); + jsonstr[datalen] = 0; + } else jsonstr = (char *)ptr; + if ( 0 && IAMLP == 0 ) + printf("%s %d, datalen.%d (%s)\n",typestr,recvlen,datalen,jsonstr); + if ( (argjson= cJSON_Parse(jsonstr)) != 0 ) + { + len = (int32_t)strlen(jsonstr) + 1; + portable_mutex_lock(&LP_commandmutex); + if ( jstr(argjson,"method") != 0 && strcmp(jstr(argjson,"method"),"forwardhex") == 0 ) + { + //printf("got forwardhex\n"); + if ( (retstr= LP_forwardhex(ctx,pubsock,jbits256(argjson,"pubkey"),jstr(argjson,"hex"))) != 0 ) + { + } + } + else if ( jstr(argjson,"method") != 0 && strcmp(jstr(argjson,"method"),"publish") == 0 ) + { + printf("got publish\n"); + if ( jobj(argjson,"method2") != 0 ) + jdelete(argjson,"method2"); + jaddstr(argjson,"method2","broadcast"); + if ( pubsock >= 0 && (reqjson= LP_dereference(argjson,"publish")) != 0 ) + { + msg = jprint(reqjson,1); + LP_send(pubsock,msg,(int32_t)strlen(msg)+1,1); + } + } + else if ( (retstr= LP_command_process(ctx,myipaddr,pubsock,argjson,&((uint8_t *)ptr)[len],recvlen - len,profitmargin)) != 0 ) { - i = (r + j) % (sizeof(default_LPnodes)/sizeof(*default_LPnodes)); - LP_peersquery(amclient,mypeer,pubsock,default_LPnodes[i],myport,"127.0.0.1",myport,profitmargin); + } + portable_mutex_unlock(&LP_commandmutex); + if ( LP_COMMAND_RECVSOCK == NN_REP ) + { + if ( retstr != 0 ) + { + if ( strcmp("PULL",typestr) == 0 ) + { + printf("%d got REQ.(%s) -> (%s)\n",recvsock,jprint(argjson,0),retstr); + LP_send(recvsock,retstr,(int32_t)strlen(retstr)+1,0); + } + } + else if ( strcmp("PULL",typestr) == 0 ) + { + printf("%d got REQ.(%s) -> null\n",recvsock,jprint(argjson,0)); + LP_send(recvsock,"{\"result\":null}",(int32_t)strlen("{\"result\":null}")+1,0); + } + } + free_json(argjson); + } else printf("error parsing(%s)\n",jsonstr); + if ( (void *)jsonstr != ptr ) + free(jsonstr); + if ( ptr != 0 ) + nn_freemsg(ptr), ptr = 0; + return(retstr); +} + +int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsock,int32_t pullsock,double profitmargin) +{ + void *ptr; int32_t recvlen=-1,nonz = 0; + *retstrp = 0; + if ( pullsock >= 0 ) + { + while ( (recvlen= nn_recv(pullsock,&ptr,NN_MSG,0)) > 0 ) + { + nonz++; + *retstrp = LP_process_message(ctx,"PULL",myipaddr,pubsock,profitmargin,ptr,recvlen,pullsock); } } - //if ( amclient != 0 ) - // tmpport = myport + 10; - //else tmpport = myport; - if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)stats_rpcloop,(void *)&myport) != 0 ) + return(nonz); +} + +int32_t LP_subsock_check(void *ctx,char *myipaddr,int32_t pubsock,int32_t sock,double profitmargin) +{ + int32_t recvlen,nonz = 0; void *ptr; char *retstr; + if ( sock >= 0 ) { - printf("error launching stats rpcloop for port.%u\n",myport); - exit(-1); + while ( (recvlen= nn_recv(sock,&ptr,NN_MSG,0)) > 0 ) + { + nonz++; + if ( (retstr= LP_process_message(ctx,"SUB",myipaddr,pubsock,profitmargin,ptr,recvlen,sock)) != 0 ) + free(retstr); + } + } + return(nonz); +} + +void LP_utxo_spentcheck(int32_t pubsock,struct LP_utxoinfo *utxo,double profitmargin) +{ + struct _LP_utxoinfo u; char str[65],destaddr[64]; uint32_t now = (uint32_t)time(NULL); + //printf("%s lag.%d\n",bits256_str(str,utxo->txid),now-utxo->lastspentcheck); + if ( utxo->T.spentflag == 0 && now > utxo->T.lastspentcheck+60 ) + { + u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; + utxo->T.lastspentcheck = now; + if ( LP_txvalue(destaddr,utxo->coin,utxo->payment.txid,utxo->payment.vout) == 0 ) + { + printf("txid.%s %s/v%d %.8f has been spent\n",utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout,dstr(utxo->payment.value)); + LP_spentnotify(utxo,0); + } + else if ( LP_txvalue(destaddr,utxo->coin,u.txid,u.vout) == 0 ) + { + printf("txid2.%s %s/v%d %.8f has been spent\n",utxo->coin,bits256_str(str,u.txid),u.vout,dstr(u.value)); + LP_spentnotify(utxo,1); + } + } +} + +void LP_myutxo_updates(void *ctx,int32_t pubsock,char *passphrase,double profitmargin) +{ + //LP_utxopurge(0); not good to disrupt existing pointers + LP_privkey_updates(ctx,pubsock,passphrase,0); +} + +int32_t LP_peer_utxosquery(struct LP_peerinfo *mypeer,uint16_t myport,int32_t pubsock,struct LP_peerinfo *peer,uint32_t now,double profitmargin,int32_t interval) +{ + int32_t lastn,n = -1; + if ( peer->lastutxos < now-interval ) + { + //lastn = peer->numutxos - mypeer->numutxos + LP_PROPAGATION_SLACK; + //if ( lastn < LP_PROPAGATION_SLACK * 2 ) + lastn = LP_PROPAGATION_SLACK * 2; + if ( mypeer == 0 || strcmp(peer->ipaddr,mypeer->ipaddr) != 0 ) + { + peer->lastutxos = now; + //printf("query utxos from %s\n",peer->ipaddr); + n = LP_utxosquery(mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,profitmargin); + } + } //else printf("LP_peer_utxosquery skip.(%s) %u\n",peer->ipaddr,peer->lastutxos); + return(n); +} + +int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int32_t pubsock,char *pushaddr,uint16_t pushport,int32_t pullsock,uint16_t myport,char *passphrase,double profitmargin) +{ + static uint32_t counter,lastforward,numpeers; + struct LP_utxoinfo *utxo,*utmp; char *retstr,*origipaddr; struct LP_peerinfo *peer,*tmp; uint32_t now; int32_t nonz = 0,n=0,lastn=-1; + now = (uint32_t)time(NULL); + if ( (origipaddr= myipaddr) == 0 ) + origipaddr = "127.0.0.1"; + if ( mypeer == 0 ) + myipaddr = "127.0.0.1"; + //if ( LP_canbind == 0 ) printf("counter.%d canbind.%d peers\n",counter,LP_canbind); + numpeers = LP_numpeers(); + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + if ( peer->errors >= LP_MAXPEER_ERRORS ) + { + if ( (rand() % 10000) == 0 ) + peer->errors--; + else continue; + } + if ( now > peer->lastpeers+60 && peer->numpeers > 0 && (peer->numpeers != numpeers || (rand() % 10000) == 0) ) + { + if ( IAMLP != 0 ) + printf("numpeers.%d updatepeer.%s lag.%d\n",numpeers,peer->ipaddr,now-peer->lastpeers); + peer->lastpeers = now; + if ( IAMLP != 0 && peer->numpeers != numpeers ) + printf("%s num.%d vs %d\n",peer->ipaddr,peer->numpeers,numpeers); + if ( strcmp(peer->ipaddr,myipaddr) != 0 ) + LP_peersquery(mypeer,pubsock,peer->ipaddr,peer->port,myipaddr,myport,profitmargin); + } + if ( peer->diduquery == 0 ) + { + if ( lastn != n || n < 20 ) + { + lastn = n; + n = LP_peer_utxosquery(mypeer,myport,pubsock,peer,now,profitmargin,60); + } + LP_peer_pricesquery(peer->ipaddr,peer->port); + peer->diduquery = now; + } + nonz += LP_subsock_check(ctx,origipaddr,pubsock,peer->subsock,profitmargin); + } + //if ( LP_canbind == 0 ) printf("counter.%d canbind.%d forwarding\n",counter,LP_canbind); + if ( (counter % 600) == 20 ) + { + LP_myutxo_updates(ctx,pubsock,passphrase,profitmargin); + if ( lastforward < now-3600 ) + { + if ( (retstr= LP_registerall(0)) != 0 ) + free(retstr); + //LP_forwarding_register(LP_mypubkey,pushaddr,pushport,10); + lastforward = now; + } + } + //if ( LP_canbind == 0 ) printf("counter.%d canbind.%d utxos\n",counter,LP_canbind); + if ( (counter % 600) == 60 ) + { + HASH_ITER(hh,LP_utxoinfos[0],utxo,utmp) + { + LP_utxo_spentcheck(pubsock,utxo,profitmargin); + } + HASH_ITER(hh,LP_utxoinfos[1],utxo,utmp) + { + //char str[65]; + LP_utxo_spentcheck(pubsock,utxo,profitmargin); + if ( utxo->T.lasttime == 0 ) + LP_utxo_clientpublish(utxo); + //else if ( strcmp(utxo->coin,"HUSH") == 0 ) + // printf("lasttime set %s\n",bits256_str(str,utxo->payment.txid)); + } + } + //if ( LP_canbind == 0 ) printf("counter.%d canbind.%d swapentry\n",counter,LP_canbind); + if ( (counter % 6000) == 5999 ) + { + if ( (retstr= basilisk_swapentry(0,0)) != 0 ) + { + //printf("SWAPS.(%s)\n",retstr); + free(retstr); + } + } + //if ( LP_canbind == 0 ) printf("counter.%d canbind.%d pullsock check\n",counter,LP_canbind); + nonz += LP_pullsock_check(ctx,&retstr,myipaddr,pubsock,pullsock,profitmargin); + if ( retstr != 0 ) + free(retstr); + //if ( LP_canbind == 0 ) printf("counter.%d canbind.%d hellos\n",counter,LP_canbind); + if ( IAMLP != 0 && (counter % 600) == 42 ) + LP_hellos(); + //if ( LP_canbind == 0 ) printf("counter.%d canbind.%d\n",counter,LP_canbind); + if ( LP_canbind == 0 && (counter % (PSOCK_KEEPALIVE*MAINLOOP_PERSEC/2)) == 13 ) + { + char keepalive[128]; + sprintf(keepalive,"{\"method\":\"keepalive\"}"); + //printf("send keepalive to %s pullsock.%d\n",pushaddr,pullsock); + if ( LP_send(pullsock,keepalive,(int32_t)strlen(keepalive)+1,0) < 0 ) + { + //LP_deadman_switch = 0; + } } + counter++; + return(nonz); +} + +void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins,char *passphrase) +{ + int32_t i,n; cJSON *item; for (i=0; i 0 ) { - if ( strcmp(peer->ipaddr,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1") != 0 ) - LP_utxosquery(0,mypeer,pubsock,peer->ipaddr,peer->port,"",100,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,profitmargin); + for (i=0; isubsock >= 0 && (recvsize= nn_recv(peer->subsock,&ptr,NN_MSG,0)) >= 0 ) - { - nonz++; - if ( (argjson= cJSON_Parse((char *)ptr)) != 0 ) - { - portable_mutex_lock(&LP_commandmutex); - if ( (retstr= stats_JSON(argjson,"127.0.0.1",0)) != 0 ) - { - //printf("%s RECV.[%d] %s\n",peer->ipaddr,recvsize,(char *)ptr); - free(retstr); - } - portable_mutex_unlock(&LP_commandmutex); - //printf("subloop.(%s)\n",jprint(argjson,0)); - free_json(argjson); - } else printf("error parsing.(%s)\n",(char *)ptr); - if ( ptr != 0 ) - nn_freemsg(ptr), ptr = 0; - } + if ( (rand() % 100) > 25 ) + continue; + LP_peersquery(mypeer,pubsock,default_LPnodes[i],myport,mypeer->ipaddr,myport,profitmargin); } - if ( nonz == 0 ) - usleep(100000); - } + } else LP_peersquery(mypeer,pubsock,seednode,myport,mypeer->ipaddr,myport,profitmargin); } else { - while ( 1 ) + if ( myipaddr == 0 ) { - nonz = 0; - if ( (++counter % 2000) == 0 ) - LP_privkey_updates(mypeer,pubsock,passphrase,amclient); - if ( (counter % 500) == 0 ) - { - HASH_ITER(hh,LP_utxoinfos,utxo,utmp) - { - if ( strcmp(utxo->ipaddr,mypeer->ipaddr) == 0 && utxo->port == mypeer->port ) - { - if ( strcmp(utxo->coin,"KMD") == 0 ) - LP_priceping(pubsock,utxo,"BTC",profitmargin); - else LP_priceping(pubsock,utxo,"KMD",profitmargin); - } - } - } - HASH_ITER(hh,LP_peerinfos,peer,tmp) - { - if ( peer->numpeers != mypeer->numpeers || (rand() % 10000) == 0 ) - { - if ( peer->numpeers != mypeer->numpeers ) - printf("%s num.%d vs %d\n",peer->ipaddr,peer->numpeers,mypeer->numpeers); - if ( strcmp(peer->ipaddr,mypeer->ipaddr) != 0 ) - LP_peersquery(amclient,mypeer,pubsock,peer->ipaddr,peer->port,mypeer->ipaddr,myport,profitmargin); - } - if ( peer->numutxos != mypeer->numutxos ) - { - lastn = peer->numutxos - mypeer->numutxos + LP_PROPAGATION_SLACK; - if ( lastn < LP_PROPAGATION_SLACK * 2 ) - lastn = LP_PROPAGATION_SLACK * 2; - printf("%s numutxos.%d vs %d lastn.%d\n",peer->ipaddr,peer->numutxos,mypeer->numutxos,lastn); - if ( strcmp(peer->ipaddr,mypeer->ipaddr) != 0 ) - LP_utxosquery(0,mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,mypeer->ipaddr,myport,profitmargin); - } - while ( peer->subsock >= 0 && (recvsize= nn_recv(peer->subsock,&ptr,NN_MSG,0)) >= 0 ) - { - nonz++; - if ( (argjson= cJSON_Parse((char *)ptr)) != 0 ) - { - portable_mutex_lock(&LP_commandmutex); - if ( (retstr= stats_JSON(argjson,"127.0.0.1",0)) != 0 ) - { - //printf("%s RECV.[%d] %s\n",peer->ipaddr,recvsize,(char *)ptr); - free(retstr); - } - portable_mutex_unlock(&LP_commandmutex); - free_json(argjson); - } else printf("error parsing.(%s)\n",(char *)ptr); - if ( ptr != 0 ) - nn_freemsg(ptr), ptr = 0; - } - } - while ( pullsock >= 0 && (recvsize= nn_recv(pullsock,&ptr,NN_MSG,0)) >= 0 ) + printf("couldnt get myipaddr\n"); + exit(-1); + } + if ( seednode == 0 || seednode[0] == 0 ) + { + OS_randombytes((void *)&r,sizeof(r)); + for (j=0; jipaddr,recvsize,(char *)ptr); - free(retstr); - } - } - portable_mutex_unlock(&LP_commandmutex); - free_json(argjson); - } - if ( ptr != 0 ) - nn_freemsg(ptr), ptr = 0; + i = (r + j) % (sizeof(default_LPnodes)/sizeof(*default_LPnodes)); + LP_peersquery(mypeer,pubsock,default_LPnodes[i],myport,"127.0.0.1",myport,profitmargin); } - if ( nonz == 0 ) - usleep(50000); - } + } else LP_peersquery(mypeer,pubsock,seednode,myport,"127.0.0.1",myport,profitmargin); } } -void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profitmargin,char *passphrase,int32_t amclient,char *userhome) +void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profitmargin,char *passphrase,int32_t amclient,char *userhome,cJSON *argjson) { - char *myipaddr=0; long filesize,n; int32_t timeout,maxsize,pullsock=-1,pubsock=-1; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128]; - IAMCLIENT = amclient; + char *myipaddr=0; long filesize,n; int32_t timeout,pullsock=-1,pubsock=-1; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128],bindaddr[128]; void *ctx = bitcoin_ctx(); + IAMLP = !amclient; +#ifndef __linux__ + if ( IAMLP != 0 ) + { + printf("must run a unix node for LP node\n"); + exit(-1); + } +#endif LP_profitratio += profitmargin; OS_randombytes((void *)&n,sizeof(n)); + if ( jobj(argjson,"gui") != 0 ) + safecopy(LP_gui,jstr(argjson,"gui"),sizeof(LP_gui)); + if ( jobj(argjson,"canbind") == 0 ) + { +#ifndef __linux__ + LP_canbind = 1; +#else + LP_canbind = IAMLP; +#endif + } else LP_canbind = jint(argjson,"canbind"); + if ( LP_canbind > 1000 && LP_canbind < 65536 ) + LP_fixed_pairport = LP_canbind; + if ( LP_canbind != 0 ) + LP_canbind = 1; srand((int32_t)n); if ( userhome != 0 && userhome[0] != 0 ) + { safecopy(USERHOME,userhome,sizeof(USERHOME)); +#ifdef __APPLE__ + strcat(USERHOME,"/Library/Application Support"); +#endif + } portable_mutex_init(&LP_peermutex); portable_mutex_init(&LP_utxomutex); + portable_mutex_init(&LP_UTXOmutex); portable_mutex_init(&LP_commandmutex); + portable_mutex_init(&LP_swaplistmutex); portable_mutex_init(&LP_cachemutex); - if ( amclient == 0 ) + portable_mutex_init(&LP_networkmutex); + portable_mutex_init(&LP_forwardmutex); + portable_mutex_init(&LP_psockmutex); + portable_mutex_init(&LP_pubkeymutex); + if ( profitmargin == 0. || profitmargin == 0.01 ) { - if ( profitmargin == 0. || profitmargin == 0.01 ) + profitmargin = 0.01 + (double)(rand() % 100)/100000; + printf("default profit margin %f\n",profitmargin); + } + if ( system("curl -s4 checkip.amazonaws.com > /tmp/myipaddr") == 0 ) + { + if ( (myipaddr= OS_filestr(&filesize,"/tmp/myipaddr")) != 0 && myipaddr[0] != 0 ) { - profitmargin = 0.01 + (double)(rand() % 100)/100000; - printf("default profit margin %f\n",profitmargin); - } - if ( system("curl -s4 checkip.amazonaws.com > /tmp/myipaddr") == 0 ) + n = strlen(myipaddr); + if ( myipaddr[n-1] == '\n' ) + myipaddr[--n] = 0; + strcpy(LP_myipaddr,myipaddr); + } else printf("error getting myipaddr\n"); + } else printf("error issuing curl\n"); + if ( IAMLP != 0 ) + { + pubsock = -1; + nanomsg_transportname(0,subaddr,myipaddr,mypubport); + nanomsg_transportname(1,bindaddr,myipaddr,mypubport); + if ( (pubsock= nn_socket(AF_SP,NN_PUB)) >= 0 ) { - if ( (myipaddr= OS_filestr(&filesize,"/tmp/myipaddr")) != 0 && myipaddr[0] != 0 ) + if ( nn_bind(pubsock,bindaddr) >= 0 ) { - n = strlen(myipaddr); - if ( myipaddr[n-1] == '\n' ) - myipaddr[--n] = 0; - pullsock = pubsock = -1; - nanomsg_tcpname(pushaddr,myipaddr,mypullport); - nanomsg_tcpname(subaddr,myipaddr,mypubport); - printf(">>>>>>>>> myipaddr.%s (%s %s)\n",myipaddr,pushaddr,subaddr); - if ( (pullsock= nn_socket(AF_SP,NN_PULL)) >= 0 && (pubsock= nn_socket(AF_SP,NN_PUB)) >= 0 ) - { - if ( nn_bind(pullsock,pushaddr) >= 0 && nn_bind(pubsock,subaddr) >= 0 ) - { - timeout = 10; - nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); - timeout = 1; - nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); - timeout = 1; - maxsize = 1024 * 1024; - nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVBUF,&maxsize,sizeof(maxsize)); - } - else - { - printf("error binding to (%s).%d (%s).%d\n",pushaddr,pullsock,subaddr,pubsock); - if ( pullsock >= 0 ) - nn_close(pullsock), pullsock = -1; - if ( pubsock >= 0 ) - nn_close(pubsock), pubsock = -1; - } - } else printf("error getting sockets %d %d\n",pullsock,pubsock); - LP_mypubsock = pubsock; - LP_mypeer = mypeer = LP_addpeer(amclient,mypeer,pubsock,myipaddr,myport,0,0,profitmargin,0,0); - //printf("my ipaddr.(%s) peers.(%s)\n",ipaddr,retstr!=0?retstr:""); - } else printf("error getting myipaddr\n"); - } else printf("error issuing curl\n"); - if ( myipaddr == 0 || mypeer == 0 ) + timeout = 10; + nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); + } + else + { + printf("error binding to (%s).%d\n",subaddr,pubsock); + if ( pubsock >= 0 ) + nn_close(pubsock), pubsock = -1; + } + } else printf("error getting pubsock %d\n",pubsock); + printf(">>>>>>>>> myipaddr.%s (%s) pullsock.%d\n",myipaddr,subaddr,pubsock); + LP_mypubsock = pubsock; + } + LP_initpeers(pubsock,mypeer,myipaddr,myport,jstr(argjson,"seednode"),profitmargin); + pullsock = LP_initpublicaddr(ctx,&mypullport,pushaddr,myipaddr,mypullport,0); + strcpy(LP_publicaddr,pushaddr); + LP_publicport = mypullport; + LP_deadman_switch = (uint32_t)time(NULL); + printf("my command address is (%s) pullsock.%d pullport.%u\n",pushaddr,pullsock,mypullport); + LP_initcoins(ctx,pubsock,jobj(argjson,"coins"),passphrase); + if ( IAMLP != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_psockloop,(void *)&myipaddr) != 0 ) + { + printf("error launching LP_psockloop for (%s)\n",myipaddr); + exit(-1); + } + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)stats_rpcloop,(void *)&myport) != 0 ) + { + printf("error launching stats rpcloop for port.%u\n",myport); + exit(-1); + } + while ( 1 ) + { + //fprintf(stderr,"."); + if ( LP_mainloop_iter(ctx,myipaddr,mypeer,pubsock,pushaddr,mypullport,pullsock,myport,passphrase,profitmargin) == 0 ) + usleep(1000000 / MAINLOOP_PERSEC); + if ( LP_canbind == 0 ) { - printf("couldnt get myipaddr or null mypeer.%p\n",mypeer); - exit(-1); + //printf("check deadman %u vs %u\n",LP_deadman_switch,(uint32_t)time(NULL)); + if ( LP_deadman_switch < time(NULL)-PSOCK_KEEPALIVE ) + { + printf("DEAD man's switch %u activated at %u lag.%d, register forwarding again\n",LP_deadman_switch,(uint32_t)time(NULL),(uint32_t)(time(NULL) - LP_deadman_switch)); + if ( pullsock >= 0 ) + nn_close(pullsock); + pullsock = LP_initpublicaddr(ctx,&mypullport,pushaddr,myipaddr,mypullport,0); + LP_deadman_switch = (uint32_t)time(NULL); + strcpy(LP_publicaddr,pushaddr); + LP_publicport = mypullport; + LP_forwarding_register(LP_mypubkey,pushaddr,mypullport,MAX_PSOCK_PORT); + } } - printf("utxos.(%s)\n",LP_utxos(mypeer,"",10000)); } - LP_mainloop(mypeer,mypubport,pubsock,pullsock,myport,amclient,passphrase,profitmargin); } + diff --git a/iguana/exchanges/LP_network.c b/iguana/exchanges/LP_network.c index ff2e35c11..b25dc824a 100644 --- a/iguana/exchanges/LP_network.c +++ b/iguana/exchanges/LP_network.c @@ -18,39 +18,52 @@ // marketmaker // -char *nanomsg_tcpname(char *str,char *ipaddr,uint16_t port) +struct psock { - sprintf(str,"tcp://%s:%u",ipaddr,port); + uint32_t lasttime,lastping,errors; + int32_t publicsock,sendsock,ispaired; + uint16_t publicport,sendport; + char sendaddr[128],publicaddr[128]; +} *PSOCKS; + +uint16_t Numpsocks,Psockport = MIN_PSOCK_PORT; + +char *nanomsg_transportname(int32_t bindflag,char *str,char *ipaddr,uint16_t port) +{ + sprintf(str,"tcp://%s:%u",bindflag == 0 ? ipaddr : "*",port); return(str); } -int32_t LP_send(int32_t sock,char *msg,int32_t freeflag) +int32_t LP_send(int32_t sock,void *msg,int32_t sendlen,int32_t freeflag) { - int32_t sentbytes,len,i; struct nn_pollfd pfd; + int32_t sentbytes,i; struct nn_pollfd pfd; if ( sock < 0 ) { - printf("LP_send.(%s) to illegal socket\n",msg); + printf("LP_send.(%s) to illegal socket\n",(char *)msg); if ( freeflag != 0 ) free(msg); return(-1); } - for (i=0; i<100; i++) + //len = (int32_t)strlen(msg) + 1; + for (i=0; i<1000; i++) // 1000 * (1 ms + 1000 us) = 2 seconds { pfd.fd = sock; pfd.events = NN_POLLOUT; - if ( nn_poll(&pfd,1,100) > 0 ) + //portable_mutex_lock(&LP_networkmutex); + if ( nn_poll(&pfd,1,1) > 0 ) { - len = (int32_t)strlen(msg) + 1; - if ( (sentbytes= nn_send(sock,msg,len,0)) != len ) - printf("LP_send sent %d instead of %d\n",sentbytes,len); - else printf("SENT.(%s)\n",msg); + if ( (sentbytes= nn_send(sock,msg,sendlen,0)) != sendlen ) + printf("LP_send sent %d instead of %d\n",sentbytes,sendlen); + //else printf("SENT.(%s)\n",msg); if ( freeflag != 0 ) free(msg); + //portable_mutex_unlock(&LP_networkmutex); return(sentbytes); } + //portable_mutex_unlock(&LP_networkmutex); usleep(1000); } - printf("error LP_send\n"); + printf("error LP_send sock.%d, i.%d timeout.(%s) %s\n",sock,i,(char *)msg,nn_strerror(nn_errno())); if ( freeflag != 0 ) free(msg); return(-1); @@ -75,8 +88,365 @@ uint32_t LP_swapsend(int32_t pairsock,struct basilisk_swap *swap,uint32_t msgbit { } } - printf("sent %d bytes\n",sentbytes); + //printf("sent %d bytes\n",sentbytes); //else printf("send.[%d] %x offset.%d datalen.%d [%llx]\n",sentbytes,msgbits,offset,datalen,*(long long *)data); free(buf); return(nextbits); } + +void LP_psockloop(void *_ptr) +{ + static struct nn_pollfd *pfds; + int32_t i,n,nonz,iter,retval,size=0,sentbytes,sendsock = -1; uint32_t now; struct psock *ptr=0; void *buf=0; char keepalive[512];//,*myipaddr = _ptr; + while ( 1 ) + { + now = (uint32_t)time(NULL); + if ( buf != 0 && ptr != 0 && sendsock >= 0 ) + { + if ( size > 0 ) + { + if ( (sentbytes= LP_send(sendsock,buf,size,0)) > 0 ) + { + //printf("PSOCKS (%d %d %d) (%s) -> %d/%d bytes %s\n",ptr->publicsock,ptr->sendsock,sendsock,(char *)buf,size,sentbytes,ptr->sendaddr); + } + else + { + ptr->errors++; + printf("send error.%d to %s\n",ptr->errors,ptr->sendaddr); + } + if ( buf != 0 ) + { + if ( buf != keepalive ) + nn_freemsg(buf); + buf = 0; + size = 0; + ptr = 0; + sendsock = -1; + } + } + } + else if ( Numpsocks > 0 ) + { + if ( pfds == 0 ) + pfds = calloc(MAX_PSOCK_PORT,sizeof(*pfds)); + portable_mutex_lock(&LP_psockmutex); + memset(pfds,0,sizeof(*pfds) * ((Numpsocks*2 <= MAX_PSOCK_PORT) ? Numpsocks*2 : MAX_PSOCK_PORT)); + for (iter=0; iter<2; iter++) + { + for (i=n=0; ipublicsock; + pfds[n].events = POLLIN; + } + else + { + if ( pfds[n].fd != ptr->publicsock ) + { + printf("unexpected fd.%d mismatched publicsock.%d\n",pfds[n].fd,ptr->publicsock); + break; + } + else if ( (pfds[n].revents & POLLIN) != 0 ) + { + //printf("publicsock.%d %s has pollin\n",ptr->publicsock,ptr->publicaddr); + if ( (size= nn_recv(ptr->publicsock,&buf,NN_MSG,0)) > 0 ) + { + ptr->lasttime = now; + sendsock = ptr->sendsock; + break; + } + } + } + n++; + if ( iter == 0 ) + { + pfds[n].fd = ptr->sendsock; + pfds[n].events = POLLIN; + } + else + { + if ( pfds[n].fd != ptr->sendsock ) + { + printf("unexpected fd.%d mismatched sendsock.%d\n",pfds[n].fd,ptr->sendsock); + break; + } + else if ( (pfds[n].revents & POLLIN) != 0 ) + { + if ( (size= nn_recv(ptr->sendsock,&buf,NN_MSG,0)) > 0 ) + { + //printf("%s paired has pollin (%s)\n",ptr->sendaddr,(char *)buf); + ptr->lasttime = now; + if ( ptr->ispaired != 0 ) + { + sendsock = ptr->publicsock; + break; + } + else + { + nn_freemsg(buf); + buf = 0; + size = 0; + } + } + } + } + n++; + } + if ( iter == 0 ) + { + if ( (retval= nn_poll(pfds,n,1)) <= 0 ) + { + if ( retval != 0 ) + printf("nn_poll retval.%d\n",retval); + break; + } // else printf("num pfds.%d retval.%d\n",n,retval); + } + } + //free(pfds); + //printf("sendsock.%d Numpsocks.%d\n",sendsock,Numpsocks); + if ( sendsock < 0 ) + { + for (i=nonz=0; i ptr->lasttime+PSOCK_KEEPALIVE ) + { + printf("PSOCKS[%d] of %d (%u %u) lag.%d IDLETIMEOUT\n",i,Numpsocks,ptr->publicport,ptr->sendport,now - ptr->lasttime); + if ( ptr->publicsock >= 0 ) + nn_close(ptr->publicsock); + if ( ptr->sendsock >= 0 ) + nn_close(ptr->sendsock); + //portable_mutex_lock(&LP_psockmutex); + if ( Numpsocks > 1 ) + { + PSOCKS[i] = PSOCKS[--Numpsocks]; + memset(&PSOCKS[Numpsocks],0,sizeof(*ptr)); + } else Numpsocks = 0; + //portable_mutex_unlock(&LP_psockmutex); + break; + } + else if ( now > ptr->lastping+PSOCK_KEEPALIVE/2 && ptr->errors < 3 ) + { + ptr->lastping = now; + sendsock = ptr->sendsock; + sprintf(keepalive,"{\"method\":\"keepalive\",\"endpoint\":\"%s\"}",ptr->sendaddr); + size = (int32_t)strlen(keepalive) + 1; + buf = keepalive; + printf("send keepalive.(%s)\n",keepalive); + break; + } + } + } + if ( nonz == 0 && i == Numpsocks ) + usleep(100000); + } + portable_mutex_unlock(&LP_psockmutex); + } else usleep(100000); + } +} + +void LP_psockadd(int32_t ispaired,int32_t publicsock,uint16_t recvport,int32_t sendsock,uint16_t sendport,char *subaddr,char *publicaddr) +{ + struct psock *ptr; + portable_mutex_lock(&LP_psockmutex); + PSOCKS = realloc(PSOCKS,sizeof(*PSOCKS) * (Numpsocks + 1)); + ptr = &PSOCKS[Numpsocks++]; + ptr->ispaired = ispaired; + ptr->publicsock = publicsock; + ptr->publicport = recvport; + ptr->sendsock = sendsock; + ptr->sendport = sendport; + safecopy(ptr->sendaddr,subaddr,sizeof(ptr->sendaddr)); + safecopy(ptr->publicaddr,publicaddr,sizeof(ptr->publicaddr)); + ptr->lasttime = (uint32_t)time(NULL); + portable_mutex_unlock(&LP_psockmutex); +} + +int32_t LP_psockmark(char *publicaddr) +{ + int32_t i,retval = -1; struct psock *ptr; + portable_mutex_lock(&LP_psockmutex); + for (i=0; ipublicaddr) == 0 ) + { + printf("mark PSOCKS[%d] %s for deletion\n",i,publicaddr); + ptr->lasttime = 0; + retval = i; + break; + } + } + portable_mutex_unlock(&LP_psockmutex); + return(retval); +} + +char *LP_psock(char *myipaddr,int32_t ispaired) +{ + char pushaddr[128],subaddr[128]; uint16_t i,publicport,subport,maxiters=100; int32_t timeout,maxsize,pullsock=-1,pubsock=-1; cJSON *retjson=0; + retjson = cJSON_CreateObject(); + publicport = Psockport++; + subport = Psockport++; + for (i=0; i= 0 && (pubsock= nn_socket(AF_SP,ispaired!=0?NN_PAIR:NN_PAIR)) >= 0 ) + { + if ( nn_bind(pullsock,pushaddr) >= 0 && nn_bind(pubsock,subaddr) >= 0 ) + { + timeout = 1; + nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); + timeout = 1; + nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); + if ( ispaired != 0 ) + { + maxsize = 1024 * 1024; + nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVBUF,&maxsize,sizeof(maxsize)); + } + //if ( ispaired != 0 ) + { + nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); + nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); + } + nanomsg_transportname(0,pushaddr,myipaddr,publicport); + nanomsg_transportname(0,subaddr,myipaddr,subport); + LP_psockadd(ispaired,pullsock,publicport,pubsock,subport,subaddr,pushaddr); + jaddstr(retjson,"result","success"); + jaddstr(retjson,"LPipaddr",myipaddr); + jaddstr(retjson,"connectaddr",subaddr); + jaddnum(retjson,"connectport",subport); + jaddnum(retjson,"ispaired",ispaired); + jaddstr(retjson,"publicaddr",pushaddr); + jaddnum(retjson,"publicport",publicport); + printf("i.%d publicaddr.(%s) for subaddr.(%s), pullsock.%d pubsock.%d\n",i,pushaddr,subaddr,pullsock,pubsock); + break; + } else printf("bind error on %s or %s\n",pushaddr,subaddr); + if ( pullsock >= 0 ) + nn_close(pullsock); + if ( pubsock >= 0 ) + nn_close(pubsock); + } + } + if ( Psockport > MAX_PSOCK_PORT ) + Psockport = MIN_PSOCK_PORT; + if ( i == maxiters ) + jaddstr(retjson,"error","cant find psock ports"); + return(jprint(retjson,1)); +} + +/* + LP_pushaddr_get makes transparent the fact that most nodes cannot bind()! + + The idea is to create an LP node NN_PAIR sock that the LP node binds to and client node connects to. Additionally, the LP node creates an NN_PULL that other nodes can NN_PUSH to and returns this address in pushaddr/retval for the client node to register with. The desired result is that other than the initial LP node, all the other nodes do a normal NN_PUSH, requiring no change to the NN_PUSH/NN_PULL logic. Of course, the initial LP node needs to autoforward all packets from the public NN_PULL to the NN_PUB + + similar to LP_pushaddr_get, create an NN_PAIR for DEX atomic data, can be assumed to have a max lifetime of 2*INSTANTDEX_LOCKTIME + + both are combined in LP_psock_get + +*/ + +int32_t nn_tests(void *ctx,int32_t pullsock,char *pushaddr,int32_t nnother) +{ + int32_t sock,n,m,timeout,retval = -1; char msg[512],*retstr; + printf("nn_tests.(%s)\n",pushaddr); + if ( (sock= nn_socket(AF_SP,nnother)) >= 0 ) + { + if ( nn_connect(sock,pushaddr) < 0 ) + printf("connect error %s\n",nn_strerror(nn_errno())); + else + { + sleep(3); + timeout = 1; + nn_setsockopt(sock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); + sprintf(msg,"{\"method\":\"nn_tests\",\"ipaddr\":\"%s\"}",pushaddr); + n = LP_send(sock,msg,(int32_t)strlen(msg)+1,0); + sleep(3); + LP_pullsock_check(ctx,&retstr,"127.0.0.1",-1,pullsock,0.); + sprintf(msg,"{\"method\":\"nn_tests2\",\"ipaddr\":\"%s\"}",pushaddr); + m = LP_send(pullsock,msg,(int32_t)strlen(msg)+1,0); + printf(">>>>>>>>>>>>>>>>>>>>>> sent %d+%d bytes -> pullsock.%d retstr.(%s)\n",n,m,pullsock,retstr!=0?retstr:""); + if ( retstr != 0 ) + { + free(retstr); + retval = 0; + } + } + nn_close(sock); + } + return(retval); +} + +int32_t LP_initpublicaddr(void *ctx,uint16_t *mypullportp,char *publicaddr,char *myipaddr,uint16_t mypullport,int32_t ispaired) +{ + int32_t nntype,pullsock,timeout; char bindaddr[128],connectaddr[128]; + *mypullportp = mypullport; + if ( ispaired == 0 ) + { + if ( LP_canbind != 0 ) + nntype = LP_COMMAND_RECVSOCK; + else nntype = NN_PAIR;//NN_SUB; + } else nntype = NN_PAIR; + if ( LP_canbind != 0 ) + { + nanomsg_transportname(0,publicaddr,myipaddr,mypullport); + nanomsg_transportname(1,bindaddr,myipaddr,mypullport); + } + else + { + *mypullportp = 0; + while ( *mypullportp == 0 ) + { + if ( (*mypullportp= LP_psock_get(connectaddr,publicaddr,ispaired)) != 0 ) + break; + sleep(10); + printf("try to get publicaddr again\n"); + } + } + while ( 1 ) + { + if ( (pullsock= nn_socket(AF_SP,nntype)) >= 0 ) + { + if ( LP_canbind == 0 ) + { + if ( nn_connect(pullsock,connectaddr) < 0 ) + { + printf("bind to %s error for %s: %s\n",connectaddr,publicaddr,nn_strerror(nn_errno())); + exit(-1); + } else printf("nntype.%d NN_PAIR.%d connect to %s connectsock.%d\n",nntype,NN_PAIR,connectaddr,pullsock); + } + else + { + if ( nn_bind(pullsock,bindaddr) < 0 ) + { + printf("bind to %s error for %s: %s\n",bindaddr,publicaddr,nn_strerror(nn_errno())); + exit(-1); + } + } + timeout = 1; + nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); + timeout = 1; + nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); + //maxsize = 2 * 1024 * 1024; + //nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVBUF,&maxsize,sizeof(maxsize)); + if ( nntype == NN_SUB ) + nn_setsockopt(pullsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); + } + if ( LP_canbind != 0 || ispaired != 0 || nn_tests(ctx,pullsock,publicaddr,NN_PUSH) >= 0 ) + break; + printf("nn_tests failed, try again\n"); + sleep(3); + if ( pullsock >= 0 ) + nn_close(pullsock); + } + return(pullsock); +} diff --git a/iguana/exchanges/LP_ordermatch.c b/iguana/exchanges/LP_ordermatch.c new file mode 100644 index 000000000..9153fb449 --- /dev/null +++ b/iguana/exchanges/LP_ordermatch.c @@ -0,0 +1,690 @@ + +/****************************************************************************** + * 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_ordermatch.c +// marketmaker +// + + +struct basilisk_request *LP_requestinit(struct basilisk_request *rp,bits256 srchash,bits256 desthash,char *src,uint64_t srcsatoshis,char *dest,uint64_t destsatoshis,uint32_t timestamp,uint32_t quotetime,int32_t DEXselector) +{ + struct basilisk_request R; + memset(rp,0,sizeof(*rp)); + rp->srchash = srchash; + rp->srcamount = srcsatoshis; + rp->timestamp = timestamp; + rp->DEXselector = DEXselector; + safecopy(rp->src,src,sizeof(rp->src)); + safecopy(rp->dest,dest,sizeof(rp->dest)); + R = *rp; + rp->requestid = basilisk_requestid(rp); + rp->quotetime = quotetime; + rp->desthash = desthash; + rp->destamount = destsatoshis; + rp->quoteid = basilisk_quoteid(rp); + printf("r.%u %u, q.%u %u: %s %.8f -> %s %.8f\n",rp->timestamp,rp->requestid,rp->quotetime,rp->quoteid,rp->src,dstr(rp->srcamount),rp->dest,dstr(rp->destamount)); + return(rp); +} + +cJSON *LP_quotejson(struct LP_quoteinfo *qp) +{ + double price; cJSON *retjson = cJSON_CreateObject(); + jaddstr(retjson,"base",qp->srccoin); + jaddstr(retjson,"rel",qp->destcoin); + if ( qp->coinaddr[0] != 0 ) + jaddstr(retjson,"address",qp->coinaddr); + if ( qp->timestamp != 0 ) + jaddnum(retjson,"timestamp",qp->timestamp); + if ( bits256_nonz(qp->txid) != 0 ) + { + jaddbits256(retjson,"txid",qp->txid); + jaddnum(retjson,"vout",qp->vout); + } + if ( bits256_nonz(qp->srchash) != 0 ) + jaddbits256(retjson,"srchash",qp->srchash); + if ( qp->txfee != 0 ) + jadd64bits(retjson,"txfee",qp->txfee); + if ( qp->quotetime != 0 ) + jaddnum(retjson,"quotetime",qp->quotetime); + if ( qp->satoshis != 0 ) + jadd64bits(retjson,"satoshis",qp->satoshis); + if ( bits256_nonz(qp->desthash) != 0 ) + jaddbits256(retjson,"desthash",qp->desthash); + if ( bits256_nonz(qp->txid2) != 0 ) + { + jaddbits256(retjson,"txid2",qp->txid2); + jaddnum(retjson,"vout2",qp->vout2); + } + if ( bits256_nonz(qp->desttxid) != 0 ) + { + if ( qp->destaddr[0] != 0 ) + jaddstr(retjson,"destaddr",qp->destaddr); + jaddbits256(retjson,"desttxid",qp->desttxid); + jaddnum(retjson,"destvout",qp->destvout); + } + if ( bits256_nonz(qp->feetxid) != 0 ) + { + jaddbits256(retjson,"feetxid",qp->feetxid); + jaddnum(retjson,"feevout",qp->feevout); + } + if ( qp->desttxfee != 0 ) + jadd64bits(retjson,"desttxfee",qp->desttxfee); + if ( qp->destsatoshis != 0 ) + { + jadd64bits(retjson,"destsatoshis",qp->destsatoshis); + if ( qp->satoshis != 0 ) + { + price = (double)qp->destsatoshis / qp->satoshis; + jaddnum(retjson,"price",price); + } + } + return(retjson); +} + +int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson) +{ + safecopy(qp->srccoin,jstr(argjson,"base"),sizeof(qp->srccoin)); + safecopy(qp->coinaddr,jstr(argjson,"address"),sizeof(qp->coinaddr)); + safecopy(qp->destcoin,jstr(argjson,"rel"),sizeof(qp->destcoin)); + safecopy(qp->destaddr,jstr(argjson,"destaddr"),sizeof(qp->destaddr)); + qp->timestamp = juint(argjson,"timestamp"); + qp->quotetime = juint(argjson,"quotetime"); + qp->txid = jbits256(argjson,"txid"); + qp->txid2 = jbits256(argjson,"txid2"); + qp->vout = jint(argjson,"vout"); + qp->vout2 = jint(argjson,"vout2"); + qp->feevout = jint(argjson,"feevout"); + qp->srchash = jbits256(argjson,"srchash"); + qp->desttxid = jbits256(argjson,"desttxid"); + qp->feetxid = jbits256(argjson,"feetxid"); + qp->destvout = jint(argjson,"destvout"); + qp->desthash = jbits256(argjson,"desthash"); + qp->satoshis = j64bits(argjson,"satoshis"); + qp->destsatoshis = j64bits(argjson,"destsatoshis"); + qp->txfee = j64bits(argjson,"txfee"); + qp->desttxfee = j64bits(argjson,"desttxfee"); + return(0); +} + +int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char *destcoin,double price,uint64_t destsatoshis) +{ + memset(qp,0,sizeof(*qp)); + if ( qp->timestamp == 0 ) + qp->timestamp = (uint32_t)time(NULL); + safecopy(qp->destcoin,destcoin,sizeof(qp->destcoin)); + if ( (qp->txfee= LP_getestimatedrate(utxo->coin)*LP_AVETXSIZE) < LP_MIN_TXFEE ) + qp->txfee = LP_MIN_TXFEE; + qp->satoshis = destsatoshis / price + 0.49; + if ( utxo->iambob == 0 || qp->txfee >= qp->satoshis || qp->txfee >= utxo->deposit.value || utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis) ) + { + printf("quoteinit error.(%d %d %d %d) %.8f vs %.8f\n",utxo->iambob == 0,qp->txfee >= qp->satoshis,qp->txfee >= utxo->deposit.value,utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis),dstr(utxo->deposit.value),dstr(LP_DEPOSITSATOSHIS(qp->satoshis))); + return(-1); + } + qp->txid = utxo->payment.txid; + qp->vout = utxo->payment.vout; + qp->txid2 = utxo->deposit.txid; + qp->vout2 = utxo->deposit.vout; + qp->destsatoshis = destsatoshis; + if ( (qp->desttxfee= LP_getestimatedrate(qp->destcoin) * LP_AVETXSIZE) < LP_MIN_TXFEE ) + qp->desttxfee = LP_MIN_TXFEE; + if ( qp->desttxfee >= qp->destsatoshis ) + { + printf("quoteinit desttxfee %.8f < %.8f destsatoshis\n",dstr(qp->desttxfee),dstr(qp->destsatoshis)); + return(-2); + } + safecopy(qp->srccoin,utxo->coin,sizeof(qp->srccoin)); + safecopy(qp->coinaddr,utxo->coinaddr,sizeof(qp->coinaddr)); + qp->srchash = utxo->pubkey; + return(0); +} + +int32_t LP_quotedestinfo(struct LP_quoteinfo *qp,bits256 desttxid,int32_t destvout,bits256 feetxid,int32_t feevout,bits256 desthash,char *destaddr) +{ + qp->desttxid = desttxid; + qp->destvout = destvout; + qp->desthash = desthash; + qp->feetxid = feetxid; + qp->feevout = feevout; + safecopy(qp->destaddr,destaddr,sizeof(qp->destaddr)); + return(0); +} + +char *LP_quotereceived(cJSON *argjson) +{ + struct LP_cacheinfo *ptr; double price; struct LP_quoteinfo Q; + LP_quoteparse(&Q,argjson); + price = (double)(Q.destsatoshis + Q.desttxfee) / (Q.satoshis + Q.txfee); + if ( (ptr= LP_cacheadd(Q.srccoin,Q.destcoin,Q.txid,Q.vout,price,&Q)) != 0 ) + { + ptr->Q = Q; + printf(">>>>>>>>>> received quote %s/%s %.8f\n",Q.srccoin,Q.destcoin,price); + return(clonestr("{\"result\":\"updated\"}")); + } else return(clonestr("{\"error\":\"nullptr\"}")); +} + +char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,char *base,char *rel,double price) +{ + bits256 zero; char *msg; cJSON *reqjson = cJSON_CreateObject(); + jaddbits256(reqjson,"pubkey",LP_mypubkey); + jaddstr(reqjson,"base",base); + jaddstr(reqjson,"rel",rel); + jaddnum(reqjson,"price",price); + if ( pubsock >= 0 ) + { + jaddstr(reqjson,"method","postprice"); + //printf("%d pricepings.(%s)\n",pubsock,jprint(reqjson,0)); + msg = jprint(reqjson,1); + LP_send(pubsock,msg,(int32_t)strlen(msg)+1,1); + } + else + { + jaddstr(reqjson,"method","forward"); + jaddstr(reqjson,"method2","postprice"); + memset(zero.bytes,0,sizeof(zero)); + LP_forward(ctx,myipaddr,pubsock,profitmargin,zero,jprint(reqjson,1),1); + } + return(clonestr("{\"result\":\"success\"}")); +} + +char *LP_postedprice(cJSON *argjson) +{ + bits256 pubkey; double price; char *base,*rel; + //printf("PRICE POSTED.(%s)\n",jprint(argjson,0)); + if ( (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 && (price= jdouble(argjson,"price")) > SMALLVAL ) + { + pubkey = jbits256(argjson,"pubkey"); + if ( bits256_nonz(pubkey) != 0 ) + { + LP_pricefeedupdate(pubkey,base,rel,price); + return(clonestr("{\"result\":\"success\"}")); + } + } + return(clonestr("{\"error\":\"missing fields in posted price\"}")); +} + +int32_t LP_quote_checkmempool(struct LP_quoteinfo *qp) +{ + int32_t selector,spendvini; bits256 spendtxid; + if ( (selector= LP_mempool_vinscan(&spendtxid,&spendvini,qp->srccoin,qp->txid,qp->vout,qp->txid2,qp->vout2)) >= 0 ) + { + char str[65]; printf("LP_tradecommand selector.%d in mempool %s vini.%d",selector,bits256_str(str,spendtxid),spendvini); + return(-1); + } + if ( (selector= LP_mempool_vinscan(&spendtxid,&spendvini,qp->destcoin,qp->desttxid,qp->destvout,qp->feetxid,qp->feevout)) >= 0 ) + { + char str[65]; printf("LP_tradecommand dest selector.%d in mempool %s vini.%d",selector,bits256_str(str,spendtxid),spendvini); + return(-1); + } + return(0); +} + +double LP_quote_validate(struct LP_utxoinfo **autxop,struct LP_utxoinfo **butxop,struct LP_quoteinfo *qp,int32_t iambob) +{ + double qprice; uint64_t srcvalue,srcvalue2,destvalue,destvalue2; + *autxop = *butxop = 0; + if ( LP_iseligible(&srcvalue,&srcvalue2,1,qp->srccoin,qp->txid,qp->vout,qp->satoshis,qp->txid2,qp->vout2,qp->srchash) == 0 ) + { + printf("bob not eligible\n"); + return(-2); + } + if ( LP_iseligible(&destvalue,&destvalue2,0,qp->destcoin,qp->desttxid,qp->destvout,qp->destsatoshis,qp->feetxid,qp->feevout,qp->desthash) == 0 ) + { + char str[65]; printf("alice not eligible (%.8f %.8f) %s/v%d\n",dstr(destvalue),dstr(destvalue2),bits256_str(str,qp->feetxid),qp->feevout); + return(-3); + } + if ( LP_quote_checkmempool(qp) < 0 ) + return(-4); + if ( (*butxop= LP_utxofind(1,qp->txid,qp->vout)) == 0 ) + return(-5); + if ( bits256_cmp((*butxop)->deposit.txid,qp->txid2) != 0 || (*butxop)->deposit.vout != qp->vout2 ) + return(-6); + if ( strcmp((*butxop)->coinaddr,qp->coinaddr) != 0 ) + return(-7); + if ( iambob == 0 ) + { + if ( (*autxop= LP_utxofind(0,qp->desttxid,qp->destvout)) == 0 ) + return(-8); + if ( bits256_cmp((*autxop)->fee.txid,qp->feetxid) != 0 || (*autxop)->fee.vout != qp->feevout ) + return(-9); + if ( strcmp((*autxop)->coinaddr,qp->destaddr) != 0 ) + return(-10); + } + if ( destvalue < qp->desttxfee+qp->destsatoshis || srcvalue < qp->txfee+qp->satoshis ) + { + printf("destvalue %.8f srcvalue %.8f, destsatoshis %.8f or satoshis %.8f is too small txfees %.8f %.8f?\n",dstr(destvalue),dstr(srcvalue),dstr(qp->destsatoshis),dstr(qp->satoshis),dstr(qp->desttxfee),dstr(qp->txfee)); + return(-11); + } + qprice = ((double)qp->destsatoshis / qp->satoshis); + if ( qp->satoshis < (srcvalue >> LP_MINVOL) ) + { + printf("utxo payment %.8f is less than half covered by Q %.8f\n",dstr(srcvalue),dstr(qp->satoshis)); + return(-12); + } + if ( qp->destsatoshis < (destvalue >> LP_MINCLIENTVOL) ) + { + printf("destsatoshis %.8f is less than half of value %.8f\n",dstr(qp->destsatoshis),dstr(destvalue)); + return(-13); + } + printf("qprice %.8f <- %.8f/%.8f txfees.(%.8f %.8f)\n",qprice,dstr(qp->destsatoshis),dstr(qp->satoshis),dstr(qp->txfee),dstr(qp->desttxfee)); + return(qprice); +} + +int32_t LP_arrayfind(cJSON *array,bits256 txid,int32_t vout) +{ + int32_t i,n = cJSON_GetArraySize(array); cJSON *item; + for (i=0; idesttxid,qp->destvout)) != 0 && LP_ismine(utxo) > 0 && LP_isavailable(utxo) > 0 ) + LP_unavailableset(utxo,qp->srchash); + else + { + printf("couldnt find my txid to make request\n"); + return(0.); + } + } + reqjson = LP_quotejson(qp); + if ( bits256_nonz(qp->desthash) != 0 ) + flag = 1; + //printf("QUERY.(%s)\n",jprint(reqjson,0)); + if ( IAMLP != 0 ) + { + jaddstr(reqjson,"method",method); + msg = jprint(reqjson,1); + LP_send(LP_mypubsock,msg,(int32_t)strlen(msg)+1,1); + } + else + { + jaddstr(reqjson,"method2",method); + jaddstr(reqjson,"method","forward"); + jaddbits256(reqjson,"pubkey",qp->srchash); + LP_forward(ctx,myipaddr,mypubsock,profitmargin,qp->srchash,jprint(reqjson,1),1); + } + for (i=0; i<30; i++) + { + if ( (price= LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout)) > SMALLVAL ) + { + if ( flag == 0 || bits256_nonz(qp->desthash) != 0 ) + { + //printf("break out of loop.%d price %.8f\n",i,price); + break; + } + } + usleep(100000); + } + return(price); +} + +int32_t LP_nanobind(void *ctx,char *pairstr) +{ + int32_t i,timeout,r,pairsock = -1; uint16_t mypullport; char bindaddr[128]; + if ( LP_canbind != 0 ) + { + if ( (pairsock= nn_socket(AF_SP,NN_PAIR)) < 0 ) + printf("error creating utxo->pair\n"); + else + { + for (i=0; i<10; i++) + { + r = (10000 + (rand() % 50000)) & 0xffff; + if ( LP_fixed_pairport != 0 ) + r = LP_fixed_pairport; + nanomsg_transportname(0,pairstr,LP_myipaddr,r); + nanomsg_transportname(1,bindaddr,LP_myipaddr,r); + if ( nn_bind(pairsock,bindaddr) >= 0 ) + { + timeout = 100; + nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); + nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); + printf("nanobind %s to %d\n",pairstr,pairsock); + return(pairsock); + } else printf("error binding to %s for %s\n",bindaddr,pairstr); + if ( LP_fixed_pairport != 0 ) + break; + } + } + } else pairsock = LP_initpublicaddr(ctx,&mypullport,pairstr,"127.0.0.1",0,1); + return(pairsock); +} + +int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJSON *argjson,char *myipaddr,char *base,char *rel,double profitmargin,double price,struct LP_quoteinfo *qp) +{ + char pairstr[512],*msg; cJSON *retjson; bits256 privkey; int32_t pair=-1,retval = -1,DEXselector = 0; struct basilisk_swap *swap; struct iguana_info *coin; + printf("LP_connectstartbob.(%s) with.(%s) %s\n",myipaddr,jprint(argjson,0),LP_myipaddr); + qp->quotetime = (uint32_t)time(NULL); + if ( (coin= LP_coinfind(utxo->coin)) == 0 ) + { + printf("cant find coin.%s\n",utxo->coin); + return(-1); + } + privkey = LP_privkey(utxo->coinaddr,coin->taddr); + if ( bits256_nonz(privkey) != 0 && qp->quotetime >= qp->timestamp-3 && qp->quotetime <= utxo->T.swappending && bits256_cmp(LP_mypubkey,qp->srchash) == 0 ) + { + if ( (pair= LP_nanobind(ctx,pairstr)) >= 0 ) + { + LP_requestinit(&qp->R,qp->srchash,qp->desthash,base,qp->satoshis,rel,qp->destsatoshis,qp->timestamp,qp->quotetime,DEXselector); + swap = LP_swapinit(1,0,privkey,&qp->R,qp); + swap->N.pair = pair; + utxo->S.swap = swap; + swap->utxo = utxo; + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_bobloop,(void *)swap) == 0 ) + { + retjson = LP_quotejson(qp); + jaddstr(retjson,"method","connected"); + jaddstr(retjson,"pair",pairstr); + jaddnum(retjson,"requestid",qp->R.requestid); + jaddnum(retjson,"quoteid",qp->R.quoteid); + char str[65]; printf("BOB pubsock.%d sends to (%s)\n",pubsock,bits256_str(str,utxo->S.otherpubkey)); + if ( pubsock >= 0 ) + { + msg = jprint(retjson,0); + LP_send(pubsock,msg,(int32_t)strlen(msg)+1,1); + } + jdelete(retjson,"method"); + jaddstr(retjson,"method2","connected"); + jaddstr(retjson,"method","forward"); + LP_forward(ctx,myipaddr,pubsock,profitmargin,utxo->S.otherpubkey,jprint(retjson,1),1); + retval = 0; + } else printf("error launching swaploop\n"); + } else printf("couldnt bind to any port %s\n",pairstr); + } + else + { + printf("dest %.8f vs required %.8f (%d %d %d %d %d)\n",dstr(qp->destsatoshis),dstr(price*(utxo->S.satoshis-qp->txfee)),bits256_nonz(privkey) != 0 ,qp->timestamp == utxo->T.swappending-LP_RESERVETIME,qp->quotetime >= qp->timestamp-3,qp->quotetime < utxo->T.swappending,bits256_cmp(LP_mypubkey,qp->srchash) == 0); + } + if ( retval < 0 ) + { + if ( pair >= 0 ) + nn_close(pair); + LP_availableset(utxo); + } else LP_unavailableset(utxo,utxo->S.otherpubkey); + return(retval); +} + +char *LP_connectedalice(cJSON *argjson) // alice +{ + cJSON *retjson; double bid,ask,price,qprice; int32_t timeout,pairsock = -1; char *pairstr; int32_t DEXselector = 0; struct LP_utxoinfo *autxo,*butxo; struct LP_quoteinfo Q; struct basilisk_swap *swap; struct iguana_info *coin; + if ( LP_quoteparse(&Q,argjson) < 0 ) + clonestr("{\"error\":\"cant parse quote\"}"); + if ( bits256_cmp(Q.desthash,LP_mypubkey) != 0 ) + return(clonestr("{\"result\",\"update stats\"}")); + printf("CONNECTED.(%s)\n",jprint(argjson,0)); + if ( (qprice= LP_quote_validate(&autxo,&butxo,&Q,0)) <= SMALLVAL ) + { + LP_availableset(autxo); + printf("quote validate error %.0f\n",qprice); + return(clonestr("{\"error\":\"quote validation error\"}")); + } + if ( (price= LP_myprice(&bid,&ask,Q.destcoin,Q.srccoin)) <= SMALLVAL || ask <= SMALLVAL ) + { + printf("this node has no price for %s/%s (%.8f %.8f)\n",Q.destcoin,Q.srccoin,bid,ask); + LP_availableset(autxo); + return(clonestr("{\"error\":\"no price set\"}")); + } + price = 1. / ask; + if ( qprice > price+0.00000001 ) + { + printf("qprice %.8f too big vs %.8f\n",qprice,price); + LP_availableset(autxo); + return(clonestr("{\"error\":\"quote price too expensive\"}")); + } + if ( (coin= LP_coinfind(Q.destcoin)) == 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 ) + { + retjson = cJSON_CreateObject(); + if ( (pairstr= jstr(argjson,"pair")) == 0 || (pairsock= nn_socket(AF_SP,NN_PAIR)) < 0 ) + jaddstr(retjson,"error","couldnt create pairsock"); + else if ( nn_connect(pairsock,pairstr) >= 0 ) + { + timeout = 100; + nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); + nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); + LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis,Q.destcoin,Q.destsatoshis,Q.timestamp,Q.quotetime,DEXselector); + swap = LP_swapinit(0,0,Q.privkey,&Q.R,&Q); + swap->N.pair = pairsock; + autxo->S.swap = swap; + swap->utxo = autxo; + printf("alice pairstr.(%s) pairsock.%d\n",pairstr,pairsock); + if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_aliceloop,(void *)swap) == 0 ) + { + jaddstr(retjson,"result","success"); + jadd(retjson,"trade",LP_quotejson(&Q)); + jaddnum(retjson,"requestid",Q.R.requestid); + jaddnum(retjson,"quoteid",Q.R.quoteid); + } else jaddstr(retjson,"error","couldnt aliceloop"); + } else printf("connect error %s\n",nn_strerror(nn_errno())); + printf("connected result.(%s)\n",jprint(retjson,0)); + if ( jobj(retjson,"error") != 0 ) + LP_availableset(autxo); + return(jprint(retjson,1)); + } + else + { + LP_availableset(autxo); + printf("no privkey found\n"); + return(clonestr("{\"error\",\"no privkey\"}")); + } +} + +int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin) +{ + char *method,*msg; cJSON *retjson; double qprice,price,bid,ask; struct LP_utxoinfo *autxo,*butxo; int32_t retval = -1; struct LP_quoteinfo Q; + if ( (method= jstr(argjson,"method")) != 0 && (strcmp(method,"request") == 0 ||strcmp(method,"connect") == 0) ) + { + //printf("TRADECOMMAND.(%s)\n",jprint(argjson,0)); + retval = 1; + if ( LP_quoteparse(&Q,argjson) == 0 && bits256_cmp(LP_mypubkey,Q.srchash) == 0 ) + { + if ( (price= LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin)) <= SMALLVAL || ask <= SMALLVAL ) + { + printf("this node has no price for %s/%s\n",Q.srccoin,Q.destcoin); + return(-3); + } + price = ask; + if ( (qprice= LP_quote_validate(&autxo,&butxo,&Q,1)) <= SMALLVAL ) + { + printf("quote validate error %.0f\n",qprice); + return(-4); + } + if ( qprice < price-0.00000001 ) + { + printf("(%.8f %.8f) quote price %.8f too low vs %.8f for %s/%s\n",bid,ask,qprice,price,Q.srccoin,Q.destcoin); + return(-5); + } + if ( butxo->S.swap == 0 && time(NULL) > butxo->T.swappending ) + butxo->T.swappending = 0; + if ( strcmp(method,"request") == 0 ) // bob needs apayment + fee tx's + { + if ( LP_isavailable(butxo) > 0 ) + { + butxo->T.swappending = Q.timestamp + LP_RESERVETIME; + retjson = LP_quotejson(&Q); + butxo->S.otherpubkey = jbits256(argjson,"desthash"); + LP_unavailableset(butxo,butxo->S.otherpubkey); + jaddnum(retjson,"quotetime",juint(argjson,"quotetime")); + jaddnum(retjson,"pending",butxo->T.swappending); + jaddbits256(retjson,"desthash",butxo->S.otherpubkey); + jaddbits256(retjson,"pubkey",butxo->S.otherpubkey); + jaddstr(retjson,"method","reserved"); + if ( pubsock >= 0 ) + { + msg = jprint(retjson,0); + LP_send(pubsock,msg,(int32_t)strlen(msg)+1,1); + } + jdelete(retjson,"method"); + jaddstr(retjson,"method2","reserved"); + jaddstr(retjson,"method","forward"); + LP_forward(ctx,myipaddr,pubsock,profitmargin,butxo->S.otherpubkey,jprint(retjson,1),1); + butxo->T.lasttime = (uint32_t)time(NULL); + printf("set swappending.%u accept qprice %.8f, min %.8f\n",butxo->T.swappending,qprice,price); + } else printf("warning swappending.%u swap.%p\n",butxo->T.swappending,butxo->S.swap); + } + else if ( strcmp(method,"connect") == 0 ) // bob + { + retval = 4; + if ( butxo->T.swappending != 0 && butxo->S.swap == 0 ) + LP_connectstartbob(ctx,pubsock,butxo,argjson,myipaddr,Q.srccoin,Q.destcoin,profitmargin,qprice,&Q); + else printf("pend.%u swap %p when connect came in (%s)\n",butxo->T.swappending,butxo->S.swap,jprint(argjson,0)); + } + } + } + return(retval); +} + +char *LP_autotrade(void *ctx,char *myipaddr,int32_t mypubsock,double profitmargin,char *base,char *rel,double maxprice,double volume,int32_t timeout) +{ + int64_t satoshis,destsatoshis,desttxfee,txfee,bestdestsatoshis=0; bits256 txid,pubkey; char *obookstr,*retstr; cJSON *orderbook,*asks,*item,*bestitem=0; struct LP_utxoinfo *autxo,*butxo,*bestutxo = 0; int32_t i,vout,numasks,DEXselector=0; uint32_t expiration; double ordermatchprice,bestmetric,metric,bestprice=0.,vol,price; struct LP_quoteinfo Q; struct LP_pubkeyinfo *pubp; + if ( maxprice <= 0. || volume <= 0. || LP_priceinfofind(base) == 0 || LP_priceinfofind(rel) == 0 ) + return(clonestr("{\"error\":\"invalid parameter\"}")); + if ( (autxo= LP_utxo_bestfit(rel,SATOSHIDEN * volume)) == 0 ) + return(clonestr("{\"error\":\"cant find utxo that is big enough\"}")); + bestmetric = ordermatchprice = 0.; + if ( (desttxfee= LP_getestimatedrate(rel) * LP_AVETXSIZE) < LP_MIN_TXFEE ) + desttxfee = LP_MIN_TXFEE; + if ( (txfee= LP_getestimatedrate(base) * LP_AVETXSIZE) < LP_MIN_TXFEE ) + txfee = LP_MIN_TXFEE; + if ( timeout == 0 ) + timeout = LP_AUTOTRADE_TIMEOUT; + if ( (obookstr= LP_orderbook(base,rel)) != 0 ) + { + if ( (orderbook= cJSON_Parse(obookstr)) != 0 ) + { + if ( (asks= jarray(&numasks,orderbook,"asks")) != 0 ) + { + for (i=0; i SMALLVAL && price <= maxprice ) + { + price *= 1.0001; + if ( price > maxprice ) + price = maxprice; + pubkey = jbits256(item,"pubkey"); + if ( bits256_cmp(pubkey,LP_mypubkey) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 && pubp->numerrors < LP_MAXPUBKEY_ERRORS ) + { + if ( bestprice == 0. ) // assumes price ordered asks + bestprice = price; + //printf("item.[%d] %s\n",i,jprint(item,0)); + txid = jbits256(item,"txid"); + vout = jint(item,"vout"); + vol = jdouble(item,"volume"); + metric = price / bestprice; + if ( (butxo= LP_utxofind(1,txid,vout)) != 0 && (long long)(vol*SATOSHIDEN) == butxo->S.satoshis && LP_isavailable(butxo) > 0 && LP_ismine(butxo) == 0 && butxo->T.bestflag == 0 ) + { + destsatoshis = ((butxo->S.satoshis - txfee) * price); + if ( destsatoshis > autxo->payment.value-desttxfee-1 ) + destsatoshis = autxo->payment.value-desttxfee-1; + satoshis = (destsatoshis / price + 0.0000000049) - txfee; + if ( metric < 1.2 && destsatoshis > desttxfee && destsatoshis-desttxfee > (autxo->payment.value >> LP_MINCLIENTVOL) && satoshis-txfee > (butxo->S.satoshis >> LP_MINVOL) && satoshis <= butxo->payment.value-txfee ) + { + printf("value %.8f price %.8f/%.8f best %.8f destsatoshis %.8f * metric %.8f -> (%f)\n",dstr(autxo->payment.value),price,bestprice,bestmetric,dstr(destsatoshis),metric,dstr(destsatoshis) * metric * metric * metric); + metric = dstr(destsatoshis) * metric * metric * metric; + if ( bestmetric == 0. || metric < bestmetric ) + { + bestutxo = butxo; + ordermatchprice = price; + bestdestsatoshis = destsatoshis; + bestmetric = metric; + printf("set best!\n"); + } + } else printf("skip.(%d %d %d %d %d) metric %f destsatoshis %.8f value %.8f destvalue %.8f txfees %.8f %.8f sats %.8f\n",metric < 1.2,destsatoshis > desttxfee,destsatoshis-desttxfee > (autxo->payment.value >> LP_MINCLIENTVOL),satoshis-txfee > (butxo->S.satoshis >> LP_MINVOL),satoshis < butxo->payment.value-txfee,metric,dstr(destsatoshis),dstr(butxo->S.satoshis),dstr(autxo->payment.value),dstr(txfee),dstr(desttxfee),dstr(satoshis)); + } + else + { + if ( butxo != 0 ) + printf("%llu %llu %d %d %d: ",(long long)(vol*SATOSHIDEN),(long long)butxo->S.satoshis,vol*SATOSHIDEN == butxo->S.satoshis,LP_isavailable(butxo) > 0,LP_ismine(butxo) == 0); + printf("cant find butxo.%p or value mismatch %.8f != %.8f\n",butxo,vol,butxo!=0?dstr(butxo->S.satoshis):0); + } + } + } else break; + } + } + free_json(orderbook); + } + free(obookstr); + } + if ( bestutxo == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) + return(clonestr("{\"error\":\"cant find ordermatch utxo\"}")); + if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestdestsatoshis) < 0 ) + return(clonestr("{\"error\":\"cant set ordermatch quote\"}")); + if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,LP_mypubkey,autxo->coinaddr) < 0 ) + return(clonestr("{\"error\":\"cant set ordermatch quote info\"}")); + bestutxo->T.bestflag = (uint32_t)time(NULL); + if ( (retstr= LP_registerall(0)) != 0 ) + free(retstr); + price = LP_query(ctx,myipaddr,mypubsock,profitmargin,"request",&Q); + bestitem = LP_quotejson(&Q); + if ( price > SMALLVAL ) + { + if ( price <= maxprice ) + { + price = LP_query(ctx,myipaddr,mypubsock,profitmargin,"connect",&Q); + LP_requestinit(&Q.R,Q.srchash,Q.desthash,base,Q.satoshis,Q.destcoin,Q.destsatoshis,Q.timestamp,Q.quotetime,DEXselector); + expiration = (uint32_t)time(NULL) + timeout; + while ( time(NULL) < expiration ) + { + if ( autxo->S.swap != 0 ) + break; + sleep(1); + } + if ( autxo->S.swap == 0 ) + { + if ( (pubp= LP_pubkeyadd(bestutxo->pubkey)) != 0 ) + pubp->numerrors++; + jaddstr(bestitem,"status","couldnt establish connection"); + } else jaddstr(bestitem,"status","connected"); + jaddnum(bestitem,"quotedprice",price); + jaddnum(bestitem,"maxprice",maxprice); + jaddnum(bestitem,"requestid",Q.R.requestid); + jaddnum(bestitem,"quoteid",Q.R.quoteid); + printf("Alice r.%u q.%u\n",Q.R.requestid,Q.R.quoteid); + } + else + { + jaddnum(bestitem,"quotedprice",price); + jaddnum(bestitem,"maxprice",maxprice); + jaddstr(bestitem,"status","too expensive"); + } + } + else + { + jaddnum(bestitem,"maxprice",maxprice); + jaddstr(bestitem,"status","no response to request"); + } + if ( autxo->S.swap == 0 ) + LP_availableset(autxo); + return(jprint(bestitem,0)); +} + + + + diff --git a/iguana/exchanges/LP_peers.c b/iguana/exchanges/LP_peers.c index e7d83a93e..95c708348 100644 --- a/iguana/exchanges/LP_peers.c +++ b/iguana/exchanges/LP_peers.c @@ -42,21 +42,22 @@ char *LP_peers() struct LP_peerinfo *peer,*tmp; cJSON *peersjson = cJSON_CreateArray(); HASH_ITER(hh,LP_peerinfos,peer,tmp) { - jaddi(peersjson,LP_peerjson(peer)); + //if ( peer->errors < LP_MAXPEER_ERRORS ) + jaddi(peersjson,LP_peerjson(peer)); } return(jprint(peersjson,1)); } -struct LP_peerinfo *LP_addpeer(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *ipaddr,uint16_t port,uint16_t pushport,uint16_t subport,double profitmargin,int32_t numpeers,int32_t numutxos) +struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char *ipaddr,uint16_t port,uint16_t pushport,uint16_t subport,double profitmargin,int32_t numpeers,int32_t numutxos) { - uint32_t ipbits; int32_t pushsock,subsock,timeout,enabled; char checkip[64],pushaddr[64],subaddr[64]; struct LP_peerinfo *peer = 0; + uint32_t ipbits; int32_t maxsize,pushsock,subsock,timeout; char checkip[64],pushaddr[64],subaddr[64]; struct LP_peerinfo *peer = 0; ipbits = (uint32_t)calc_ipbits(ipaddr); expand_ipbits(checkip,ipbits); if ( strcmp(checkip,ipaddr) == 0 ) { if ( (peer= LP_peerfind(ipbits,port)) != 0 ) { - if ( peer->profitmargin == 0. ) + if ( profitmargin != 0. ) peer->profitmargin = profitmargin; if ( numpeers > peer->numpeers ) peer->numpeers = numpeers; @@ -65,34 +66,32 @@ struct LP_peerinfo *LP_addpeer(int32_t amclient,struct LP_peerinfo *mypeer,int32 } else { - //printf("LPaddpeer %s\n",ipaddr); + printf("LPaddpeer %s\n",ipaddr); peer = calloc(1,sizeof(*peer)); peer->pushsock = peer->subsock = pushsock = subsock = -1; strcpy(peer->ipaddr,ipaddr); - if ( amclient == 0 ) - enabled = 1; - else enabled = 1;//(rand() % (1 << Client_connections)) == 0; if ( pushport != 0 && subport != 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 ) { - timeout = 1000; - nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); - nanomsg_tcpname(pushaddr,peer->ipaddr,pushport); + nanomsg_transportname(0,pushaddr,peer->ipaddr,pushport); if ( nn_connect(pushsock,pushaddr) >= 0 ) { + timeout = 100; + nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); + maxsize = 2 * 1024 * 1024; + nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDBUF,&maxsize,sizeof(maxsize)); printf("connected to push.(%s) %d\n",pushaddr,pushsock); peer->connected = (uint32_t)time(NULL); peer->pushsock = pushsock; - if ( enabled != 0 && (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 ) + if ( (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 ) { timeout = 1; nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); nn_setsockopt(subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); - nanomsg_tcpname(subaddr,peer->ipaddr,subport); + nanomsg_transportname(0,subaddr,peer->ipaddr,subport); if ( nn_connect(subsock,subaddr) >= 0 ) { peer->subsock = subsock; printf("connected to sub.(%s) %d\n",subaddr,peer->subsock); - Client_connections += amclient; } else nn_close(subsock); } } @@ -115,13 +114,16 @@ struct LP_peerinfo *LP_addpeer(int32_t amclient,struct LP_peerinfo *mypeer,int32 } else peer->numpeers = 1; // will become mypeer portable_mutex_unlock(&LP_peermutex); if ( mypubsock >= 0 ) - LP_send(mypubsock,jprint(LP_peerjson(peer),1),1); + { + char *msg = jprint(LP_peerjson(peer),1); + LP_send(mypubsock,msg,(int32_t)strlen(msg)+1,1); + } } } else printf("LP_addpeer: checkip.(%s) vs (%s)\n",checkip,ipaddr); return(peer); } -int32_t LP_peersparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now) +int32_t LP_peersparse(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now) { struct LP_peerinfo *peer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; if ( (array= cJSON_Parse(retstr)) != 0 ) @@ -140,7 +142,7 @@ int32_t LP_peersparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubs argipbits = (uint32_t)calc_ipbits(argipaddr); if ( (peer= LP_peerfind(argipbits,argport)) == 0 ) { - peer = LP_addpeer(amclient,mypeer,mypubsock,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos")); + peer = LP_addpeer(mypeer,mypubsock,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos")); } if ( peer != 0 ) { @@ -156,19 +158,17 @@ int32_t LP_peersparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubs return(n); } -void LP_peersquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *myipaddr,uint16_t myport,double myprofit) +void LP_peersquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *myipaddr,uint16_t myport,double myprofit) { char *retstr; struct LP_peerinfo *peer,*tmp; uint32_t now,flag = 0; peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); - if ( peer != 0 && peer->errors > 0 ) - return; if ( (retstr= issue_LP_getpeers(destipaddr,destport,myipaddr,myport,myprofit,mypeer!=0?mypeer->numpeers:0,mypeer!=0?mypeer->numutxos:0)) != 0 ) { //printf("got.(%s)\n",retstr); now = (uint32_t)time(NULL); - LP_peersparse(amclient,mypeer,mypubsock,destipaddr,destport,retstr,now); + LP_peersparse(mypeer,mypubsock,destipaddr,destport,retstr,now); free(retstr); - if ( amclient == 0 ) + if ( IAMLP != 0 ) { HASH_ITER(hh,LP_peerinfos,peer,tmp) { @@ -183,6 +183,15 @@ void LP_peersquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock if ( flag != 0 ) printf(" <- missing peers\n"); } - } else if ( peer != 0 ) - peer->errors++; + } +} + +int32_t LP_numpeers() +{ + struct LP_peerinfo *peer,*tmp; int32_t numpeers = 0; + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + numpeers++; + } + return(numpeers); } diff --git a/iguana/exchanges/LP_prices.c b/iguana/exchanges/LP_prices.c index 11fe76813..eaf3db19a 100644 --- a/iguana/exchanges/LP_prices.c +++ b/iguana/exchanges/LP_prices.c @@ -18,7 +18,9 @@ // marketmaker // -#define LP_MAXPRICEINFOS 64 +struct LP_orderbookentry { bits256 txid,txid2,pubkey; double price; uint64_t basesatoshis; int32_t vout,vout2; }; + +#define LP_MAXPRICEINFOS 256 struct LP_priceinfo { char symbol[16]; @@ -39,6 +41,45 @@ struct LP_cacheinfo uint32_t timestamp; } *LP_cacheinfos; +struct LP_pubkeyinfo +{ + UT_hash_handle hh; + bits256 pubkey; + double matrix[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS]; + uint32_t timestamp,istrusted,numerrors; +} *LP_pubkeyinfos; + +struct LP_priceinfo *LP_priceinfofind(char *symbol) +{ + int32_t i; struct LP_priceinfo *pp; uint64_t coinbits; + if ( symbol == 0 || symbol[0] == 0 ) + return(0); + if ( LP_numpriceinfos > 0 ) + { + coinbits = stringbits(symbol); + pp = LP_priceinfos; + for (i=0; icoinbits == coinbits ) + return(pp); + } + return(0); +} + +struct LP_priceinfo *LP_priceinfoptr(int32_t *indp,char *base,char *rel) +{ + struct LP_priceinfo *basepp,*relpp; + if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) + { + *indp = relpp->ind; + return(basepp); + } + else + { + *indp = -1; + return(0); + } +} + int32_t LP_cachekey(uint8_t *key,char *base,char *rel,bits256 txid,int32_t vout) { uint64_t basebits,relbits; int32_t offset = 0; @@ -54,6 +95,8 @@ int32_t LP_cachekey(uint8_t *key,char *base,char *rel,bits256 txid,int32_t vout) struct LP_cacheinfo *LP_cachefind(char *base,char *rel,bits256 txid,int32_t vout) { struct LP_cacheinfo *ptr=0; uint8_t key[sizeof(bits256)+sizeof(uint64_t)*2+sizeof(vout)]; + if ( base == 0 || rel == 0 ) + return(0); if ( LP_cachekey(key,base,rel,txid,vout) == sizeof(key) ) { portable_mutex_lock(&LP_cachemutex); @@ -70,6 +113,131 @@ struct LP_cacheinfo *LP_cachefind(char *base,char *rel,bits256 txid,int32_t vout return(ptr); } +struct LP_pubkeyinfo *LP_pubkeyfind(bits256 pubkey) +{ + struct LP_pubkeyinfo *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_pubkeyinfo *pubp=0; + if ( (pubp= LP_pubkeyfind(pubkey)) == 0 ) + { + portable_mutex_lock(&LP_pubkeymutex); + pubp = calloc(1,sizeof(*pubp)); + pubp->pubkey = pubkey; + HASH_ADD_KEYPTR(hh,LP_pubkeyinfos,&pubp->pubkey,sizeof(pubp->pubkey),pubp); + portable_mutex_unlock(&LP_pubkeymutex); + if ( (pubp= LP_pubkeyfind(pubkey)) == 0 ) + printf("pubkeyadd find error after add\n"); + } + return(pubp); +} + +int32_t LP_pubkey_istrusted(bits256 pubkey) +{ + struct LP_pubkeyinfo *pubp; + if ( (pubp= LP_pubkeyfind(pubkey)) != 0 ) + return(pubp->istrusted != 0); + return(0); +} + +char *LP_pubkey_trustset(bits256 pubkey,uint32_t trustval) +{ + struct LP_pubkeyinfo *pubp; + if ( (pubp= LP_pubkeyfind(pubkey)) != 0 ) + { + pubp->istrusted = trustval; + return(clonestr("{\"result\":\"success\"}")); + } + return(clonestr("{\"error\":\"pubkey not found\"}")); +} + +cJSON *LP_pubkeyjson(struct LP_pubkeyinfo *pubp) +{ + int32_t baseid,relid; char *base; double price; cJSON *item,*array,*obj; + obj = cJSON_CreateObject(); + array = cJSON_CreateArray(); + for (baseid=0; baseidmatrix[baseid][relid]) > SMALLVAL ) + { + item = cJSON_CreateArray(); + jaddistr(item,base); + jaddistr(item,LP_priceinfos[relid].symbol); + jaddinum(item,price); + jaddi(array,item); + } + } + } + jaddbits256(obj,"pubkey",pubp->pubkey); + jaddnum(obj,"timestamp",pubp->timestamp); + jadd(obj,"asks",array); + if ( pubp->istrusted != 0 ) + jaddnum(obj,"istrusted",pubp->istrusted); + return(obj); +} + +char *LP_prices() +{ + struct LP_pubkeyinfo *pubp,*tmp; cJSON *array = cJSON_CreateArray(); + HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) + { + jaddi(array,LP_pubkeyjson(pubp)); + } + return(jprint(array,1)); +} + +void LP_prices_parse(cJSON *obj) +{ + struct LP_pubkeyinfo *pubp; struct LP_priceinfo *basepp; uint32_t timestamp; bits256 pubkey; cJSON *asks,*item; int32_t i,n,relid; char *base,*rel; double askprice; + pubkey = jbits256(obj,"pubkey"); + if ( bits256_nonz(pubkey) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 ) + { + if ( (timestamp= juint(obj,"timestamp")) > pubp->timestamp && (asks= jarray(&n,obj,"asks")) != 0 ) + { + pubp->timestamp = timestamp; + for (i=0; iind,relid,askprice); + pubp->matrix[basepp->ind][relid] = askprice; + } + } + } + } +} + +void LP_peer_pricesquery(char *destipaddr,uint16_t destport) +{ + char *retstr; cJSON *array; int32_t i,n; + if ( (retstr= issue_LP_getprices(destipaddr,destport)) != 0 ) + { + if ( (array= cJSON_Parse(retstr)) != 0 ) + { + if ( is_cJSON_Array(array) && (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; iQ; if ( ptr->price == 0. && ptr->Q.satoshis != 0 ) { - printf("null ptr->price? "); + printf("LP_pricecache: null ptr->price? "); ptr->price = (double)ptr->Q.destsatoshis / ptr->Q.satoshis; } //printf("found %s/%s %.8f\n",base,rel,ptr->price); @@ -89,63 +257,87 @@ double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,i return(0.); } -struct LP_priceinfo *LP_priceinfofind(char *symbol) -{ - int32_t i; struct LP_priceinfo *pp; uint64_t coinbits; - if ( LP_numpriceinfos > 0 ) - { - coinbits = stringbits(symbol); - pp = LP_priceinfos; - for (i=0; icoinbits == coinbits ) - return(pp); - } - return(0); -} - -struct LP_priceinfo *LP_priceinfoptr(int32_t *indp,char *base,char *rel) +void LP_priceinfoupdate(char *base,char *rel,double price) { struct LP_priceinfo *basepp,*relpp; if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) { - *indp = relpp->ind; - return(basepp); - } - else - { - *indp = -1; - return(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; } } -void LP_priceinfoupdate(char *base,char *rel,double price) +double LP_myprice(double *bidp,double *askp,char *base,char *rel) { - struct LP_priceinfo *basepp,*relpp; + struct LP_priceinfo *basepp,*relpp; double val; + *bidp = *askp = 0.; 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); + if ( (*askp= basepp->myprices[relpp->ind]) > SMALLVAL ) + { + if ( (val= relpp->myprices[basepp->ind]) > SMALLVAL ) + { + *bidp = 1. / val; + return((*askp + *bidp) * 0.5); + } + else + { + *bidp = 0.; + return(*askp); + } + } + else + { + if ( (val= relpp->myprices[basepp->ind]) > SMALLVAL ) + { + *bidp = 1. / val; + *askp = 0.; + return(*bidp); + } + } } + return(0.); } -double LP_myprice(double *bidp,double *askp,char *base,char *rel) +char *LP_myprices() { - struct LP_priceinfo *basepp,*relpp; - if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) + int32_t baseid,relid; double bid,ask; char *base,*rel; cJSON *item,*array; + array = cJSON_CreateArray(); + for (baseid=0; baseidmyprices[relpp->ind]; - *bidp = relpp->myprices[basepp->ind]; - return((*askp + *bidp) * 0.5); - } else return(0.); + base = LP_priceinfos[baseid].symbol; + for (relid=0; relid SMALLVAL ) + { + item = cJSON_CreateObject(); + jaddstr(item,"base",base); + jaddstr(item,"rel",rel); + jaddnum(item,"bid",bid); + jaddnum(item,"ask",ask); + jaddi(array,item); + } + } + } + return(jprint(array,1)); } int32_t LP_mypriceset(char *base,char *rel,double price) { - struct LP_priceinfo *basepp,*relpp; - if ( price != 0. && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) + struct LP_priceinfo *basepp,*relpp; struct LP_pubkeyinfo *pubp; + if ( base != 0 && rel != 0 && price > SMALLVAL && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) { - basepp->myprices[relpp->ind] = price * LP_profitratio; // ask - relpp->myprices[basepp->ind] = (1. / price) * LP_profitratio; // bid + basepp->myprices[relpp->ind] = price; // ask + //relpp->myprices[basepp->ind] = (1. / price); // bid + if ( (pubp= LP_pubkeyadd(LP_mypubkey)) != 0 ) + { + pubp->matrix[basepp->ind][relpp->ind] = price; + //pubp->matrix[relpp->ind][basepp->ind] = (1. / price); + pubp->timestamp = (uint32_t)time(NULL); + } return(0); } else return(-1); } @@ -167,7 +359,7 @@ cJSON *LP_priceinfomatrix(int32_t usemyprices) now = (uint32_t)time(NULL); HASH_ITER(hh,LP_cacheinfos,ptr,tmp) { - if ( ptr->timestamp < now-60 || ptr->price == 0. ) + if ( ptr->timestamp < now-3600*2 || ptr->price == 0. ) continue; LP_priceinfoupdate(ptr->Q.srccoin,ptr->Q.destcoin,ptr->price); } @@ -180,7 +372,7 @@ cJSON *LP_priceinfomatrix(int32_t usemyprices) { if ( usemyprices == 0 || (val= pp->myprices[j]) == 0. ) val = pp->relvals[j]; - if ( val != 0. ) + if ( val > SMALLVAL ) { sum += val; n++; @@ -197,8 +389,11 @@ cJSON *LP_priceinfomatrix(int32_t usemyprices) pp = LP_priceinfos; for (i=0; idiagval /= total; - jaddnum(vectorjson,pp->symbol,pp->diagval); + if ( pp->diagval > SMALLVAL ) + { + pp->diagval /= total; + jaddnum(vectorjson,pp->symbol,pp->diagval); + } } } return(vectorjson); @@ -207,6 +402,8 @@ cJSON *LP_priceinfomatrix(int32_t usemyprices) struct LP_priceinfo *LP_priceinfoadd(char *symbol) { struct LP_priceinfo *pp; cJSON *retjson; + if ( symbol == 0 ) + return(0); if ( LP_numpriceinfos >= sizeof(LP_priceinfos)/sizeof(*LP_priceinfos) ) { printf("cant add any more priceinfos\n"); @@ -217,16 +414,6 @@ struct LP_priceinfo *LP_priceinfoadd(char *symbol) safecopy(pp->symbol,symbol,sizeof(pp->symbol)); pp->coinbits = stringbits(symbol); pp->ind = LP_numpriceinfos++; - /*pp->relvals = calloc(LP_numpriceinfos+1,sizeof(*pp->relvals)); - //pp->myprices = calloc(LP_numpriceinfos+1,sizeof(*pp->myprices)); - vecsize = sizeof(*LP_priceinfos[i].relvals) * (LP_numpriceinfos + 1); - for (i=0; iprice -#define ptr_b ((struct LP_cacheinfo *)b)->price + int32_t retval = 0; +#define ptr_a (*(struct LP_orderbookentry **)a)->price +#define ptr_b (*(struct LP_orderbookentry **)b)->price if ( ptr_b > ptr_a ) - return(1); + retval = -1; else if ( ptr_b < ptr_a ) - return(-1); + retval = 1; else { #undef ptr_a #undef ptr_b -#define ptr_a ((struct LP_cacheinfo *)a)->Q.satoshis -#define ptr_b ((struct LP_cacheinfo *)b)->Q.satoshis +#define ptr_a ((struct LP_orderbookentry *)a)->basesatoshis +#define ptr_b ((struct LP_orderbookentry *)b)->basesatoshis if ( ptr_b > ptr_a ) - return(1); - else if ( ptr_b < ptr_a ) return(-1); + else if ( ptr_b < ptr_a ) + return(1); } - return(0); + // printf("%.8f vs %.8f -> %d\n",ptr_a,ptr_b,retval); + return(retval); #undef ptr_a #undef ptr_b } -static int _cmp_orderbookrev(const void *a,const void *b) +cJSON *LP_orderbookjson(struct LP_orderbookentry *op) { - return(-_cmp_orderbook(a,b)); + cJSON *item = cJSON_CreateObject(); + if ( op->price > SMALLVAL ) + { + jaddnum(item,"price",op->price); + jaddnum(item,"volume",dstr(op->basesatoshis)); + jaddbits256(item,"txid",op->txid); + jaddnum(item,"vout",op->vout); + jaddbits256(item,"pubkey",op->pubkey); + } + return(item); } -cJSON *LP_orderbookjson(struct LP_cacheinfo *ptr,int32_t polarity) +struct LP_orderbookentry *LP_orderbookentry(char *base,char *rel,bits256 txid,int32_t vout,bits256 txid2,int32_t vout2,double price,uint64_t basesatoshis,bits256 pubkey) { - double price; cJSON *item = cJSON_CreateObject(); - if ( ptr->Q.satoshis != 0 && ptr->Q.destsatoshis != 0 ) + struct LP_orderbookentry *op; + if ( (op= calloc(1,sizeof(*op))) != 0 ) { - price = (double)ptr->Q.destsatoshis / ptr->Q.satoshis; - jaddnum(item,"price",polarity > 0 ? price : 1. / price); - jaddnum(item,"volume",polarity > 0 ? dstr(ptr->Q.satoshis) : dstr(ptr->Q.destsatoshis)); - jaddbits256(item,"txid",ptr->Q.txid); - jaddnum(item,"vout",ptr->Q.vout); + op->txid = txid; + op->vout = vout; + op->txid2 = txid2; + op->vout2 = vout2; + op->price = price; + op->basesatoshis = basesatoshis; + op->pubkey = pubkey; } - return(item); + return(op); +} + +int32_t LP_orderbookfind(struct LP_orderbookentry **array,int32_t num,bits256 txid,int32_t vout) +{ + int32_t i; + for (i=0; ivout == vout && bits256_cmp(array[i]->txid,txid) == 0) || (array[i]->vout2 == vout && bits256_cmp(array[i]->txid2,txid) == 0) ) + return(i); + return(-1); +} + +int32_t LP_utxo_clientpublish(struct LP_utxoinfo *utxo) +{ + struct LP_peerinfo *peer,*tmp; cJSON *retjson; char *retstr; int32_t n = 0; + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + if ( (retstr= issue_LP_notifyutxo(peer->ipaddr,peer->port,utxo)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( jobj(retjson,"error") == 0 ) + { + //if ( strcmp("HUSH",utxo->coin) == 0 ) + // printf("clientpublish %s (%s)\n",peer->ipaddr,retstr); + utxo->T.lasttime = (uint32_t)time(NULL); + n++; + } + free_json(retjson); + } + free(retstr); + } + //if ( utxo->T.lasttime != 0 ) + // return(0); + } + return(n); +} + +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) +{ + struct LP_utxoinfo *utxo,*tmp; struct LP_pubkeyinfo *pubp=0; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; double price; int32_t baseid,relid; uint64_t basesatoshis; + if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 ) + baseid = basepp->ind; + else return(num); + HASH_ITER(hh,LP_utxoinfos[1],utxo,tmp) + { + if ( pubp == 0 || bits256_cmp(pubp->pubkey,utxo->pubkey) != 0 ) + pubp = LP_pubkeyfind(utxo->pubkey); + if ( pubp != 0 && pubp->numerrors >= LP_MAXPUBKEY_ERRORS ) + continue; + //char str[65],str2[65]; printf("check utxo.%s/v%d from %s\n",bits256_str(str,utxo->payment.txid),utxo->payment.vout,bits256_str(str2,utxo->pubkey)); + if ( strcmp(base,utxo->coin) == 0 && LP_isavailable(utxo) > 0 && pubp != 0 && (price= pubp->matrix[baseid][relid]) > SMALLVAL ) + { + if ( LP_orderbookfind(*arrayp,cachednum,utxo->payment.txid,utxo->payment.vout) < 0 ) + { + if ( polarity > 0 ) + basesatoshis = utxo->S.satoshis; + else basesatoshis = utxo->S.satoshis * price; + //char str[65]; printf("found utxo not in orderbook %s/v%d %.8f %.8f\n",bits256_str(str,utxo->payment.txid),utxo->payment.vout,dstr(basesatoshis),polarity > 0 ? price : 1./price); + if ( (op= LP_orderbookentry(base,rel,utxo->payment.txid,utxo->payment.vout,utxo->deposit.txid,utxo->deposit.vout,polarity > 0 ? price : 1./price,basesatoshis,utxo->pubkey)) != 0 ) + { + *arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1)); + (*arrayp)[num++] = op; + if ( bits256_cmp(utxo->pubkey,LP_mypubkey) == 0 && utxo->T.lasttime == 0 ) + LP_utxo_clientpublish(utxo); + } + } + } + } + return(num); } char *LP_orderbook(char *base,char *rel) { - uint32_t now,i; struct LP_cacheinfo *ptr,*tmp,**bids = 0,**asks = 0; cJSON *retjson,*array; int32_t numbids=0,numasks=0; + uint32_t now,i; struct LP_priceinfo *basepp=0,*relpp=0; struct LP_orderbookentry **bids = 0,**asks = 0; cJSON *retjson,*array; int32_t numbids=0,numasks=0,cachenumbids,cachenumasks,baseid,relid; + if ( (basepp= LP_priceinfofind(base)) == 0 || (relpp= LP_priceinfofind(rel)) == 0 ) + return(clonestr("{\"error\":\"base or rel not added\"}")); + baseid = basepp->ind; + relid = relpp->ind; now = (uint32_t)time(NULL); - HASH_ITER(hh,LP_cacheinfos,ptr,tmp) + /*struct LP_cacheinfo *ptr,*tmp; + HASH_ITER(hh,LP_cacheinfos,ptr,tmp) { - if ( ptr->timestamp < now-60 || ptr->price == 0. ) + if ( ptr->timestamp < now-3600*2 || ptr->price == 0. ) continue; if ( strcmp(ptr->Q.srccoin,base) == 0 && strcmp(ptr->Q.destcoin,rel) == 0 ) { asks = realloc(asks,sizeof(*asks) * (numasks+1)); - asks[numasks++] = ptr; + if ( (op= LP_orderbookentry(base,rel,ptr->Q.txid,ptr->Q.vout,ptr->Q.txid2,ptr->Q.vout2,ptr->price,ptr->Q.satoshis,ptr->Q.srchash)) != 0 ) + asks[numasks++] = op; } else if ( strcmp(ptr->Q.srccoin,rel) == 0 && strcmp(ptr->Q.destcoin,base) == 0 ) { bids = realloc(bids,sizeof(*bids) * (numbids+1)); - bids[numbids++] = ptr; + if ( (op= LP_orderbookentry(base,rel,ptr->Q.txid,ptr->Q.vout,ptr->Q.txid2,ptr->Q.vout2,1./ptr->price,ptr->Q.satoshis,ptr->Q.srchash)) != 0 ) + bids[numbids++] = op; } - } + }*/ + cachenumbids = numbids, cachenumasks = numasks; + //printf("start cache.(%d %d) numbids.%d numasks.%d\n",cachenumbids,cachenumasks,numbids,numasks); + numasks = LP_orderbook_utxoentries(now,1,base,rel,&asks,numasks,cachenumasks); + numbids = LP_orderbook_utxoentries(now,-1,rel,base,&bids,numbids,cachenumbids); retjson = cJSON_CreateObject(); array = cJSON_CreateArray(); if ( numbids > 1 ) - qsort(bids,numbids,sizeof(*bids),_cmp_orderbookrev); + qsort(bids,numbids,sizeof(*bids),_cmp_orderbook); + if ( numasks > 1 ) + { + for (i=0; iprice); + printf(" -> "); + qsort(asks,numasks,sizeof(*asks),_cmp_orderbook); + for (i=0; iprice); + printf("sorted asks.%d\n",numasks); + } for (i=0; i 1 ) - qsort(asks,numasks,sizeof(*asks),_cmp_orderbook); for (i=0; i SMALLVAL && origprice < price ) + price = origprice; + } + if ( price > SMALLVAL ) { retjson = cJSON_CreateObject(); jaddstr(retjson,"result","success"); + jaddstr(retjson,"method","postprice"); + jaddbits256(retjson,"pubkey",LP_mypubkey); jaddstr(retjson,"base",base); jaddstr(retjson,"rel",rel); jaddnum(retjson,"price",price); @@ -361,7 +666,24 @@ char *LP_pricestr(char *base,char *rel) } else return(clonestr("{\"error\":\"cant find baserel pair\"}")); } +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); +} +void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price) +{ + struct LP_priceinfo *basepp,*relpp; struct LP_pubkeyinfo *pubp; char str[65]; + if ( price > SMALLVAL && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) + { + printf("PRICEFEED UPDATE.(%s/%s) %.8f %s\n",base,rel,price,bits256_str(str,pubkey)); + if ( (pubp= LP_pubkeyadd(pubkey)) != 0 ) + { + pubp->matrix[basepp->ind][relpp->ind] = price; + pubp->timestamp = (uint32_t)time(NULL); + } else printf("error creating pubkey entry\n"); + } else printf("error finding %s/%s %.8f\n",base,rel,price); +} diff --git a/iguana/exchanges/LP_remember.c b/iguana/exchanges/LP_remember.c index bf9d34b82..78ce4a783 100644 --- a/iguana/exchanges/LP_remember.c +++ b/iguana/exchanges/LP_remember.c @@ -71,7 +71,7 @@ void basilisk_dontforget(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx fprintf(fp,",\"trigger\":\"%s\"",bits256_str(str,triggertxid)); if ( bits256_nonz(swap->I.pubAm) != 0 && bits256_nonz(swap->I.pubBn) != 0 ) { - basilisk_alicescript(redeemscript,&len,script,0,coinaddr,swap->alicecoin.p2shtype,swap->I.pubAm,swap->I.pubBn); + basilisk_alicescript(redeemscript,&len,script,0,coinaddr,swap->alicecoin.taddr,swap->alicecoin.p2shtype,swap->I.pubAm,swap->I.pubBn); LP_importaddress(swap->alicecoin.symbol,coinaddr); fprintf(fp,",\"Apayment\":\"%s\"",coinaddr); } @@ -427,13 +427,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti if ( bits256_nonz(privkey) != 0 ) { privAm = privkey; - printf("set privAm <- %s\n",bits256_str(str,privAm)); + //printf("set privAm <- %s\n",bits256_str(str,privAm)); } privkey = jbits256(item,"privBn"); if ( bits256_nonz(privkey) != 0 ) { privBn = privkey; - printf("set privBn <- %s\n",bits256_str(str,privBn)); + //printf("set privBn <- %s\n",bits256_str(str,privBn)); } expiration = juint(item,"expiration"); state = jint(item,"state"); @@ -554,7 +554,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti } else if ( finishedflag == 0 ) printf("%s not finished\n",fname); } - printf("alicepayment.%s bobpayment.%s bobdeposit.%s\n",alicepaymentaddr,bobpaymentaddr,bobdepositaddr); + //printf("alicepayment.%s bobpayment.%s bobdeposit.%s\n",alicepaymentaddr,bobpaymentaddr,bobdepositaddr); //printf("iambob.%d src.%s dest.%s bob.%s alice.%s pubA0.(%s)\n",iambob,src,dest,bobcoin,alicecoin,bits256_str(str,pubA0)); Adestaddr[0] = destaddr[0] = 0; Adest = Bdest = AAdest = ABdest = 0; @@ -568,12 +568,12 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti { if ( (alice= LP_coinfind(alicecoin)) != 0 ) { - bitcoin_address(Adestaddr,alice->pubtype,pubkey33,33); + bitcoin_address(Adestaddr,alice->taddr,alice->pubtype,pubkey33,33); AAdest = Adestaddr; } if ( (bob= LP_coinfind(bobcoin)) != 0 ) { - bitcoin_address(destaddr,bob->pubtype,pubkey33,33); + bitcoin_address(destaddr,bob->taddr,bob->pubtype,pubkey33,33); Adest = destaddr; } } @@ -581,12 +581,12 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti { if ( (bob= LP_coinfind(bobcoin)) != 0 ) { - bitcoin_address(destaddr,bob->pubtype,pubkey33,33); + bitcoin_address(destaddr,bob->taddr,bob->pubtype,pubkey33,33); Bdest = destaddr; } if ( (alice= LP_coinfind(alicecoin)) != 0 ) { - bitcoin_address(Adestaddr,alice->pubtype,pubkey33,33); + bitcoin_address(Adestaddr,alice->taddr,alice->pubtype,pubkey33,33); ABdest = Adestaddr; } } @@ -625,18 +625,18 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti { char privaddr[64]; uint8_t privpub33[33]; bitcoin_pubkey33(ctx,privpub33,myprivs[0]); - bitcoin_address(privaddr,60,privpub33,33); + bitcoin_address(privaddr,0,60,privpub33,33); printf("alicespend len.%d redeemlen.%d priv0addr.(%s) priv0.(%s)\n",len,redeemlen,privaddr,bits256_str(str,myprivs[0])); } for (j=0; j<32; j++) rev.bytes[j] = myprivs[0].bytes[31 - j]; - if ( (txbytes[BASILISK_ALICESPEND]= basilisk_swap_bobtxspend(&signedtxid,txfee,"alicespend",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,0,pubkey33,1,expiration,&values[BASILISK_ALICESPEND],0,0,bobpaymentaddr,1)) != 0 ) + if ( (txbytes[BASILISK_ALICESPEND]= basilisk_swap_bobtxspend(&signedtxid,txfee,"alicespend",bobcoin,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,0,pubkey33,1,expiration,&values[BASILISK_ALICESPEND],0,0,bobpaymentaddr,1)) != 0 ) printf("alicespend.(%s)\n",txbytes[BASILISK_ALICESPEND]); } } if ( txbytes[BASILISK_ALICESPEND] != 0 ) { - txids[BASILISK_ALICESPEND] = LP_broadcast("alicespend",bobcoin,txbytes[BASILISK_ALICESPEND]); + txids[BASILISK_ALICESPEND] = LP_broadcast("alicespend",bobcoin,txbytes[BASILISK_ALICESPEND],zero); if ( bits256_nonz(txids[BASILISK_ALICESPEND]) != 0 ) // tested { sentflags[BASILISK_ALICESPEND] = 1; @@ -655,13 +655,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti if ( redeemlen > 0 ) { len = basilisk_swapuserdata(userdata,zero,1,myprivs[0],redeemscript,redeemlen); - if ( (txbytes[BASILISK_ALICECLAIM]= basilisk_swap_bobtxspend(&signedtxid,txfee,"aliceclaim",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,0,pubkey33,0,expiration,&values[BASILISK_ALICECLAIM],0,0,bobdepositaddr,1)) != 0 ) + if ( (txbytes[BASILISK_ALICECLAIM]= basilisk_swap_bobtxspend(&signedtxid,txfee,"aliceclaim",bobcoin,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,0,pubkey33,0,expiration,&values[BASILISK_ALICECLAIM],0,0,bobdepositaddr,1)) != 0 ) printf("privBn.(%s) aliceclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICECLAIM]); } } if ( txbytes[BASILISK_ALICECLAIM] != 0 ) { - txids[BASILISK_ALICECLAIM] = LP_broadcast("aliceclaim",bobcoin,txbytes[BASILISK_ALICECLAIM]); + txids[BASILISK_ALICECLAIM] = LP_broadcast("aliceclaim",bobcoin,txbytes[BASILISK_ALICECLAIM],zero); if ( bits256_nonz(txids[BASILISK_ALICECLAIM]) != 0 ) // tested { sentflags[BASILISK_ALICECLAIM] = 1; @@ -677,13 +677,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti privBn = basilisk_swap_privBn_extract(&txids[BASILISK_BOBREFUND],bobcoin,txids[BASILISK_BOBDEPOSIT],privBn); if ( bits256_nonz(txids[BASILISK_ALICEPAYMENT]) != 0 && bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 ) { - if ( (txbytes[BASILISK_ALICERECLAIM]= basilisk_swap_Aspend("alicereclaim",alicecoin,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_ALICERECLAIM],alicepaymentaddr)) != 0 ) + if ( (txbytes[BASILISK_ALICERECLAIM]= basilisk_swap_Aspend("alicereclaim",alicecoin,alice->taddr,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_ALICERECLAIM],alicepaymentaddr)) != 0 ) printf("privBn.(%s) alicereclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICERECLAIM]); } } if ( txbytes[BASILISK_ALICERECLAIM] != 0 ) { - txids[BASILISK_ALICERECLAIM] = LP_broadcast("alicereclaim",alicecoin,txbytes[BASILISK_ALICERECLAIM]); + txids[BASILISK_ALICERECLAIM] = LP_broadcast("alicereclaim",alicecoin,txbytes[BASILISK_ALICERECLAIM],zero); if ( bits256_nonz(txids[BASILISK_ALICERECLAIM]) != 0 ) // tested { sentflags[BASILISK_ALICERECLAIM] = 1; @@ -707,13 +707,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti } if ( bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 ) { - if ( (txbytes[BASILISK_BOBSPEND]= basilisk_swap_Aspend("bobspend",alicecoin,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_BOBSPEND],alicepaymentaddr)) != 0 ) + if ( (txbytes[BASILISK_BOBSPEND]= basilisk_swap_Aspend("bobspend",alicecoin,alice->taddr,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_BOBSPEND],alicepaymentaddr)) != 0 ) printf("bobspend.(%s)\n",txbytes[BASILISK_BOBSPEND]); } } if ( txbytes[BASILISK_BOBSPEND] != 0 ) { - txids[BASILISK_BOBSPEND] = LP_broadcast("bobspend",alicecoin,txbytes[BASILISK_BOBSPEND]); + txids[BASILISK_BOBSPEND] = LP_broadcast("bobspend",alicecoin,txbytes[BASILISK_BOBSPEND],zero); if ( bits256_nonz(txids[BASILISK_BOBSPEND]) != 0 ) // tested { sentflags[BASILISK_BOBSPEND] = 1; @@ -731,7 +731,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti if ( redeemlen > 0 ) { len = basilisk_swapuserdata(userdata,zero,1,myprivs[1],redeemscript,redeemlen); - if ( (txbytes[BASILISK_BOBRECLAIM]= basilisk_swap_bobtxspend(&signedtxid,txfee,"bobrefund",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[1],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,0,pubkey33,0,expiration,&values[BASILISK_BOBRECLAIM],0,0,bobpaymentaddr,1)) != 0 ) + if ( (txbytes[BASILISK_BOBRECLAIM]= basilisk_swap_bobtxspend(&signedtxid,txfee,"bobrefund",bobcoin,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[1],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,0,pubkey33,0,expiration,&values[BASILISK_BOBRECLAIM],0,0,bobpaymentaddr,1)) != 0 ) { int32_t z; for (z=0; z<20; z++) @@ -742,7 +742,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti } if ( txbytes[BASILISK_BOBRECLAIM] != 0 ) { - txids[BASILISK_BOBRECLAIM] = LP_broadcast("bobreclaim",bobcoin,txbytes[BASILISK_BOBRECLAIM]); + txids[BASILISK_BOBRECLAIM] = LP_broadcast("bobreclaim",bobcoin,txbytes[BASILISK_BOBRECLAIM],zero); if ( bits256_nonz(txids[BASILISK_BOBRECLAIM]) != 0 ) // tested { sentflags[BASILISK_BOBRECLAIM] = 1; @@ -761,12 +761,12 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti vcalc_sha256(0,secretBn256,privBn.bytes,sizeof(privBn)); redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,dlocktime,pubA0,pubB0,pubB1,privAm,privBn,secretAm,secretAm256,secretBn,secretBn256); len = basilisk_swapuserdata(userdata,privBn,0,myprivs[0],redeemscript,redeemlen); - if ( (txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend(&signedtxid,txfee,"bobrefund",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,0,pubkey33,1,expiration,&values[BASILISK_BOBREFUND],0,0,bobdepositaddr,1)) != 0 ) + if ( (txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend(&signedtxid,txfee,"bobrefund",bobcoin,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,0,pubkey33,1,expiration,&values[BASILISK_BOBREFUND],0,0,bobdepositaddr,1)) != 0 ) printf("pubB1.(%s) bobrefund.(%s)\n",bits256_str(str,pubB1),txbytes[BASILISK_BOBREFUND]); } if ( txbytes[BASILISK_BOBREFUND] != 0 ) { - txids[BASILISK_BOBREFUND] = LP_broadcast("bobrefund",bobcoin,txbytes[BASILISK_BOBREFUND]); + txids[BASILISK_BOBREFUND] = LP_broadcast("bobrefund",bobcoin,txbytes[BASILISK_BOBREFUND],zero); if ( bits256_nonz(txids[BASILISK_BOBREFUND]) != 0 ) // tested { sentflags[BASILISK_BOBREFUND] = 1; @@ -867,6 +867,24 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti if ( finishedflag != 0 ) jaddstr(item,"status","finished"); else jaddstr(item,"status","pending"); + if ( bits256_nonz(paymentspent) == 0 ) + { + if ( bits256_nonz(txids[BASILISK_ALICESPEND]) != 0 ) + paymentspent = txids[BASILISK_ALICESPEND]; + else paymentspent = txids[BASILISK_BOBRECLAIM]; + } + if ( bits256_nonz(depositspent) == 0 ) + { + if ( bits256_nonz(txids[BASILISK_BOBREFUND]) != 0 ) + depositspent = txids[BASILISK_BOBREFUND]; + else depositspent = txids[BASILISK_ALICECLAIM]; + } + if ( bits256_nonz(Apaymentspent) == 0 ) + { + if ( bits256_nonz(txids[BASILISK_BOBSPEND]) != 0 ) + Apaymentspent = txids[BASILISK_BOBSPEND]; + else Apaymentspent = txids[BASILISK_ALICERECLAIM]; + } bits256_str(str,paymentspent), jaddbits256(item,"paymentspent",paymentspent); bits256_str(str,Apaymentspent), jaddbits256(item,"Apaymentspent",Apaymentspent); bits256_str(str,depositspent), jaddbits256(item,"depositspent",depositspent); @@ -888,7 +906,8 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti char *basilisk_swaplist() { - char fname[512],*status; FILE *fp; cJSON *item,*retjson,*array,*totalsobj; uint32_t quoteid,requestid; int64_t KMDtotals[16],BTCtotals[16],Btotal,Ktotal; int32_t i; + char fname[512]; FILE *fp; cJSON *item,*retjson,*array,*totalsobj; uint32_t quoteid,requestid; int64_t KMDtotals[16],BTCtotals[16],Btotal,Ktotal; int32_t i; + portable_mutex_lock(&LP_swaplistmutex); memset(KMDtotals,0,sizeof(KMDtotals)); memset(BTCtotals,0,sizeof(BTCtotals)); //,statebits; int32_t optionduration; struct basilisk_request R; bits256 privkey; @@ -914,8 +933,8 @@ char *basilisk_swaplist() if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid)) != 0 ) { jaddi(array,item); - if ( 1 && (status= jstr(item,"status")) != 0 && strcmp(status,"pending") == 0 ) - break; + //if ( (status= jstr(item,"status")) != 0 && strcmp(status,"pending") == 0 ) + // break; } } } @@ -949,6 +968,36 @@ char *basilisk_swaplist() jaddi(array,linfo_json(&myinfo->linfos[i])); } jadd(retjson,"quotes",array);*/ + portable_mutex_unlock(&LP_swaplistmutex); return(jprint(retjson,1)); } +char *basilisk_swapentry(uint32_t requestid,uint32_t quoteid) +{ + char *liststr,*retstr = 0; cJSON *retjson,*array,*item; int32_t i,n; + if ( (liststr= basilisk_swaplist()) != 0 ) + { + if ( (retjson= cJSON_Parse(liststr)) != 0 ) + { + if ( (array= jarray(&n,retjson,"swaps")) != 0 ) + { + for (i=0; ierrors < maxerrs || peer->good >= LP_MINPEER_GOOD) ) + { + if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) == 0 ) + { + if ( peer != 0 ) + { + peer->errors++; + peer->good *= LP_PEERGOOD_ERRORDECAY; + } else printf("%s error on (%s:%u) without peer\n",debugstr,destip,port); + } + else if ( peer != 0 ) + peer->good++; + } + return(retstr); +} + +char *LP_isitme(char *destip,uint16_t destport) +{ + if ( LP_mypeer != 0 && strcmp(destip,LP_mypeer->ipaddr) == 0 && LP_mypeer->port == destport ) + { + //printf("no need to notify ourselves\n"); + return(clonestr("{\"result\":\"success\"}")); + } else return(0); +} + char *issue_LP_getpeers(char *destip,uint16_t destport,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos) { - char url[512],*retstr; + char url[512]; sprintf(url,"http://%s:%u/api/stats/getpeers?ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,profitmargin,numpeers,numutxos); - //printf("send.(%s)\n",url); - retstr = issue_curl(url); - //printf("GETPEERS.(%s)\n",retstr); - return(retstr); + return(LP_issue_curl("getpeers",destip,port,url)); } char *issue_LP_getutxos(char *destip,uint16_t destport,char *coin,int32_t lastn,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos) { char url[512]; sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,coin,lastn,ipaddr,port,profitmargin,numpeers,numutxos); - return(issue_curl(url)); + return(LP_issue_curl("getutxos",destip,destport,url)); + //return(issue_curlt(url,LP_HTTP_TIMEOUT)); } char *issue_LP_clientgetutxos(char *destip,uint16_t destport,char *coin,int32_t lastn) { - char url[512]; + char url[512];//,*retstr; sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=127.0.0.1&port=0",destip,destport,coin,lastn); - //printf("getutxos.(%s)\n",url); - return(issue_curl(url)); + return(LP_issue_curl("clientgetutxos",destip,destport,url)); + //retstr = issue_curlt(url,LP_HTTP_TIMEOUT); + //printf("%s clientgetutxos.(%s)\n",url,retstr); + //return(retstr); } char *issue_LP_notify(char *destip,uint16_t destport,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos) { - char url[512]; + char url[512],*retstr; + if ( (retstr= LP_isitme(destip,destport)) != 0 ) + { + free(retstr); + return(0); + } sprintf(url,"http://%s:%u/api/stats/notify?ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,profitmargin,numpeers,numutxos); - return(issue_curl(url)); + return(LP_issue_curl("notify",destip,destport,url)); + //return(issue_curlt(url,LP_HTTP_TIMEOUT)); } char *issue_LP_notifyutxo(char *destip,uint16_t destport,struct LP_utxoinfo *utxo) { - char url[4096],str[65],str2[65]; - sprintf(url,"http://%s:%u/api/stats/notifyutxo?ipaddr=%s&port=%u&profit=%.6f&coin=%s&txid=%s&vout=%d&value=%.8f&txid2=%s&vout2=%d&value2=%.8f&script=%s&address=%s",destip,destport,utxo->ipaddr,utxo->port,utxo->profitmargin,utxo->coin,bits256_str(str,utxo->txid),utxo->vout,dstr(utxo->satoshis),bits256_str(str2,utxo->txid2),utxo->vout2,dstr(utxo->satoshis2),utxo->spendscript,utxo->coinaddr); - if ( strlen(url) > 1024 ) - printf("WARNING long url.(%s)\n",url); - return(issue_curl(url)); + char url[4096],str[65],str2[65],str3[65],*retstr; struct _LP_utxoinfo u; uint64_t val,val2; + if ( (retstr= LP_isitme(destip,destport)) != 0 ) + { + free(retstr); + return(0); + } + if ( utxo->iambob == 0 ) + { + printf("issue_LP_notifyutxo trying to send Alice %s/v%d\n",bits256_str(str,utxo->payment.txid),utxo->payment.vout); + return(0); + } + u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; + if ( LP_iseligible(&val,&val2,utxo->iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,u.txid,u.vout,utxo->pubkey) > 0 ) + { + sprintf(url,"http://%s:%u/api/stats/notified?iambob=%d&pubkey=%s&profit=%.6f&coin=%s&txid=%s&vout=%d&value=%llu&txid2=%s&vout2=%d&value2=%llu&script=%s&address=%s×tamp=%u&gui=%s",destip,destport,utxo->iambob,bits256_str(str3,utxo->pubkey),utxo->S.profitmargin,utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout,(long long)utxo->payment.value,bits256_str(str2,utxo->deposit.txid),utxo->deposit.vout,(long long)utxo->deposit.value,utxo->spendscript,utxo->coinaddr,(uint32_t)time(NULL),utxo->gui); + if ( strlen(url) > 1024 ) + printf("WARNING long url.(%s)\n",url); + return(LP_issue_curl("notifyutxo",destip,destport,url)); + //return(issue_curlt(url,LP_HTTP_TIMEOUT)); + } + else + { + printf("issue_LP_notifyutxo: ineligible utxo iambob.%d %.8f %.8f\n",utxo->iambob,dstr(val),dstr(val2)); + return(0); + } +} + +char *issue_LP_register(char *destip,uint16_t destport,bits256 pubkey,char *ipaddr,uint16_t pushport) +{ + char url[512],str[65];//*retstr; + sprintf(url,"http://%s:%u/api/stats/register?client=%s&pushaddr=%s&pushport=%u",destip,destport,bits256_str(str,pubkey),ipaddr,pushport); + return(LP_issue_curl("register",destip,destport,url)); + //retstr = issue_curlt(url,LP_HTTP_TIMEOUT); + //printf("getutxo.(%s) -> (%s)\n",url,retstr!=0?retstr:""); + //return(retstr); +} + +char *issue_LP_psock(char *destip,uint16_t destport,int32_t ispaired) +{ + char url[512]; + sprintf(url,"http://%s:%u/api/stats/psock?ispaired=%d",destip,destport,ispaired); + return(LP_issue_curl("psock",destip,destport,url)); + //retstr = issue_curlt(url,LP_HTTP_TIMEOUT); + //printf("getutxo.(%s) -> (%s)\n",url,retstr!=0?retstr:""); + //return(retstr); +} + +uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired) +{ + uint16_t publicport = 0; char *retstr,*addr; cJSON *retjson; struct LP_peerinfo *peer,*tmp; + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + connectaddr[0] = publicaddr[0] = 0; + if ( peer->errors < LP_MAXPEER_ERRORS && (retstr= issue_LP_psock(peer->ipaddr,peer->port,ispaired)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( (addr= jstr(retjson,"publicaddr")) != 0 ) + safecopy(publicaddr,addr,128); + if ( (addr= jstr(retjson,"connectaddr")) != 0 ) + safecopy(connectaddr,addr,128); + if ( publicaddr[0] != 0 && connectaddr[0] != 0 ) + publicport = juint(retjson,"publicport"); + free_json(retjson); + } + printf("got.(%s) connect.%s public.%s\n",retstr,connectaddr,publicaddr); + free(retstr); + } + if ( publicport != 0 ) + break; + } + return(publicport); +} + +char *issue_LP_lookup(char *destip,uint16_t destport,bits256 pubkey) +{ + char url[512],str[65]; + sprintf(url,"http://%s:%u/api/stats/lookup?client=%s",destip,destport,bits256_str(str,pubkey)); + //printf("getutxo.(%s)\n",url); + return(LP_issue_curl("lookup",destip,destport,url)); + //return(issue_curlt(url,LP_HTTP_TIMEOUT)); +} + +char *issue_LP_getprices(char *destip,uint16_t destport) +{ + char url[512]; + sprintf(url,"http://%s:%u/api/stats/getprices",destip,destport); + //printf("getutxo.(%s)\n",url); + return(LP_issue_curl("getprices",destip,destport,url)); + //return(issue_curlt(url,LP_HTTP_TIMEOUT)); } cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params) @@ -71,8 +193,9 @@ cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params) retjson = cJSON_Parse(retstr); free(retstr); } + //usleep(1000); //printf("dpow_gettxout.(%s)\n",retstr); - } + } else printf("bitcoin_json cant talk to NULL coin\n"); return(retjson); } @@ -87,10 +210,16 @@ cJSON *LP_getinfo(char *symbol) return(bitcoin_json(coin,"getinfo","[]")); } +cJSON *LP_getmempool(char *symbol) +{ + struct iguana_info *coin = LP_coinfind(symbol); + return(bitcoin_json(coin,"getrawmempool","[]")); +} + cJSON *LP_gettxout(char *symbol,bits256 txid,int32_t vout) { char buf[128],str[65]; struct iguana_info *coin = LP_coinfind(symbol); - sprintf(buf,"\"%s\", %d",bits256_str(str,txid),vout); + sprintf(buf,"\"%s\", %d, true",bits256_str(str,txid),vout); return(bitcoin_json(coin,"gettxout",buf)); } @@ -101,6 +230,20 @@ cJSON *LP_gettx(char *symbol,bits256 txid) return(bitcoin_json(coin,"getrawtransaction",buf)); } +cJSON *LP_getblock(char *symbol,bits256 txid) +{ + char buf[128],str[65]; struct iguana_info *coin = LP_coinfind(symbol); + sprintf(buf,"[\"%s\"]",bits256_str(str,txid)); + return(bitcoin_json(coin,"getblock",buf)); +} + +cJSON *LP_getblockhashstr(char *symbol,char *blockhashstr) +{ + char buf[128]; struct iguana_info *coin = LP_coinfind(symbol); + sprintf(buf,"[\"%s\"]",blockhashstr); + return(bitcoin_json(coin,"getblock",buf)); +} + cJSON *LP_listunspent(char *symbol,char *coinaddr) { char buf[128]; struct iguana_info *coin = LP_coinfind(symbol); @@ -152,15 +295,15 @@ int32_t LP_importaddress(char *symbol,char *address) sprintf(buf,"[\"%s\", \"%s\", false]",address,address); if ( (retstr= bitcoind_passthru(symbol,coin->serverport,coin->userpass,"importaddress",buf)) != 0 ) { - printf("importaddress.(%s %s) -> (%s)\n",symbol,address,retstr); + //printf("importaddress.(%s %s) -> (%s)\n",symbol,address,retstr); free(retstr); - } else printf("importaddress.(%s %s)\n",symbol,address); + } //else printf("importaddress.(%s %s)\n",symbol,address); return(1); } double LP_getestimatedrate(char *symbol) { - char buf[512],*retstr; double rate = 200; struct iguana_info *coin = LP_coinfind(symbol); + char buf[512],*retstr; double rate = 20; struct iguana_info *coin = LP_coinfind(symbol); if ( coin != 0 ) { sprintf(buf,"[%d]",3); @@ -168,7 +311,7 @@ double LP_getestimatedrate(char *symbol) { if ( retstr[0] != '-' ) { - rate = atof(retstr) / 1024.; + coin->estimatedrate = rate = atof(retstr) / 1024.; printf("estimated rate.(%s) %s -> %.8f\n",symbol,retstr,rate); } free(retstr); @@ -185,6 +328,19 @@ uint64_t LP_txfee(char *symbol) return(txfee); } +char *LP_blockhashstr(char *symbol,int32_t height) +{ + cJSON *array; char *paramstr,*retstr; struct iguana_info *coin = LP_coinfind(symbol); + if ( coin == 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); + return(retstr); +} + char *LP_sendrawtransaction(char *symbol,char *signedtx) { cJSON *array; char *paramstr,*retstr; struct iguana_info *coin = LP_coinfind(symbol); @@ -194,7 +350,7 @@ char *LP_sendrawtransaction(char *symbol,char *signedtx) jaddistr(array,signedtx); paramstr = jprint(array,1); retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"sendrawtransaction",paramstr); - printf(">>>>>>>>>>> %s dpow_sendrawtransaction.(%s) -> (%s)\n",coin->symbol,paramstr,retstr); + //printf(">>>>>>>>>>> %s dpow_sendrawtransaction.(%s) -> (%s)\n",coin->symbol,paramstr,retstr); free(paramstr); return(retstr); } @@ -238,3 +394,31 @@ char *LP_signrawtx(char *symbol,bits256 *signedtxidp,int32_t *completedp,cJSON * free(paramstr); return(signedtx); } + +cJSON *LP_blockjson(int32_t *heightp,char *symbol,char *blockhashstr,int32_t height) +{ + cJSON *json = 0; int32_t flag = 0; + if ( blockhashstr == 0 ) + blockhashstr = LP_blockhashstr(symbol,height), flag = 1; + if ( blockhashstr != 0 ) + { + if ( (json= LP_getblockhashstr(symbol,blockhashstr)) != 0 ) + { + if ( *heightp != 0 ) + { + *heightp = juint(json,"height"); + if ( height >= 0 && *heightp != height ) + { + printf("unexpected height %d vs %d\n",*heightp,height); + *heightp = -1; + free_json(json); + json = 0; + } + } + } + if ( flag != 0 && blockhashstr != 0 ) + free(blockhashstr); + } + return(json); +} + diff --git a/iguana/exchanges/LP_statemachine.c b/iguana/exchanges/LP_statemachine.c index dc0240c1b..70e6d1c7b 100644 --- a/iguana/exchanges/LP_statemachine.c +++ b/iguana/exchanges/LP_statemachine.c @@ -204,7 +204,7 @@ void basilisk_swapgotdata(struct basilisk_swap *swap,uint32_t crc32,bits256 srch int32_t basilisk_swapget(struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,int32_t (*basilisk_verify_func)(void *ptr,uint8_t *data,int32_t datalen)) { uint8_t *ptr; bits256 srchash,desthash; uint32_t crc32,_msgbits,quoteid; int32_t i,size,offset,retval = -1; struct basilisk_swapmessage *mp = 0; - while ( (size= nn_recv(swap->subsock,&ptr,NN_MSG,0)) >= 0 ) + while ( (size= nn_recv(swap->subsock,&ptr,NN_MSG,NN_DONTWAIT)) >= 0 ) { swap->lasttime = (uint32_t)time(NULL); memset(srchash.bytes,0,sizeof(srchash)); @@ -404,18 +404,12 @@ cJSON *LP_createvins(struct basilisk_rawtx *dest,struct vin_info *V,struct basil int32_t _basilisk_rawtx_gen(char *str,uint32_t swapstarted,uint8_t *pubkey33,int32_t iambob,int32_t lockinputs,struct basilisk_rawtx *rawtx,uint32_t locktime,uint8_t *script,int32_t scriptlen,int64_t txfee,int32_t minconf,int32_t delay,bits256 privkey) { char scriptstr[1024],wifstr[256],coinaddr[64],*signedtx,*rawtxbytes; uint32_t basilisktag; int32_t retval = -1; cJSON *vins,*privkeys,*addresses,*valsobj; struct vin_info *V; - //bitcoin_address(coinaddr,rawtx->coin->chain->pubtype,myinfo->persistent_pubkey33,33); - if ( rawtx->coin->changeaddr[0] == 0 ) - { - bitcoin_address(rawtx->coin->changeaddr,rawtx->coin->pubtype,pubkey33,33); - printf("set change address.(%s)\n",rawtx->coin->changeaddr); - } init_hexbytes_noT(scriptstr,script,scriptlen); basilisktag = (uint32_t)rand(); valsobj = cJSON_CreateObject(); jaddstr(valsobj,"coin",rawtx->coin->symbol); jaddstr(valsobj,"spendscript",scriptstr); - jaddstr(valsobj,"changeaddr",rawtx->coin->changeaddr); + jaddstr(valsobj,"changeaddr",rawtx->coin->smartaddr); jadd64bits(valsobj,"satoshis",rawtx->I.amount); if ( strcmp(rawtx->coin->symbol,"BTC") == 0 && txfee > 0 && txfee < 50000 ) txfee = 50000; @@ -990,7 +984,6 @@ cJSON *basilisk_privkeyarray(struct iguana_info *coin,cJSON *vins) { cJSON *privkeyarray,*item,*sobj; struct iguana_waddress *waddr; struct iguana_waccount *wacct; char coinaddr[64],account[128],wifstr[64],str[65],typestr[64],*hexstr; uint8_t script[1024]; int32_t i,n,len,vout; bits256 txid,privkey; double bidasks[2]; privkeyarray = cJSON_CreateArray(); - //printf("%s persistent.(%s) (%s) change.(%s) scriptstr.(%s)\n",coin->symbol,myinfo->myaddr.BTC,coinaddr,coin->changeaddr,scriptstr); if ( (n= cJSON_GetArraySize(vins)) > 0 ) { for (i=0; iDEX_swapmutex); }*/ + +/*int32_t LP_priceping(int32_t pubsock,struct LP_utxoinfo *utxo,char *rel,double origprice) + { + double price,bid,ask; uint32_t now; cJSON *retjson; struct LP_quoteinfo Q; char *retstr; + if ( (now= (uint32_t)time(NULL)) > utxo->T.swappending && utxo->S.swap == 0 ) + utxo->T.swappending = 0; + if ( now > utxo->T.published+60 && LP_isavailable(utxo) && (price= LP_myprice(&bid,&ask,utxo->coin,rel)) != 0. ) + { + if ( origprice < price ) + price = origprice; + if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 ) + return(-1); + Q.timestamp = (uint32_t)time(NULL); + retjson = LP_quotejson(&Q); + jaddstr(retjson,"method","quote"); + retstr = jprint(retjson,1); + //printf("PING.(%s)\n",retstr); + if ( pubsock >= 0 ) + LP_send(pubsock,retstr,1); + else + { + // verify it is in list + // push if it isnt + } + utxo->T.published = now; + return(0); + } + return(-1); + }*/ +/*if ( addflag != 0 && LP_utxofind(1,Q.txid,Q.vout) == 0 ) + { + LP_utxoadd(1,-1,Q.srccoin,Q.txid,Q.vout,Q.value,Q.txid2,Q.vout2,Q.value2,"",Q.srcaddr,Q.srchash,0.); + LP_utxoadd(0,-1,Q.destcoin,Q.desttxid,Q.destvout,Q.destvalue,Q.feetxid,Q.feevout,Q.feevalu,"",Q.destaddr,Q.desthash,0.); + }*/ + +/*struct LP_utxoinfo *utxo,*tmp; + HASH_ITER(hh,LP_utxoinfos[1],utxo,tmp) + { + if ( LP_ismine(utxo) > 0 && strcmp(utxo->coin,base) == 0 ) + LP_priceping(LP_mypubsock,utxo,rel,price * LP_profitratio); + }*/ +/* +bestprice = 0.; +if ( (array= LP_tradecandidates(base)) != 0 ) +{ + printf("candidates.(%s)\nn.%d\n",jprint(array,0),cJSON_GetArraySize(array)); + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + memset(prices,0,sizeof(prices)); + memset(Q,0,sizeof(Q)); + for (i=0; icoin,zero); + Q[i].destsatoshis = price * Q[i].satoshis; + } + if ( (prices[i]= price) > SMALLVAL && (bestprice == 0. || price < bestprice) ) + bestprice = price; + char str[65]; printf("i.%d of %d: (%s) -> txid.%s price %.8f best %.8f dest %.8f\n",i,n,jprint(item,0),bits256_str(str,Q[i].txid),price,bestprice,dstr(Q[i].destsatoshis)); + } + if ( bestprice > SMALLVAL ) + { + bestmetric = 0.; + besti = -1; + for (i=0; i SMALLVAL && myutxo->S.satoshis >= Q[i].destsatoshis+Q[i].desttxfee ) + { + metric = price / bestprice; + printf("%f %f %f %f ",price,metric,dstr(Q[i].destsatoshis),metric * metric * metric); + if ( metric < 1.1 ) + { + metric = dstr(Q[i].destsatoshis) * metric * metric * metric; + printf("%f\n",metric); + if ( bestmetric == 0. || metric < bestmetric ) + { + besti = i; + bestmetric = metric; + } + } + } else printf("(%f %f) ",dstr(myutxo->S.satoshis),dstr(Q[i].destsatoshis)); + } + printf("metrics, best %f\n",bestmetric); +*/ + +/*cJSON *LP_tradecandidates(char *base) + { + struct LP_peerinfo *peer,*tmp; struct LP_quoteinfo Q; char *utxostr,coinstr[16]; cJSON *array,*retarray=0,*item; int32_t i,n,totaladded,added; + totaladded = 0; + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + printf("%s:%u %s\n",peer->ipaddr,peer->port,base); + n = added = 0; + if ( (utxostr= issue_LP_clientgetutxos(peer->ipaddr,peer->port,base,100)) != 0 ) + { + printf("%s:%u %s %s\n",peer->ipaddr,peer->port,base,utxostr); + if ( (array= cJSON_Parse(utxostr)) != 0 ) + { + if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) + { + retarray = cJSON_CreateArray(); + for (i=0; i 0 ) + { + memset(&Q,0,sizeof(Q)); + for (i=0; i 0 ) + { + printf("iterate through all locally generated quotes and update, or change to price feed\n"); + // jl777: iterated Q's + if ( strcmp(utxo->coin,"KMD") == 0 ) + LP_priceping(pubsock,utxo,"BTC",profitmargin); + else LP_priceping(pubsock,utxo,"KMD",profitmargin); + }*/ + diff --git a/iguana/exchanges/LP_swap.c b/iguana/exchanges/LP_swap.c index b6e91d625..6f0c8aa34 100644 --- a/iguana/exchanges/LP_swap.c +++ b/iguana/exchanges/LP_swap.c @@ -17,22 +17,12 @@ // LP_swap.c // marketmaker // + /* - resume handling: list of tx broadcast, tx pending + required items, reconnect state machine or have statemachine assume off by one or state/otherstate specific handling make sure to broadcast deposit before claiming refund, or to just skip it if neither is done */ -// Todo: monitor blockchains, ie complete extracting scriptsig -// mode to autocreate required outputs -// more better LP commands - -// depends on just three external functions: -// - basilisk_sendrawtransaction(coin,signedtx); -// - basilisk_value(rawtx->coin,0,0,myinfo->myaddr.persistent,argjson,0) -// basilisk_bitcoinrawtx(rawtx->coin,"",basilisktag,jint(valsobj,"timeout"),valsobj,V) - - // included from basilisk.c /* https://bitcointalk.org/index.php?topic=1340621.msg13828271#msg13828271 https://bitcointalk.org/index.php?topic=1364951 @@ -130,6 +120,8 @@ void basilisk_rawtx_purge(struct basilisk_rawtx *rawtx) void basilisk_swap_finished(struct basilisk_swap *swap) { int32_t i; + if ( swap->utxo != 0 && swap->sentflag == 0 ) + LP_availableset(swap->utxo); swap->I.finished = (uint32_t)time(NULL); // save to permanent storage basilisk_rawtx_purge(&swap->bobdeposit); @@ -148,6 +140,8 @@ void basilisk_swap_finished(struct basilisk_swap *swap) free(swap->messages[i].data), swap->messages[i].data = 0; free(swap->messages), swap->messages = 0; swap->nummessages = 0; + if ( swap->N.pair >= 0 ) + nn_close(swap->N.pair), swap->N.pair = -1; } uint32_t basilisk_quoteid(struct basilisk_request *rp) @@ -257,6 +251,11 @@ int32_t LP_choosei_verify(struct basilisk_swap *swap,uint8_t *data,int32_t datal vcalc_sha256(0,swap->I.secretAm256,swap->I.privAm.bytes,sizeof(swap->I.privAm)); swap->I.pubAm = bitcoin_pubkey33(swap->ctx,pubkey33,swap->I.privAm); printf("set privAm.%s %s\n",bits256_str(str,swap->I.privAm),bits256_str(str2,*(bits256 *)swap->I.secretAm256)); + swap->bobdeposit.I.pubkey33[0] = 2; + swap->bobpayment.I.pubkey33[0] = 2; + for (i=0; i<32; i++) + swap->bobpayment.I.pubkey33[i+1] = swap->bobdeposit.I.pubkey33[i+1] = swap->I.pubA0.bytes[i]; + printf("SET bobdeposit pubkey33.(02%s)\n",bits256_str(str,swap->I.pubA0)); //basilisk_bobscripts_set(swap,0); } return(0); @@ -404,13 +403,15 @@ int32_t LP_waitfor(int32_t pairsock,struct basilisk_swap *swap,int32_t timeout,i void *data; int32_t datalen,retval = -1; uint32_t expiration = (uint32_t)time(NULL) + timeout; while ( time(NULL) < expiration ) { + //printf("start wait\n"); if ( (datalen= nn_recv(pairsock,&data,NN_MSG,0)) >= 0 ) { - printf("wait for got.%d\n",datalen); + //printf("wait for got.%d\n",datalen); retval = (*verify)(swap,data,datalen); nn_freemsg(data); + //printf("retval.%d\n",retval); return(retval); - } else printf("error nn_recv\n"); + } // else printf("error nn_recv\n"); } printf("waitfor timedout\n"); return(retval); @@ -419,30 +420,39 @@ int32_t LP_waitfor(int32_t pairsock,struct basilisk_swap *swap,int32_t timeout,i int32_t LP_waitsend(char *statename,int32_t timeout,int32_t pairsock,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen,int32_t (*verify)(struct basilisk_swap *swap,uint8_t *data,int32_t datalen),int32_t (*datagen)(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)) { int32_t datalen,sendlen,retval = -1; + printf("waitsend.%s\n",statename); if ( LP_waitfor(pairsock,swap,timeout,verify) == 0 ) { + printf("waited for %s\n",statename); if ( (datalen= (*datagen)(swap,data,maxlen)) > 0 ) { if ( (sendlen= nn_send(pairsock,data,datalen,0)) == datalen ) + { + printf("sent.%d after waitfor.%s\n",sendlen,statename); retval = 0; - else printf("send %s error\n",statename); - } - } else printf("didnt get valid data\n"); + } else printf("send %s error\n",statename); + } else printf("%s datagen no data\n",statename); + } else printf("didnt get valid data after %d\n",timeout); return(retval); } int32_t LP_sendwait(char *statename,int32_t timeout,int32_t pairsock,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen,int32_t (*verify)(struct basilisk_swap *swap,uint8_t *data,int32_t datalen),int32_t (*datagen)(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)) { int32_t datalen,sendlen,retval = -1; + //printf("sendwait.%s\n",statename); if ( (datalen= (*datagen)(swap,data,maxlen)) > 0 ) { + //printf("generated %d for %s\n",datalen,statename); if ( (sendlen= nn_send(pairsock,data,datalen,0)) == datalen ) { + //printf("sendwait.%s sent %d\n",statename,sendlen); if ( LP_waitfor(pairsock,swap,timeout,verify) == 0 ) + { + //printf("waited! sendwait.%s sent %d\n",statename,sendlen); retval = 0; - else printf("didnt get %s\n",statename); + } else printf("didnt get %s\n",statename); } else printf("send pubkeys error\n"); - } + } else printf("no datagen for %s\n",statename); return(retval); } @@ -456,7 +466,7 @@ void LP_swapsfp_update(struct basilisk_request *rp) if ( (swapsfp= fopen(fname,"rb+")) == 0 ) swapsfp = fopen(fname,"wb+"); else fseek(swapsfp,0,SEEK_END); - printf("LIST fp.%p\n",swapsfp); + //printf("LIST fp.%p\n",swapsfp); } if ( swapsfp != 0 ) { @@ -477,9 +487,90 @@ struct basilisk_rawtx *LP_swapdata_rawtx(struct basilisk_swap *swap,uint8_t *dat return(0); } +int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys) +{ + bits256 otherhash,myhash,txid; int32_t i,offset=0,datalen=0,retval=-1,hexlen,n; uint8_t *data; cJSON *txobj,*skey,*vouts,*vout; char *hexstr,redeemaddr[64],checkaddr[64]; uint32_t quoteid,msgbits; + for (i=0; i<32; i++) + otherhash.bytes[i] = recvbuf[offset++]; + for (i=0; i<32; i++) + myhash.bytes[i] = recvbuf[offset++]; + offset += iguana_rwnum(0,&recvbuf[offset],sizeof(quoteid),"eid); + offset += iguana_rwnum(0,&recvbuf[offset],sizeof(msgbits),&msgbits); + datalen = recvbuf[offset++]; + datalen += (int32_t)recvbuf[offset++] << 8; + if ( datalen > 1024 ) + { + printf("LP_rawtx_spendscript %s datalen.%d too big\n",rawtx->name,datalen); + return(-1); + } + rawtx->I.redeemlen = recvbuf[offset++]; + data = &recvbuf[offset]; + if ( rawtx->I.redeemlen > 0 && rawtx->I.redeemlen < 0x100 ) + { + memcpy(rawtx->redeemscript,&data[datalen],rawtx->I.redeemlen); + for (i=0; iI.redeemlen; i++) + printf("%02x",rawtx->redeemscript[i]); + bitcoin_address(redeemaddr,rawtx->coin->taddr,rawtx->coin->p2shtype,rawtx->redeemscript,rawtx->I.redeemlen); + printf(" received redeemscript.(%s) %s taddr.%d\n",redeemaddr,rawtx->coin->symbol,rawtx->coin->taddr); + LP_swap_coinaddr(swap,rawtx->coin,checkaddr,data,datalen); + if ( strcmp(redeemaddr,checkaddr) != 0 ) + { + printf("REDEEMADDR MISMATCH??? %s != %s\n",redeemaddr,checkaddr); + return(-1); + } + } + //printf("recvlen.%d datalen.%d redeemlen.%d\n",recvlen,datalen,rawtx->redeemlen); + if ( rawtx->I.datalen == 0 ) + { + //for (i=0; itxbytes,data,datalen); + rawtx->I.datalen = datalen; + } + else if ( datalen != rawtx->I.datalen || memcmp(rawtx->txbytes,data,datalen) != 0 ) + { + for (i=0; iI.datalen; i++) + printf("%02x",rawtx->txbytes[i]); + printf(" <- rawtx\n"); + printf("%s rawtx data compare error, len %d vs %d <<<<<<<<<< warning\n",rawtx->name,rawtx->I.datalen,datalen); + return(-1); + } + if ( recvlen != datalen+rawtx->I.redeemlen+75 ) + printf("RECVLEN %d != %d + %d\n",recvlen,datalen,rawtx->I.redeemlen); + txid = bits256_doublesha256(0,data,datalen); + //char str[65]; printf("rawtx.%s txid %s\n",rawtx->name,bits256_str(str,txid)); + if ( bits256_cmp(txid,rawtx->I.actualtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 ) + rawtx->I.actualtxid = txid; + if ( (txobj= bitcoin_data2json(rawtx->coin->taddr,rawtx->coin->pubtype,rawtx->coin->p2shtype,rawtx->coin->isPoS,height,&rawtx->I.signedtxid,&rawtx->msgtx,rawtx->extraspace,sizeof(rawtx->extraspace),data,datalen,0,suppress_pubkeys)) != 0 ) + { + rawtx->I.actualtxid = rawtx->I.signedtxid; + //char str[65]; printf("got %s txid.%s (%s)\n",rawtx->name,bits256_str(str,rawtx->I.signedtxid),jprint(txobj,0)); + rawtx->I.locktime = rawtx->msgtx.lock_time; + if ( (vouts= jarray(&n,txobj,"vout")) != 0 && v < n ) + { + vout = jitem(vouts,v); + if ( j64bits(vout,"satoshis") == rawtx->I.amount && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 ) + { + if ( (hexlen= (int32_t)strlen(hexstr) >> 1) < sizeof(rawtx->spendscript) ) + { + decode_hex(rawtx->spendscript,hexlen,hexstr); + rawtx->I.spendlen = hexlen; + bitcoin_address(rawtx->p2shaddr,rawtx->coin->taddr,rawtx->coin->p2shtype,rawtx->spendscript,hexlen); + //if ( swap != 0 ) + // basilisk_txlog(swap->myinfoptr,swap,rawtx,-1); // bobdeposit, bobpayment or alicepayment + retval = 0; + } + } else printf("%s ERROR.(%s)\n",rawtx->name,jprint(txobj,0)); + } + free_json(txobj); + } + return(retval); +} + 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) { - uint8_t sendbuf[32768]; int32_t sendlen; + uint8_t sendbuf[32768]; int32_t sendlen,retval = -1; if ( LP_swapdata_rawtx(swap,data,maxlen,rawtx) != 0 ) { if ( bits256_nonz(rawtx->I.signedtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 ) @@ -496,6 +587,7 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3 sendbuf[sendlen++] = rawtx->I.datalen & 0xff; sendbuf[sendlen++] = (rawtx->I.datalen >> 8) & 0xff; sendbuf[sendlen++] = rawtx->I.redeemlen; + //int32_t z; for (z=0; zI.datalen; z++) printf("%02x",rawtx->txbytes[z]); printf(" >>>>>>> send.%d %s\n",rawtx->I.datalen,rawtx->name); //printf("datalen.%d redeemlen.%d\n",rawtx->I.datalen,rawtx->I.redeemlen); memcpy(&sendbuf[sendlen],rawtx->txbytes,rawtx->I.datalen), sendlen += rawtx->I.datalen; if ( rawtx->I.redeemlen > 0 && rawtx->I.redeemlen < 0x100 ) @@ -506,7 +598,15 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3 basilisk_dontforget_update(swap,rawtx); //printf("sendlen.%d datalen.%d redeemlen.%d\n",sendlen,rawtx->datalen,rawtx->redeemlen); if ( suppress_swapsend == 0 ) - return(LP_swapsend(pairsock,swap,msgbits,sendbuf,sendlen,nextbits,rawtx->I.crcs)); + { + retval = LP_swapsend(pairsock,swap,msgbits,sendbuf,sendlen,nextbits,rawtx->I.crcs); + if ( LP_waitmempool(rawtx->coin->symbol,rawtx->I.signedtxid,LP_SWAPSTEP_TIMEOUT) < 0 ) + { + char str[65]; printf("failed to find %s %s in the mempool?\n",rawtx->name,bits256_str(str,rawtx->I.actualtxid)); + retval = -1; + } + return(retval); + } else { printf("suppress swapsend %x\n",msgbits); @@ -520,108 +620,162 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3 return(0); } -void LP_bobloop(void *_utxo) +int32_t LP_swapwait(uint32_t requestid,uint32_t quoteid,int32_t duration,int32_t sleeptime) +{ + char *retstr; cJSON *retjson=0; uint32_t divisor=8,expiration = (uint32_t)(time(NULL) + duration); + printf("wait %d:%d for SWAP.(r%u/q%u) to complete\n",duration,sleeptime,requestid,quoteid); + sleep(10); + if ( sleeptime < divisor*60 ) + sleeptime = divisor * 60; + while ( time(NULL) < expiration ) + { + if ( (retstr= basilisk_swapentry(requestid,quoteid)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( jstr(retjson,"status") != 0 && strcmp(jstr(retjson,"status"),"finished") == 0 ) + break; + free_json(retjson); + retjson = 0; + } + free(retstr); + } + sleep(sleeptime/divisor); + if ( divisor > 1 ) + divisor--; + } + if ( retjson != 0 ) + { + printf("\n>>>>>>>>>>>>>>>>>>>>>>>>>\nSWAP completed! %u-%u %s\n",requestid,quoteid,jprint(retjson,0)); + free_json(retjson); + if ( (retstr= basilisk_swapentry(requestid,quoteid)) != 0 ) + { + printf("second call.(%s)\n",retstr); + free(retstr); + } + return(0); + } else return(-1); +} + +void LP_bobloop(void *_swap) { - uint8_t *data; char *retstr; int32_t maxlen; uint32_t expiration; struct basilisk_swap *swap; struct LP_utxoinfo *utxo = _utxo; + uint8_t *data; int32_t maxlen,n; uint32_t expiration; struct basilisk_swap *swap = _swap; fprintf(stderr,"start swap iambob\n"); maxlen = 1024*1024 + sizeof(*swap); data = malloc(maxlen); - expiration = (uint32_t)time(NULL) + 10; - while ( (swap= utxo->swap) == 0 && time(NULL) < expiration ) - sleep(1); - if ( (utxo->swap= swap) != 0 ) + expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT; + if ( swap != 0 ) { - if ( LP_waitsend("pubkeys",10,utxo->pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) + if ( LP_waitsend("pubkeys",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) printf("error waitsend pubkeys\n"); - else if ( LP_waitsend("choosei",10,utxo->pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 ) + 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"); - else if ( LP_waitsend("mostprivs",10,utxo->pair,swap,data,maxlen,LP_mostprivs_verify,LP_mostprivs_data) < 0 ) + else if ( LP_waitsend("mostprivs",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_mostprivs_verify,LP_mostprivs_data) < 0 ) printf("error waitsend mostprivs\n"); else if ( basilisk_bobscripts_set(swap,1,1) < 0 ) printf("error bobscripts deposit\n"); else { + swap->bobrefund.utxovout = 0; + swap->bobrefund.utxotxid = swap->bobdeposit.I.signedtxid; + basilisk_bobdeposit_refund(swap,swap->I.putduration); + //printf("depositlen.%d\n",swap->bobdeposit.I.datalen); LP_swapsfp_update(&swap->I.req); - if ( LP_waitfor(utxo->pair,swap,10,LP_verify_otherfee) < 0 ) + if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT,LP_verify_otherfee) < 0 ) printf("error waiting for alicefee\n"); - else if ( LP_swapdata_rawtxsend(utxo->pair,swap,0x200,data,maxlen,&swap->bobdeposit,0x100,0) == 0 ) + else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x200,data,maxlen,&swap->bobdeposit,0x100,0) == 0 ) printf("error sending bobdeposit\n"); - else if ( LP_waitfor(utxo->pair,swap,10,LP_verify_alicepayment) < 0 ) + else if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT,LP_verify_alicepayment) < 0 ) printf("error waiting for alicepayment\n"); - else if ( basilisk_bobscripts_set(swap,0,1) < 0 ) - printf("error bobscripts payment\n"); - else if ( LP_swapdata_rawtxsend(utxo->pair,swap,0x8000,data,maxlen,&swap->bobpayment,0x4000,0) == 0 ) - printf("error sending bobpayment\n"); else { - printf("looping on swaplist\n"); - while ( 1 ) + if ( basilisk_bobscripts_set(swap,0,1) < 0 ) + printf("error bobscripts payment\n"); + else { - if ( (retstr= basilisk_swaplist()) != 0 ) + while ( (n= LP_numconfirms(swap,&swap->alicepayment)) < 1 ) // sync with alice { - printf("%s\n",retstr); - free(retstr); + char str[65];printf("%d waiting for alicepayment to be confirmed.%d %s %s\n",n,1,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid)); + sleep(3); } - sleep(100); + if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x8000,data,maxlen,&swap->bobpayment,0x4000,0) == 0 ) + printf("error sending bobpayment\n"); + swap->sentflag = 1; + swap->bobreclaim.utxovout = 0; + swap->bobreclaim.utxotxid = swap->bobpayment.I.signedtxid; + basilisk_bobpayment_reclaim(swap,swap->I.callduration); + if ( swap->N.pair >= 0 ) + nn_close(swap->N.pair), swap->N.pair = -1; + LP_swapwait(swap->I.req.requestid,swap->I.req.quoteid,4*3600,300); } } } basilisk_swap_finished(swap); - free(utxo->swap); + free(swap); } else printf("swap timed out\n"); - utxo->swap = 0; - nn_close(utxo->pair); - utxo->pair = -1; } -void LP_aliceloop(void *_qp) +void LP_aliceloop(void *_swap) { - uint8_t *data; char *retstr; int32_t maxlen; uint32_t expiration; struct basilisk_swap *swap = 0; struct LP_quoteinfo *qp = _qp; - fprintf(stderr,"start swap iamalice pair.%d\n",qp->pair); + uint8_t *data; int32_t maxlen,n; uint32_t expiration; struct basilisk_swap *swap = _swap; maxlen = 1024*1024 + sizeof(*swap); data = malloc(maxlen); - expiration = (uint32_t)time(NULL) + 10; - swap = LP_swapinit(0,0,qp->privkey,&qp->R,qp); + expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT; if ( swap != 0 ) { - if ( LP_sendwait("pubkeys",10,qp->pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) + fprintf(stderr,"start swap iamalice pair.%d\n",swap->N.pair); + if ( LP_sendwait("pubkeys",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) printf("error LP_sendwait pubkeys\n"); - else if ( LP_sendwait("choosei",10,qp->pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 ) + 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"); - else if ( LP_sendwait("mostprivs",10,qp->pair,swap,data,maxlen,LP_mostprivs_verify,LP_mostprivs_data) < 0 ) + else if ( LP_sendwait("mostprivs",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_mostprivs_verify,LP_mostprivs_data) < 0 ) printf("error LP_sendwait mostprivs\n"); - else if ( basilisk_alicetxs(qp->pair,swap,data,maxlen) != 0 ) + else if ( basilisk_alicetxs(swap->N.pair,swap,data,maxlen) != 0 ) printf("basilisk_alicetxs error\n"); else { LP_swapsfp_update(&swap->I.req); - if ( LP_swapdata_rawtxsend(qp->pair,swap,0x80,data,maxlen,&swap->myfee,0x40,0) == 0 ) + if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x80,data,maxlen,&swap->myfee,0x40,0) == 0 ) printf("error sending alicefee\n"); - else if ( LP_waitfor(qp->pair,swap,10,LP_verify_bobdeposit) < 0 ) + else if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT,LP_verify_bobdeposit) < 0 ) printf("error waiting for bobdeposit\n"); - else if ( LP_swapdata_rawtxsend(qp->pair,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0) == 0 ) + else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0) == 0 ) printf("error sending alicepayment\n"); - else if ( LP_waitfor(qp->pair,swap,10,LP_verify_bobpayment) < 0 ) - printf("error waiting for bobpayment\n"); else { - printf("looping on swaplist\n"); - while ( 1 ) + while ( (n= LP_numconfirms(swap,&swap->alicepayment)) < 1 ) { - if ( (retstr= basilisk_swaplist()) != 0 ) + char str[65];printf("%d waiting for alicepayment to be confirmed.%d %s %s\n",n,1,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid)); + sleep(LP_SWAPSTEP_TIMEOUT); + } + swap->sentflag = 1; + if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT,LP_verify_bobpayment) < 0 ) + printf("error waiting for bobpayment\n"); + else + { + while ( (n= LP_numconfirms(swap,&swap->bobpayment)) < swap->I.bobconfirms ) + { + char str[65];printf("%d waiting for bobpayment to be confirmed.%d %s %s\n",n,swap->I.bobconfirms,swap->bobcoin.symbol,bits256_str(str,swap->bobpayment.I.signedtxid)); + sleep(LP_SWAPSTEP_TIMEOUT); + } + if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x20000,data,maxlen,&swap->alicespend,0x40000,0) == 0 ) + printf("error sending alicespend\n"); + while ( (n= LP_numconfirms(swap,&swap->alicespend)) < swap->I.aliceconfirms ) { - printf("%s\n",retstr); - free(retstr); + char str[65];printf("%d waiting for alicespend to be confirmed.%d %s %s\n",n,swap->I.aliceconfirms,swap->bobcoin.symbol,bits256_str(str,swap->alicespend.I.signedtxid)); + sleep(LP_SWAPSTEP_TIMEOUT); } - sleep(100); + if ( swap->N.pair >= 0 ) + nn_close(swap->N.pair), swap->N.pair = -1; + LP_swapwait(swap->I.req.requestid,swap->I.req.quoteid,4*3600,300); } } } basilisk_swap_finished(swap); free(swap); } - nn_close(qp->pair); - free(qp); + free(data); + nn_close(swap->N.pair); } bits256 instantdex_derivekeypair(void *ctx,bits256 *newprivp,uint8_t pubkey[33],bits256 privkey,bits256 orderhash) @@ -704,6 +858,9 @@ int32_t instantdex_pubkeyargs(struct basilisk_swap *swap,int32_t numpubs,bits256 void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx *rawtx,struct iguana_info *coin,int32_t numconfirms,int32_t vintype,uint64_t satoshis,int32_t vouttype,uint8_t *pubkey33,int32_t jumblrflag) { +#ifdef BASILISK_DISABLEWAITTX + numconfirms = 0; +#endif strcpy(rawtx->name,name); rawtx->coin = coin; strcpy(rawtx->I.coinstr,coin->symbol); @@ -717,13 +874,13 @@ void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx * if ( strcmp(coin->symbol,"BTC") == 0 && (quoteid % 10) == 0 ) decode_hex(rawtx->I.rmd160,20,TIERNOLAN_RMD160); else decode_hex(rawtx->I.rmd160,20,INSTANTDEX_RMD160); - bitcoin_address(rawtx->I.destaddr,rawtx->coin->pubtype,rawtx->I.rmd160,20); + bitcoin_address(rawtx->I.destaddr,rawtx->coin->taddr,rawtx->coin->pubtype,rawtx->I.rmd160,20); } if ( pubkey33 != 0 ) { memcpy(rawtx->I.pubkey33,pubkey33,33); - bitcoin_address(rawtx->I.destaddr,rawtx->coin->pubtype,rawtx->I.pubkey33,33); - bitcoin_addr2rmd160(&rawtx->I.addrtype,rawtx->I.rmd160,rawtx->I.destaddr); + bitcoin_address(rawtx->I.destaddr,rawtx->coin->taddr,rawtx->coin->pubtype,rawtx->I.pubkey33,33); + bitcoin_addr2rmd160(rawtx->coin->taddr,&rawtx->I.addrtype,rawtx->I.rmd160,rawtx->I.destaddr); } if ( rawtx->I.vouttype <= 1 && rawtx->I.destaddr[0] != 0 ) { @@ -732,10 +889,10 @@ 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 basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 pubkey25519,struct basilisk_swap *swap,int32_t optionduration,uint32_t statebits,struct LP_quoteinfo *qp) { //FILE *fp; char fname[512]; - uint8_t *alicepub33=0,*bobpub33=0; int32_t jumblrflag=-2,x = -1; struct iguana_info *coin; + uint8_t *alicepub33=0,*bobpub33=0; int32_t bobistrusted,aliceistrusted,jumblrflag=-2,x = -1; struct iguana_info *coin; swap->I.putduration = swap->I.callduration = INSTANTDEX_LOCKTIME; if ( optionduration < 0 ) swap->I.putduration -= optionduration; @@ -761,11 +918,15 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 { swap->I.iambob = 0; swap->I.otherhash = swap->I.req.desthash; + aliceistrusted = 1; + bobistrusted = LP_pubkey_istrusted(swap->I.req.desthash); } else { swap->I.iambob = 1; swap->I.otherhash = swap->I.req.srchash; + bobistrusted = 1; + aliceistrusted = LP_pubkey_istrusted(swap->I.req.desthash); } if ( bits256_nonz(privkey) == 0 || (x= instantdex_pubkeyargs(swap,2 + INSTANTDEX_DECKSIZE,privkey,swap->I.orderhash,0x02+swap->I.iambob)) != 2 + INSTANTDEX_DECKSIZE ) { @@ -790,41 +951,38 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 } if ( strcmp("BTC",swap->bobcoin.symbol) == 0 ) { - swap->I.bobconfirms = (1*0 + sqrt(dstr(swap->I.bobsatoshis) * .1)); - swap->I.aliceconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.bobconfirms * 3); + swap->I.bobconfirms = (1 + sqrt(dstr(swap->I.bobsatoshis) * .1)); + swap->I.aliceconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.bobconfirms); } else if ( strcmp("BTC",swap->alicecoin.symbol) == 0 ) { - swap->I.aliceconfirms = (1*0 + sqrt(dstr(swap->I.alicesatoshis) * .1)); - swap->I.bobconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.bobconfirms * 3); + swap->I.aliceconfirms = (1 + sqrt(dstr(swap->I.alicesatoshis) * .1)); + swap->I.bobconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.aliceconfirms); } else { swap->I.bobconfirms = BASILISK_DEFAULT_NUMCONFIRMS; swap->I.aliceconfirms = BASILISK_DEFAULT_NUMCONFIRMS; } - /*if ( swap->I.bobconfirms == 0 ) - swap->I.bobconfirms = swap->bobcoin->chain->minconfirms; - if ( swap->I.aliceconfirms == 0 ) - swap->I.aliceconfirms = swap->alicecoin->chain->minconfirms;*/ - //jumblrflag = (bits256_cmp(pubkey25519,myinfo->jumblr_pubkey) == 0 || bits256_cmp(pubkey25519,myinfo->jumblr_depositkey) == 0); - printf(">>>>>>>>>> jumblrflag.%d <<<<<<<<< use smart address, %.8f bobconfs.%d, %.8f aliceconfs.%d\n",jumblrflag,dstr(swap->I.bobsatoshis),swap->I.bobconfirms,dstr(swap->I.alicesatoshis),swap->I.aliceconfirms); + swap->I.bobconfirms *= !bobistrusted; + swap->I.aliceconfirms *= !aliceistrusted; + printf(">>>>>>>>>> jumblrflag.%d <<<<<<<<< use smart address, %.8f bobconfs.%d, %.8f aliceconfs.%d taddr.%d %d\n",jumblrflag,dstr(swap->I.bobsatoshis),swap->I.bobconfirms,dstr(swap->I.alicesatoshis),swap->I.aliceconfirms,swap->bobcoin.taddr,swap->alicecoin.taddr); if ( swap->I.iambob != 0 ) { - basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,&swap->bobcoin,0,0,swap->I.bobsatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag); - basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,&swap->alicecoin,0,0,swap->I.alicesatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag); + basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,&swap->bobcoin,0,0,LP_DEXFEE(swap->I.bobsatoshis),0,0,jumblrflag); + basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,&swap->alicecoin,0,0,LP_DEXFEE(swap->I.alicesatoshis),0,0,jumblrflag); bobpub33 = pubkey33; } else { - basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,&swap->bobcoin,0,0,swap->I.bobsatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag); - basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,&swap->alicecoin,0,0,swap->I.alicesatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag); + basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,&swap->bobcoin,0,0,LP_DEXFEE(swap->I.bobsatoshis),0,0,jumblrflag); + basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,&swap->alicecoin,0,0,LP_DEXFEE(swap->I.alicesatoshis),0,0,jumblrflag); alicepub33 = pubkey33; } - basilisk_rawtx_setparms("bobdeposit",swap->I.req.quoteid,&swap->bobdeposit,&swap->bobcoin,swap->I.bobconfirms,0,swap->I.bobsatoshis + (swap->I.bobsatoshis>>3) + swap->bobcoin.txfee,4,0,jumblrflag); - basilisk_rawtx_setparms("bobrefund",swap->I.req.quoteid,&swap->bobrefund,&swap->bobcoin,1,4,swap->I.bobsatoshis + (swap->I.bobsatoshis>>3),1,bobpub33,jumblrflag); + basilisk_rawtx_setparms("bobdeposit",swap->I.req.quoteid,&swap->bobdeposit,&swap->bobcoin,swap->I.bobconfirms,0,LP_DEPOSITSATOSHIS(swap->I.bobsatoshis) + swap->bobcoin.txfee,4,0,jumblrflag); + basilisk_rawtx_setparms("bobrefund",swap->I.req.quoteid,&swap->bobrefund,&swap->bobcoin,1,4,LP_DEPOSITSATOSHIS(swap->I.bobsatoshis),1,bobpub33,jumblrflag); swap->bobrefund.I.suppress_pubkeys = 1; - basilisk_rawtx_setparms("aliceclaim",swap->I.req.quoteid,&swap->aliceclaim,&swap->bobcoin,1,4,swap->I.bobsatoshis + (swap->I.bobsatoshis>>3),1,alicepub33,jumblrflag); + basilisk_rawtx_setparms("aliceclaim",swap->I.req.quoteid,&swap->aliceclaim,&swap->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; @@ -839,7 +997,13 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 swap->bobspend.I.suppress_pubkeys = 1; basilisk_rawtx_setparms("alicereclaim",swap->I.req.quoteid,&swap->alicereclaim,&swap->alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,alicepub33,jumblrflag); swap->alicereclaim.I.suppress_pubkeys = 1; - printf("IAMBOB.%d\n",swap->I.iambob); + swap->bobpayment.utxotxid = qp->txid, swap->bobpayment.utxovout = qp->vout; + swap->bobdeposit.utxotxid = qp->txid2, swap->bobdeposit.utxovout = qp->vout2; + swap->alicepayment.utxotxid = qp->desttxid, swap->alicepayment.utxovout = qp->destvout; + if ( swap->I.iambob != 0 ) + swap->otherfee.utxotxid = qp->feetxid, swap->otherfee.utxovout = qp->feevout; + else swap->myfee.utxotxid = qp->feetxid, swap->myfee.utxovout = qp->feevout; + char str[65],str2[65],str3[65]; printf("IAMBOB.%d %s %s %s\n",swap->I.iambob,bits256_str(str,qp->txid),bits256_str(str2,qp->txid2),bits256_str(str3,qp->feetxid)); return(swap); } @@ -857,18 +1021,12 @@ 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) == 0 ) + if ( bitcoin_swapinit(privkey,pubkey33,pubkey25519,swap,optionduration,!iambob,qp) == 0 ) { printf("error doing swapinit\n"); free(swap); swap = 0; } - swap->bobpayment.utxotxid = qp->txid, swap->bobpayment.utxovout = qp->vout; - swap->bobdeposit.utxotxid = qp->txid2, swap->bobdeposit.utxovout = qp->vout2; - swap->alicepayment.utxotxid = qp->desttxid, swap->alicepayment.utxovout = qp->destvout; - if ( iambob != 0 ) - swap->otherfee.utxotxid = qp->feetxid, swap->otherfee.utxovout = qp->feevout; - else swap->myfee.utxotxid = qp->feetxid, swap->myfee.utxovout = qp->feevout; return(swap); } diff --git a/iguana/exchanges/LP_transaction.c b/iguana/exchanges/LP_transaction.c index 193c20475..2e3d57a89 100644 --- a/iguana/exchanges/LP_transaction.c +++ b/iguana/exchanges/LP_transaction.c @@ -19,11 +19,11 @@ // -bits256 LP_broadcast(char *txname,char *symbol,char *txbytes) +bits256 LP_broadcast(char *txname,char *symbol,char *txbytes,bits256 expectedtxid) { - char *retstr; bits256 txid; int32_t i,sentflag = 0; + char *retstr; bits256 txid; cJSON *retjson,*errorobj; int32_t i,sentflag = 0; memset(&txid,0,sizeof(txid)); - for (i=0; i<3; i++) + for (i=0; i<1; i++) { if ( (retstr= LP_sendrawtransaction(symbol,txbytes)) != 0 ) { @@ -32,6 +32,18 @@ bits256 LP_broadcast(char *txname,char *symbol,char *txbytes) decode_hex(txid.bytes,32,retstr); sentflag = 1; } + else if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( (errorobj= jobj(retjson,"error")) != 0 ) + { + if ( jint(errorobj,"code") == -27 ) // "transaction already in block chain" + { + txid = expectedtxid; + sentflag = 1; + } + } + free_json(retjson); + } char str[65]; printf("[%s] %s RETSTR.(%s) %s.%s\n",txname,txbytes,retstr,symbol,bits256_str(str,txid)); free(retstr); } @@ -47,22 +59,20 @@ bits256 LP_broadcast_tx(char *name,char *symbol,uint8_t *data,int32_t datalen) memset(txid.bytes,0,sizeof(txid)); if ( data != 0 && datalen != 0 ) { - char str[65]; -#ifdef BASILISK_DISABLESENDTX - txid = bits256_doublesha256(0,data,datalen); - printf("%s <- dont sendrawtransaction (%s)\n",name,bits256_str(str,txid)); - return(txid); -#endif signedtx = malloc(datalen*2 + 1); init_hexbytes_noT(signedtx,data,datalen); - txid = LP_broadcast(name,symbol,signedtx); - // sent to nn_socket! + txid = bits256_doublesha256(0,data,datalen); +#ifdef BASILISK_DISABLESENDTX + char str[65]; printf("%s <- dont sendrawtransaction (%s) %s\n",name,bits256_str(str,txid),signedtx); +#else + txid = LP_broadcast(name,symbol,signedtx,txid); +#endif free(signedtx); } return(txid); } -uint64_t LP_txvalue(char *symbol,bits256 txid,int32_t vout) +uint64_t oldLP_txvalue(char *symbol,bits256 txid,int32_t vout) { uint64_t value = 0; double interest; cJSON *txobj,*vouts,*utxoobj; int32_t numvouts; if ( (txobj= LP_gettx(symbol,txid)) != 0 ) @@ -81,7 +91,7 @@ uint64_t LP_txvalue(char *symbol,bits256 txid,int32_t vout) { if ( (interest= jdouble(utxoobj,"interest")) != 0. ) { - printf("add interest of %.8f to %.8f\n",interest,dstr(value)); + //printf("add interest of %.8f to %.8f\n",interest,dstr(value)); value += SATOSHIDEN * interest; } free_json(utxoobj); @@ -93,20 +103,181 @@ uint64_t LP_txvalue(char *symbol,bits256 txid,int32_t vout) return(value); } +uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout) +{ + uint64_t value = 0; double interest; cJSON *txobj,*sobj,*array; int32_t n; + coinaddr[0] = 0; + if ( (txobj= LP_gettxout(symbol,txid,vout)) != 0 ) + { + if ( (value= jdouble(txobj,"amount")*SATOSHIDEN) == 0 && (value= jdouble(txobj,"value")*SATOSHIDEN) == 0 ) + { + char str[65]; printf("%s LP_txvalue.%s strange utxo.(%s) vout.%d\n",symbol,bits256_str(str,txid),jprint(txobj,0),vout); + } + else if ( strcmp(symbol,"KMD") == 0 ) + { + if ( (interest= jdouble(txobj,"interest")) != 0. ) + { + //printf("add interest of %.8f to %.8f\n",interest,dstr(value)); + value += SATOSHIDEN * interest; + } + } + if ( (sobj= jobj(txobj,"scriptPubKey")) != 0 && (array= jarray(&n,sobj,"addresses")) != 0 ) + strcpy(coinaddr,jstri(array,0)); + //char str[65]; printf("%.8f <- %s.(%s) txobj.(%s)\n",dstr(value),symbol,bits256_str(str,txid),jprint(txobj,0)); + free_json(txobj); + } + return(value); +} + +int32_t LP_vinscan(bits256 *spendtxidp,int32_t *spendvinip,char *symbol,bits256 txid,bits256 searchtxid,int32_t searchvout,bits256 searchtxid2,int32_t searchvout2) +{ + cJSON *txobj,*vins,*vin; bits256 spenttxid; int32_t j,numvins,spentvout,retval = -1; + if ( (txobj= LP_gettx(symbol,txid)) != 0 ) + { + if ( bits256_cmp(txid,jbits256(txobj,"txid")) != 0 ) + { + char str[65]; printf("txid mismatch error %s vs %s\n",bits256_str(str,txid),jprint(txobj,0)); + free_json(txobj); + return(-2); + } + vins = jarray(&numvins,txobj,"vin"); + for (j=0; j 0 ) + return(0); + if ( (txobj= LP_gettx(symbol,searchtxid)) == 0 ) + return(0); + hash = jbits256(txobj,"blockhash"); + free_json(txobj); + if ( bits256_nonz(hash) == 0 ) + return(0); + if ( (blockjson= LP_getblock(symbol,hash)) == 0 ) + return(0); + loadheight = jint(blockjson,"height"); + free_json(blockjson); + if ( loadheight <= 0 ) + return(0); + while ( errs == 0 && *indp < 0 ) + { + //printf("search %s ht.%d\n",symbol,loadheight); + if ( (blockjson= LP_blockjson(&h,symbol,0,loadheight)) != 0 && h == loadheight ) + { + if ( (txids= jarray(&numtxids,blockjson,"tx")) != 0 ) + { + for (i=0; i= 0 ) + break; + } + } + free_json(blockjson); + } else errs++; + loadheight++; + } + char str[65]; printf("reached %s ht.%d %s/v%d\n",symbol,loadheight,bits256_str(str,*spendtxidp),*indp); + if ( bits256_nonz(*spendtxidp) != 0 && *indp >= 0 ) + return(loadheight); + else return(0); +} + +int32_t LP_mempoolscan(char *symbol,bits256 txid) +{ + int32_t i,n; cJSON *array; + if ( (array= LP_getmempool(symbol)) != 0 ) + { + if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; i 0 ) + { + for (i=0; i= 0 ) + return(i); + } + free_json(array); + } + } + return(-1); +} + int32_t LP_numconfirms(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx) { int32_t numconfirms = 100; -#ifndef BASILISK_DISABLEWAITTX +//#ifndef BASILISK_DISABLEWAITTX cJSON *txobj; - if ( (txobj= LP_gettx(symbol,txid)) != 0 ) + numconfirms = -1; + if ( (txobj= LP_gettx(rawtx->coin->symbol,rawtx->I.signedtxid)) != 0 ) { numconfirms = jint(txobj,"confirmations"); free_json(txobj); } -#endif + else if ( LP_mempoolscan(rawtx->coin->symbol,rawtx->I.signedtxid) >= 0 ) + numconfirms = 0; +//#endif return(numconfirms); } +int32_t LP_waitmempool(char *symbol,bits256 txid,int32_t duration) +{ + uint32_t expiration = (uint32_t)time(NULL) + duration; + while ( time(NULL) < expiration ) + { + if ( LP_mempoolscan(symbol,txid) >= 0 ) + return(0); + usleep(250000); + } + return(-1); +} + int32_t iguana_msgtx_Vset(uint8_t *serialized,int32_t maxlen,struct iguana_msgtx *msgtx,struct vin_info *V) { int32_t vini,j,scriptlen,p2shlen,userdatalen,siglen,plen,need_op0=0,len = 0; uint8_t *script,*redeemscript=0,*userdata=0; struct vin_info *vp; @@ -225,6 +396,7 @@ int32_t iguana_interpreter(struct iguana_info *coin,cJSON *logarray,int64_t nLoc if ( activescriptlen < 16 ) continue; //printf("interpreter.(%s)\n",jprint(spendscript,0)); + //printf("bitcoin_assembler ignore_cltverr.%d suppress.%d\n",V[vini].ignore_cltverr,V[vini].suppress_pubkeys); if ( (scriptlen= bitcoin_assembler(coin,logarray,script,spendscript,1,nLockTime,&V[vini])) < 0 ) { //printf("bitcoin_assembler error scriptlen.%d\n",scriptlen); @@ -283,7 +455,7 @@ bits256 iguana_str2priv(char *str) return(privkey); } -int32_t iguana_vininfo_create(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msgtx,cJSON *vins,int32_t numinputs,struct vin_info *V) +int32_t iguana_vininfo_create(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msgtx,cJSON *vins,int32_t numinputs,struct vin_info *V) { int32_t i,plen,finalized = 1,len = 0; struct vin_info *vp; //struct iguana_waccount *wacct; struct iguana_waddress *waddr; uint32_t sigsize,pubkeysize,p2shsize,userdatalen; msgtx->tx_in = numinputs; @@ -315,9 +487,9 @@ int32_t iguana_vininfo_create(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uin { memcpy(vp->spendscript,msgtx->vins[i].spendscript,msgtx->vins[i].spendlen); vp->spendlen = msgtx->vins[i].spendlen; - _iguana_calcrmd160(pubtype,p2shtype,vp); + _iguana_calcrmd160(taddr,pubtype,p2shtype,vp); if ( (plen= bitcoin_pubkeylen(vp->signers[0].pubkey)) > 0 ) - bitcoin_address(vp->coinaddr,pubtype,vp->signers[0].pubkey,plen); + bitcoin_address(vp->coinaddr,taddr,pubtype,vp->signers[0].pubkey,plen); } if ( vp->M == 0 && vp->N == 0 ) vp->M = vp->N = 1; @@ -335,7 +507,7 @@ int32_t iguana_vininfo_create(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uin return(finalized); } -int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *signedtxidp,char **signedtx,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxlen,struct vin_info *V,uint32_t sighash,int32_t signtx,int32_t suppress_pubkeys) +int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *signedtxidp,char **signedtx,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxlen,struct vin_info *V,uint32_t sighash,int32_t signtx,int32_t suppress_pubkeys) { bits256 sigtxid; uint8_t *sig,*script; struct vin_info *vp; char vpnstr[64]; int32_t scriptlen,complete=0,j,vini=0,flag=0,siglen,numvouts,numsigs; numvouts = msgtx->tx_out; @@ -357,7 +529,7 @@ int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t pubtype,uint8_t p2shty script = msgtx->vins[vini].spendscript; scriptlen = msgtx->vins[vini].spendlen; } - sigtxid = bitcoin_sigtxid(pubtype,p2shtype,isPoS,height,serialized,maxlen,msgtx,vini,script,scriptlen,sighash,vpnstr,suppress_pubkeys); + sigtxid = bitcoin_sigtxid(taddr,pubtype,p2shtype,isPoS,height,serialized,maxlen,msgtx,vini,script,scriptlen,sighash,vpnstr,suppress_pubkeys); if ( bits256_nonz(sigtxid) != 0 ) { vp = &V[vini]; @@ -397,14 +569,14 @@ int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t pubtype,uint8_t p2shty { flag++; numsigs++; - int32_t z; char tmpaddr[64]; + /*int32_t z; char tmpaddr[64]; for (z=0; zsigners[j].pubkey[z]); bitcoin_address(tmpaddr,60,vp->signers[j].pubkey,33); - printf(" <- pub, SIG.%d.%d VERIFIED numsigs.%d vs M.%d %s\n",vini,j,numsigs,vp->M,tmpaddr); + printf(" <- pub, SIG.%d.%d VERIFIED numsigs.%d vs M.%d %s\n",vini,j,numsigs,vp->M,tmpaddr);*/ } } if ( numsigs >= vp->M ) @@ -413,7 +585,7 @@ int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t pubtype,uint8_t p2shty } iguana_msgtx_Vset(serialized,maxlen,msgtx,V); cJSON *txobj = cJSON_CreateObject(); - *signedtx = iguana_rawtxbytes(pubtype,p2shtype,isPoS,height,txobj,msgtx,suppress_pubkeys); + *signedtx = iguana_rawtxbytes(taddr,pubtype,p2shtype,isPoS,height,txobj,msgtx,suppress_pubkeys); //printf("SIGNEDTX.(%s)\n",jprint(txobj,1)); *signedtxidp = msgtx->txid; return(complete); @@ -427,7 +599,7 @@ int64_t iguana_lockval(int32_t finalized,int64_t locktime) return(lockval); } -int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,struct iguana_msgtx *msgtx,char **signedtxp,bits256 *signedtxidp,struct vin_info *V,int32_t numinputs,char *rawtx,cJSON *vins,cJSON *privkeysjson) +int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t 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) { uint8_t *serialized,*serialized2,*serialized3,*serialized4,*extraspace,pubkeys[64][33]; int32_t finalized,i,len,n,z,plen,maxsize,complete = 0,extralen = 65536; char *privkeystr,*signedtx = 0; bits256 privkeys[64],privkey,txid; cJSON *item; cJSON *txobj = 0; maxsize = 1000000; @@ -442,7 +614,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t pubtype,uint8_t memset(msgtx,0,sizeof(*msgtx)); decode_hex(serialized,len,rawtx); // printf("call hex2json.(%s) vins.(%s)\n",rawtx,jprint(vins,0)); - if ( (txobj= bitcoin_hex2json(pubtype,p2shtype,isPoS,height,&txid,msgtx,rawtx,extraspace,extralen,serialized4,vins,V->suppress_pubkeys)) != 0 ) + if ( (txobj= bitcoin_hex2json(taddr,pubtype,p2shtype,isPoS,height,&txid,msgtx,rawtx,extraspace,extralen,serialized4,vins,V->suppress_pubkeys)) != 0 ) { //printf("back from bitcoin_hex2json (%s)\n",jprint(vins,0)); } else fprintf(stderr,"no txobj from bitcoin_hex2json\n"); @@ -450,7 +622,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t pubtype,uint8_t { //printf("numinputs.%d msgtx.%d\n",numinputs,msgtx->tx_in); memset(msgtx,0,sizeof(*msgtx)); - if ( iguana_rwmsgtx(pubtype,p2shtype,isPoS,height,0,0,serialized,maxsize,msgtx,&txid,"",extraspace,65536,vins,V->suppress_pubkeys) > 0 && numinputs == msgtx->tx_in ) + if ( iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,0,0,serialized,maxsize,msgtx,&txid,"",extraspace,65536,vins,V->suppress_pubkeys) > 0 && numinputs == msgtx->tx_in ) { memset(pubkeys,0,sizeof(pubkeys)); memset(privkeys,0,sizeof(privkeys)); @@ -478,14 +650,14 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t pubtype,uint8_t coinaddr[0] = 0; sigsize = 0; flag = (msgtx->vins[i].vinscript[0] == 0); - type = bitcoin_scriptget(pubtype,p2shtype,&hashtype,&sigsize,&pubkeysize,&userdata,&userdatalen,&mainvin,msgtx->vins[i].vinscript+flag,msgtx->vins[i].scriptlen-flag,0); + type = bitcoin_scriptget(taddr,pubtype,p2shtype,&hashtype,&sigsize,&pubkeysize,&userdata,&userdatalen,&mainvin,msgtx->vins[i].vinscript+flag,msgtx->vins[i].scriptlen-flag,0); //printf("i.%d flag.%d type.%d scriptlen.%d\n",i,flag,type,msgtx->vins[i].scriptlen); if ( msgtx->vins[i].redeemscript != 0 ) { //for (j=0; jvins[i].p2shlen; j++) // printf("%02x",msgtx->vins[i].redeemscript[j]); - bitcoin_address(coinaddr,p2shtype,msgtx->vins[i].redeemscript,msgtx->vins[i].p2shlen); - type = iguana_calcrmd160(pubtype,p2shtype,0,&mvin,msgtx->vins[i].redeemscript,msgtx->vins[i].p2shlen,zero,0,0); + bitcoin_address(coinaddr,taddr,p2shtype,msgtx->vins[i].redeemscript,msgtx->vins[i].p2shlen); + type = iguana_calcrmd160(taddr,pubtype,p2shtype,0,&mvin,msgtx->vins[i].redeemscript,msgtx->vins[i].p2shlen,zero,0,0); for (j=0; jsuppress_pubkeys == 0 ) @@ -535,16 +707,16 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t pubtype,uint8_t } } } - finalized = iguana_vininfo_create(pubtype,p2shtype,isPoS,serialized2,maxsize,msgtx,vins,numinputs,V); - printf("finalized.%d\n",finalized); - if ( (complete= bitcoin_verifyvins(ctx,symbol,pubtype,p2shtype,isPoS,height,signedtxidp,&signedtx,msgtx,serialized3,maxsize,V,SIGHASH_ALL,1,V->suppress_pubkeys)) > 0 && signedtx != 0 ) + finalized = iguana_vininfo_create(taddr,pubtype,p2shtype,isPoS,serialized2,maxsize,msgtx,vins,numinputs,V); + //printf("finalized.%d ignore_cltverr.%d suppress.%d\n",finalized,V[0].ignore_cltverr,V[0].suppress_pubkeys); + if ( (complete= bitcoin_verifyvins(ctx,symbol,taddr,pubtype,p2shtype,isPoS,height,signedtxidp,&signedtx,msgtx,serialized3,maxsize,V,SIGHASH_ALL,1,V->suppress_pubkeys)) > 0 && signedtx != 0 ) { - int32_t tmp; //char str[65]; + /*int32_t tmp; //char str[65]; if ( (tmp= iguana_interpreter(ctx,cJSON_CreateArray(),iguana_lockval(finalized,jint(txobj,"locktime")),V,numinputs)) < 0 ) { printf("iguana_interpreter %d error.(%s)\n",tmp,signedtx); complete = 0; - } else printf("interpreter passed\n"); + } else printf("interpreter passed\n");*/ } else printf("complete.%d\n",complete); } else printf("rwmsgtx error\n"); } else fprintf(stderr,"no inputs in vins.(%s)\n",vins!=0?jprint(vins,0):"null"); @@ -557,9 +729,9 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t pubtype,uint8_t return(complete); } -char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privkey,bits256 *privkey2p,uint8_t *redeemscript,int32_t redeemlen,uint8_t *userdata,int32_t userdatalen,bits256 utxotxid,int32_t vout,char *destaddr,uint8_t *pubkey33,int32_t finalseqid,uint32_t expiration,int64_t *destamountp,uint64_t satoshis,char *changeaddr,char *vinaddr,int32_t suppress_pubkeys) +char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privkey,bits256 *privkey2p,uint8_t *redeemscript,int32_t redeemlen,uint8_t *userdata,int32_t userdatalen,bits256 utxotxid,int32_t vout,char *destaddr,uint8_t *pubkey33,int32_t finalseqid,uint32_t expiration,int64_t *destamountp,uint64_t satoshis,char *changeaddr,char *vinaddr,int32_t suppress_pubkeys) { - char *rawtxbytes=0,*signedtx=0,str[65],tmpaddr[64],hexstr[999],wifstr[128],_destaddr[64]; uint8_t spendscript[512],addrtype,rmd160[20]; cJSON *txobj,*vins,*item,*privkeys; int32_t completed,spendlen,ignore_cltverr=1; struct vin_info V[16]; uint32_t timestamp,locktime = 0,sequenceid = 0xffffffff * finalseqid; bits256 txid; uint64_t value,change = 0; struct iguana_msgtx msgtx; + char *rawtxbytes=0,*signedtx=0,tmpaddr[64],hexstr[999],wifstr[128],txdestaddr[64],_destaddr[64]; uint8_t spendscript[512],addrtype,rmd160[20]; cJSON *txobj,*vins,*item,*privkeys; int32_t completed,spendlen,ignore_cltverr=1; struct vin_info V[2]; uint32_t timestamp,locktime = 0,sequenceid = 0xffffffff * finalseqid; bits256 txid; uint64_t value,change = 0; struct iguana_msgtx msgtx; *destamountp = 0; memset(signedtxidp,0,sizeof(*signedtxidp)); if ( finalseqid == 0 ) @@ -567,11 +739,16 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch //printf("bobtxspend.%s redeem.[%d]\n",symbol,redeemlen); if ( redeemlen < 0 ) return(0); - if ( (value= LP_txvalue(symbol,utxotxid,vout)) == 0 ) +#ifndef BASILISK_DISABLESENDTX + if ( (value= LP_txvalue(txdestaddr,symbol,utxotxid,vout)) == 0 ) { + char str[65]; printf("basilisk_swap_bobtxspend.%s %s utxo.(%s) already spent or doesnt exist\n",name,symbol,bits256_str(str,utxotxid)); return(0); } +#else + value = satoshis; +#endif if ( satoshis != 0 ) { if ( value > satoshis+txfee ) @@ -580,7 +757,8 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch } else if ( value > txfee ) satoshis = value - txfee; else printf("unexpected small value %.8f vs txfee %.8f\n",dstr(value),dstr(txfee)); - *destamountp = satoshis; + if ( destamountp != 0 ) + *destamountp = satoshis; timestamp = (uint32_t)time(NULL); memset(V,0,sizeof(V)); privkeys = cJSON_CreateArray(); @@ -612,16 +790,16 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch } jaddbits256(item,"txid",utxotxid); jaddnum(item,"vout",vout); - bitcoin_address(tmpaddr,pubtype,pubkey33,33); - bitcoin_addr2rmd160(&addrtype,rmd160,tmpaddr); + bitcoin_address(tmpaddr,taddr,pubtype,pubkey33,33); + bitcoin_addr2rmd160(taddr,&addrtype,rmd160,tmpaddr); if ( redeemlen != 0 ) { init_hexbytes_noT(hexstr,redeemscript,redeemlen); jaddstr(item,"redeemScript",hexstr); if ( vinaddr != 0 ) - bitcoin_addr2rmd160(&addrtype,rmd160,vinaddr); + bitcoin_addr2rmd160(taddr,&addrtype,rmd160,vinaddr); spendlen = bitcoin_p2shspend(spendscript,0,rmd160); - printf("P2SH path.%s\n",vinaddr!=0?vinaddr:0); + //printf("P2SH path.%s\n",vinaddr!=0?vinaddr:0); } else spendlen = bitcoin_standardspend(spendscript,0,rmd160); init_hexbytes_noT(hexstr,spendscript,spendlen); jaddstr(item,"scriptPubKey",hexstr); @@ -633,17 +811,23 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch if ( destaddr == 0 ) { destaddr = _destaddr; - bitcoin_address(destaddr,pubtype,pubkey33,33); + bitcoin_address(destaddr,taddr,pubtype,pubkey33,33); } - bitcoin_addr2rmd160(&addrtype,rmd160,destaddr); + bitcoin_addr2rmd160(taddr,&addrtype,rmd160,destaddr); if ( addrtype == p2shtype ) spendlen = bitcoin_p2shspend(spendscript,0,rmd160); else spendlen = bitcoin_standardspend(spendscript,0,rmd160); + if ( change != 0 && strcmp(changeaddr,destaddr) == 0 ) + { + printf("combine change %.8f -> %s\n",dstr(change),changeaddr); + satoshis += change; + change = 0; + } txobj = bitcoin_txoutput(txobj,spendscript,spendlen,satoshis); if ( change != 0 ) { int32_t changelen; uint8_t changescript[1024],changetype,changermd160[20]; - bitcoin_addr2rmd160(&changetype,changermd160,changeaddr); + bitcoin_addr2rmd160(taddr,&changetype,changermd160,changeaddr); changelen = bitcoin_standardspend(changescript,0,changermd160); txobj = bitcoin_txoutput(txobj,changescript,changelen,change); } @@ -653,7 +837,7 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch completed = 0; memset(signedtxidp,0,sizeof(*signedtxidp)); //printf("locktime.%u sequenceid.%x rawtx.(%s) vins.(%s)\n",locktime,sequenceid,rawtxbytes,jprint(vins,0)); - if ( (completed= iguana_signrawtransaction(ctx,symbol,pubtype,p2shtype,isPoS,1000000,&msgtx,&signedtx,signedtxidp,V,1,rawtxbytes,vins,privkeys)) < 0 ) + if ( (completed= iguana_signrawtransaction(ctx,symbol,taddr,pubtype,p2shtype,isPoS,1000000,&msgtx,&signedtx,signedtxidp,V,1,rawtxbytes,vins,privkeys)) < 0 ) //if ( (signedtx= LP_signrawtx(symbol,signedtxidp,&completed,vins,rawtxbytes,privkeys,V)) == 0 ) printf("couldnt sign transaction.%s %s\n",name,bits256_str(str,*signedtxidp)); else if ( completed == 0 ) @@ -661,7 +845,7 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch printf("incomplete signing suppress.%d %s (%s)\n",suppress_pubkeys,name,jprint(vins,0)); if ( signedtx != 0 ) free(signedtx), signedtx = 0; - } else printf("%s -> %s\n",name,bits256_str(str,*signedtxidp)); + } else printf("basilisk_swap_bobtxspend %s -> %s\n",name,bits256_str(str,*signedtxidp)); free(rawtxbytes); } else printf("error making rawtx suppress.%d\n",suppress_pubkeys); free_json(privkeys); @@ -672,18 +856,19 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pubkey33,int32_t iambob,int32_t lockinputs,struct basilisk_rawtx *rawtx,uint32_t locktime,uint8_t *script,int32_t scriptlen,int64_t txfee,int32_t minconf,int32_t delay,bits256 privkey,uint8_t *changermd160,char *vinaddr) { int32_t retval=-1,len,iter; char *signedtx,*changeaddr = 0,_changeaddr[64]; struct iguana_info *coin; int64_t newtxfee=0,destamount; + char str2[65]; printf("%s rawtxgen.(%s/v%d)\n",rawtx->name,bits256_str(str2,rawtx->utxotxid),rawtx->utxovout); if ( (coin= rawtx->coin) == 0 ) return(-1); //return(_basilisk_rawtx_gen(str,swapstarted,pubkey33,iambob,lockinputs,rawtx,locktime,script,scriptlen,txfee,minconf,delay,privkey)); if ( changermd160 != 0 ) { changeaddr = _changeaddr; - bitcoin_address(changeaddr,coin->pubtype,changermd160,20); - printf("changeaddr.(%s) vs destaddr.(%s)\n",changeaddr,rawtx->I.destaddr); + bitcoin_address(changeaddr,coin->taddr,coin->pubtype,changermd160,20); + //printf("changeaddr.(%s) vs destaddr.(%s)\n",changeaddr,rawtx->I.destaddr); } for (iter=0; iter<2; iter++) { - if ( (signedtx= basilisk_swap_bobtxspend(&rawtx->I.signedtxid,iter == 0 ? txfee : newtxfee,str,coin->symbol,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,ctx,privkey,0,0,0,0,0,rawtx->utxotxid,rawtx->utxovout,rawtx->I.destaddr,pubkey33,1,0,&destamount,rawtx->I.amount,changeaddr,vinaddr,rawtx->I.suppress_pubkeys)) != 0 ) + if ( (signedtx= basilisk_swap_bobtxspend(&rawtx->I.signedtxid,iter == 0 ? txfee : newtxfee,str,coin->symbol,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,ctx,privkey,0,0,0,0,0,rawtx->utxotxid,rawtx->utxovout,rawtx->I.destaddr,pubkey33,1,0,&destamount,rawtx->I.amount,changeaddr,vinaddr,rawtx->I.suppress_pubkeys)) != 0 ) { rawtx->I.datalen = (int32_t)strlen(signedtx) >> 1; if ( rawtx->I.datalen <= sizeof(rawtx->txbytes) ) @@ -699,15 +884,18 @@ int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pub if ( coin->estimatedrate == 0. ) coin->estimatedrate = LP_getestimatedrate(coin->symbol); newtxfee = coin->estimatedrate * len; + if ( newtxfee < LP_MIN_TXFEE ) + newtxfee = LP_MIN_TXFEE; printf("txfee %.8f -> newtxfee %.8f\n",dstr(txfee),dstr(newtxfee)); } else break; } return(retval); } -int32_t basilisk_rawtx_sign(char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,struct basilisk_swap *swap,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr,uint8_t *changermd160,char *vinaddr) +int32_t basilisk_rawtx_sign(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,struct basilisk_swap *swap,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr,uint8_t *changermd160,char *vinaddr) { - char *signedtx,*changeaddr = 0,_changeaddr[64]; int64_t txfee,newtxfee=0,destamount; uint32_t timestamp,locktime=0,sequenceid = 0xffffffff; int32_t iter,len,retval = -1; double estimatedrate; + char *signedtx,*changeaddr = 0,_changeaddr[64]; int64_t txfee,newtxfee=0,destamount; uint32_t timestamp,locktime=0,sequenceid = 0xffffffff; int32_t iter,retval = -1; double estimatedrate; + //char str2[65]; printf("%s rawtxsign.(%s/v%d)\n",dest->name,bits256_str(str2,dest->utxotxid),dest->utxovout); timestamp = swap->I.started; if ( dest == &swap->aliceclaim ) locktime = swap->bobdeposit.I.locktime + 1, sequenceid = 0; @@ -717,36 +905,32 @@ int32_t basilisk_rawtx_sign(char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_ if ( changermd160 != 0 ) { changeaddr = _changeaddr; - bitcoin_address(changeaddr,pubtype,changermd160,20); - printf("changeaddr.(%s)\n",changeaddr); + bitcoin_address(changeaddr,taddr,pubtype,changermd160,20); + //printf("changeaddr.(%s)\n",changeaddr); } - for (iter=0; iter<33; iter++) - printf("%02x",rawtx->I.pubkey33[iter]); - printf(" pubkey33.%s, suppress.%d\n",rawtx->name,rawtx->I.suppress_pubkeys); for (iter=0; iter<2; iter++) { - if ( (signedtx= basilisk_swap_bobtxspend(&rawtx->I.signedtxid,iter == 0 ? txfee : newtxfee,rawtx->name,symbol,pubtype,p2shtype,isPoS,wiftype,swap->ctx,privkey,privkey2,0,0,userdata,userdatalen,rawtx->utxotxid,rawtx->utxovout,dest->p2shaddr,rawtx->I.pubkey33,1,0,&destamount,rawtx->I.amount,changeaddr,vinaddr,rawtx->I.suppress_pubkeys)) != 0 ) + if ( (signedtx= basilisk_swap_bobtxspend(&dest->I.signedtxid,iter == 0 ? txfee : newtxfee,rawtx->name,symbol,taddr,pubtype,p2shtype,isPoS,wiftype,swap->ctx,privkey,privkey2,rawtx->redeemscript,rawtx->I.redeemlen,userdata,userdatalen,dest->utxotxid,dest->utxovout,dest->I.destaddr,rawtx->I.pubkey33,1,0,&destamount,rawtx->I.amount,changeaddr,vinaddr,dest->I.suppress_pubkeys)) != 0 ) { - rawtx->I.datalen = (int32_t)strlen(signedtx) >> 1; - if ( rawtx->I.datalen <= sizeof(rawtx->txbytes) ) + dest->I.datalen = (int32_t)strlen(signedtx) >> 1; + if ( dest->I.datalen <= sizeof(dest->txbytes) ) { - decode_hex(rawtx->txbytes,rawtx->I.datalen,signedtx); - rawtx->I.completed = 1; + decode_hex(dest->txbytes,dest->I.datalen,signedtx); + dest->I.completed = 1; retval = 0; } free(signedtx); if ( strcmp(symbol,"BTC") != 0 ) return(retval); - len = rawtx->I.datalen; estimatedrate = LP_getestimatedrate(symbol); - newtxfee = estimatedrate * len; + newtxfee = estimatedrate * dest->I.datalen; } else break; } return(retval); //return(_basilisk_rawtx_sign(symbol,pubtype,p2shtype,isPoS,wiftype,swap,timestamp,locktime,sequenceid,dest,rawtx,privkey,privkey2,userdata,userdatalen,ignore_cltverr)); } -int32_t basilisk_alicescript(uint8_t *redeemscript,int32_t *redeemlenp,uint8_t *script,int32_t n,char *msigaddr,uint8_t altps2h,bits256 pubAm,bits256 pubBn) +int32_t basilisk_alicescript(uint8_t *redeemscript,int32_t *redeemlenp,uint8_t *script,int32_t n,char *msigaddr,uint8_t taddr,uint8_t altps2h,bits256 pubAm,bits256 pubBn) { uint8_t p2sh160[20]; struct vin_info V; memset(&V,0,sizeof(V)); @@ -754,7 +938,7 @@ int32_t basilisk_alicescript(uint8_t *redeemscript,int32_t *redeemlenp,uint8_t * memcpy(&V.signers[1].pubkey[1],pubBn.bytes,sizeof(pubBn)), V.signers[1].pubkey[0] = 0x03; V.M = V.N = 2; *redeemlenp = bitcoin_MofNspendscript(p2sh160,redeemscript,n,&V); - bitcoin_address(msigaddr,altps2h,p2sh160,sizeof(p2sh160)); + bitcoin_address(msigaddr,taddr,altps2h,p2sh160,sizeof(p2sh160)); n = bitcoin_p2shspend(script,0,p2sh160); //for (i=0; i<*redeemlenp; i++) // printf("%02x",redeemscript[i]); @@ -762,7 +946,7 @@ int32_t basilisk_alicescript(uint8_t *redeemscript,int32_t *redeemlenp,uint8_t * return(n); } -char *basilisk_swap_Aspend(char *name,char *symbol,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privAm,bits256 privBn,bits256 utxotxid,int32_t vout,uint8_t pubkey33[33],uint32_t expiration,int64_t *destamountp,char *vinaddr) +char *basilisk_swap_Aspend(char *name,char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privAm,bits256 privBn,bits256 utxotxid,int32_t vout,uint8_t pubkey33[33],uint32_t expiration,int64_t *destamountp,char *vinaddr) { char msigaddr[64],*signedtx = 0; int32_t spendlen,redeemlen; uint8_t tmp33[33],redeemscript[512],spendscript[128]; bits256 pubAm,pubBn,signedtxid; uint64_t txfee; if ( bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 ) @@ -772,7 +956,7 @@ char *basilisk_swap_Aspend(char *name,char *symbol,uint8_t pubtype,uint8_t p2sht //char str[65]; //printf("pubAm.(%s)\n",bits256_str(str,pubAm)); //printf("pubBn.(%s)\n",bits256_str(str,pubBn)); - spendlen = basilisk_alicescript(redeemscript,&redeemlen,spendscript,0,msigaddr,p2shtype,pubAm,pubBn); + spendlen = basilisk_alicescript(redeemscript,&redeemlen,spendscript,0,msigaddr,taddr,p2shtype,pubAm,pubBn); //char str[65]; printf("%s utxo.(%s) redeemlen.%d spendlen.%d\n",msigaddr,bits256_str(str,utxotxid),redeemlen,spendlen); /*rev = privAm; for (i=0; i<32; i++) @@ -781,7 +965,7 @@ char *basilisk_swap_Aspend(char *name,char *symbol,uint8_t pubtype,uint8_t p2sht for (i=0; i<32; i++) privBn.bytes[i] = rev.bytes[31 - i];*/ txfee = LP_txfee(symbol); - signedtx = basilisk_swap_bobtxspend(&signedtxid,txfee,name,symbol,pubtype,p2shtype,isPoS,wiftype,ctx,privAm,&privBn,redeemscript,redeemlen,0,0,utxotxid,vout,0,pubkey33,1,expiration,destamountp,0,0,vinaddr,0); + signedtx = basilisk_swap_bobtxspend(&signedtxid,txfee,name,symbol,taddr,pubtype,p2shtype,isPoS,wiftype,ctx,privAm,&privBn,redeemscript,redeemlen,0,0,utxotxid,vout,0,pubkey33,1,expiration,destamountp,0,0,vinaddr,1); } return(signedtx); } @@ -911,11 +1095,14 @@ bits256 _LP_swap_spendtxid(char *symbol,char *destaddr,char *coinaddr,bits256 ut bits256 LP_swap_spendtxid(char *symbol,char *destaddr,bits256 utxotxid,int32_t vout) { - bits256 spendtxid,txid; char *catstr,*addr; cJSON *array,*item,*item2,*txobj,*vins; int32_t i,n,m; char coinaddr[64],str[65]; + bits256 spendtxid,txid; char *catstr,*addr; cJSON *array,*item,*item2,*txobj,*vins; int32_t i,n,m,spendvin; char coinaddr[64],str[65]; // listtransactions or listspents destaddr[0] = 0; coinaddr[0] = 0; memset(&spendtxid,0,sizeof(spendtxid)); + if ( LP_spendsearch(&spendtxid,&spendvin,symbol,utxotxid,vout) > 0 ) + printf("spend of %s/v%d detected\n",bits256_str(str,utxotxid),vout); + return(spendtxid); //char str[65]; printf("swap %s spendtxid.(%s)\n",symbol,bits256_str(str,utxotxid)); if ( 0 && strcmp("BTC",symbol) == 0 ) { @@ -1097,9 +1284,9 @@ int32_t basilisk_bobscript(uint8_t *rmd160,uint8_t *redeemscript,int32_t *redeem { calc_rmd160_sha256(rmd160,redeemscript,n); n = bitcoin_p2shspend(script,0,rmd160); - //for (i=0; iI.myprivs[1],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); memcpy(swap->I.userdata_bobreclaim,userdata,len); swap->I.userdata_bobreclaimlen = len; - if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->bobreclaim,&swap->bobpayment,swap->I.myprivs[1],0,userdata,len,1,swap->changermd160,swap->bobpayment.I.destaddr)) == 0 ) + if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->bobreclaim,&swap->bobpayment,swap->I.myprivs[1],0,userdata,len,1,swap->changermd160,swap->bobpayment.I.destaddr)) == 0 ) { - for (i=0; ibobreclaim.I.datalen; i++) - printf("%02x",swap->bobreclaim.txbytes[i]); - printf(" <- bobreclaim\n"); + //for (i=0; ibobreclaim.I.datalen; i++) + // printf("%02x",swap->bobreclaim.txbytes[i]); + //printf(" <- bobreclaim\n"); //basilisk_txlog(swap,&swap->bobreclaim,delay); return(retval); } @@ -1153,7 +1340,7 @@ int32_t basilisk_bobdeposit_refund(struct basilisk_swap *swap,int32_t delay) len = basilisk_swapuserdata(userdata,swap->I.privBn,0,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); memcpy(swap->I.userdata_bobrefund,userdata,len); swap->I.userdata_bobrefundlen = len; - if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->bobrefund,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,0,swap->changermd160,swap->bobdeposit.I.destaddr)) == 0 ) + if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->bobrefund,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,0,swap->changermd160,swap->bobdeposit.I.destaddr)) == 0 ) { for (i=0; ibobrefund.I.datalen; i++) printf("%02x",swap->bobrefund.txbytes[i]); @@ -1164,20 +1351,46 @@ int32_t basilisk_bobdeposit_refund(struct basilisk_swap *swap,int32_t delay) return(-1); } +void LP_swap_coinaddr(struct basilisk_swap *swap,struct iguana_info *coin,char *coinaddr,uint8_t *data,int32_t datalen) +{ + cJSON *txobj,*vouts,*vout,*addresses,*item,*skey; uint8_t extraspace[8192]; bits256 signedtxid; struct iguana_msgtx msgtx; char *addr; int32_t n,m,suppress_pubkeys = 0; + if ( (txobj= bitcoin_data2json(coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->longestchain,&signedtxid,&msgtx,extraspace,sizeof(extraspace),data,datalen,0,suppress_pubkeys)) != 0 ) + { + //char str[65]; printf("got txid.%s (%s)\n",bits256_str(str,signedtxid),jprint(txobj,0)); + if ( (vouts= jarray(&n,txobj,"vout")) != 0 && n > 0 ) + { + vout = jitem(vouts,0); + //printf("VOUT.(%s)\n",jprint(vout,0)); + if ( (skey= jobj(vout,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 ) + { + item = jitem(addresses,0); + //printf("item.(%s)\n",jprint(item,0)); + if ( (addr= jstr(item,0)) != 0 ) + { + safecopy(coinaddr,addr,64); + //printf("extracted.(%s)\n",coinaddr); + } + } + } + free_json(txobj); + } +} + int32_t basilisk_bobscripts_set(struct basilisk_swap *swap,int32_t depositflag,int32_t genflag) { - int32_t j; char coinaddr[64]; - bitcoin_address(coinaddr,swap->bobcoin.pubtype,swap->changermd160,20); + int32_t j; char coinaddr[64],checkaddr[64]; + bitcoin_address(coinaddr,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->changermd160,20); if ( genflag != 0 && swap->I.iambob == 0 ) printf("basilisk_bobscripts_set WARNING: alice generating BOB tx\n"); if ( depositflag == 0 ) { swap->bobpayment.I.spendlen = basilisk_bobscript(swap->bobpayment.I.rmd160,swap->bobpayment.redeemscript,&swap->bobpayment.I.redeemlen,swap->bobpayment.spendscript,0,&swap->bobpayment.I.locktime,&swap->bobpayment.I.secretstart,&swap->I,0); - bitcoin_address(swap->bobpayment.p2shaddr,swap->bobcoin.p2shtype,swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); + bitcoin_address(swap->bobpayment.p2shaddr,swap->bobcoin.taddr,swap->bobcoin.p2shtype,swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); strcpy(swap->bobpayment.I.destaddr,swap->bobpayment.p2shaddr); - int32_t i; for (i=0; ibobpayment.I.redeemlen; i++) - printf("%02x",swap->bobpayment.redeemscript[i]); - printf(" <- bobpayment redeem %d %s\n",i,swap->bobpayment.I.destaddr); + //LP_importaddress(swap->bobcoin.symbol,swap->bobpayment.I.destaddr); + //int32_t i; for (i=0; ibobpayment.I.redeemlen; i++) + // printf("%02x",swap->bobpayment.redeemscript[i]); + //printf(" <- bobpayment redeem %d %s\n",i,swap->bobpayment.I.destaddr); if ( genflag != 0 && bits256_nonz(*(bits256 *)swap->I.secretBn256) != 0 && swap->bobpayment.I.datalen == 0 ) { basilisk_rawtx_gen(swap->ctx,"payment",swap->I.started,swap->persistent_pubkey33,1,1,&swap->bobpayment,swap->bobpayment.I.locktime,swap->bobpayment.spendscript,swap->bobpayment.I.spendlen,swap->bobpayment.coin->txfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr); @@ -1195,9 +1408,13 @@ int32_t basilisk_bobscripts_set(struct basilisk_swap *swap,int32_t depositflag,i printf("%02x",swap->bobpayment.redeemscript[j]); printf(" <- redeem.%d\n",swap->bobpayment.I.redeemlen); printf(" <- GENERATED BOB PAYMENT.%d destaddr.(%s)\n",swap->bobpayment.I.datalen,swap->bobpayment.I.destaddr); + LP_swap_coinaddr(swap,&swap->bobcoin,checkaddr,swap->bobpayment.txbytes,swap->bobpayment.I.datalen); + if ( strcmp(swap->bobpayment.I.destaddr,checkaddr) != 0 ) + { + printf("BOBPAYMENT REDEEMADDR MISMATCH??? %s != %s\n",swap->bobpayment.I.destaddr,checkaddr); + return(-1); + } LP_unspents_mark(swap->bobcoin.symbol,swap->bobpayment.vins); - if ( swap->I.iambob != 0 ) - basilisk_bobpayment_reclaim(swap,swap->I.callduration); //printf("bobscripts set completed\n"); return(0); } @@ -1206,8 +1423,9 @@ int32_t basilisk_bobscripts_set(struct basilisk_swap *swap,int32_t depositflag,i else { swap->bobdeposit.I.spendlen = basilisk_bobscript(swap->bobdeposit.I.rmd160,swap->bobdeposit.redeemscript,&swap->bobdeposit.I.redeemlen,swap->bobdeposit.spendscript,0,&swap->bobdeposit.I.locktime,&swap->bobdeposit.I.secretstart,&swap->I,1); - bitcoin_address(swap->bobdeposit.p2shaddr,swap->bobcoin.p2shtype,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); + bitcoin_address(swap->bobdeposit.p2shaddr,swap->bobcoin.taddr,swap->bobcoin.p2shtype,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); strcpy(swap->bobdeposit.I.destaddr,swap->bobdeposit.p2shaddr); + //LP_importaddress(swap->bobcoin.symbol,swap->bobdeposit.I.destaddr); int32_t i; for (i=0; ibobdeposit.I.redeemlen; i++) printf("%02x",swap->bobdeposit.redeemscript[i]); printf(" <- bobdeposit redeem %d %s\n",i,swap->bobdeposit.I.destaddr); @@ -1223,10 +1441,14 @@ int32_t basilisk_bobscripts_set(struct basilisk_swap *swap,int32_t depositflag,i { for (j=0; jbobdeposit.I.datalen; j++) printf("%02x",swap->bobdeposit.txbytes[j]); - printf(" <- GENERATED BOB DEPOSIT.%d\n",swap->bobdeposit.I.datalen); + printf(" <- GENERATED BOB DEPOSIT.%d (%s)\n",swap->bobdeposit.I.datalen,swap->bobdeposit.I.destaddr); + LP_swap_coinaddr(swap,&swap->bobcoin,checkaddr,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen); + if ( strcmp(swap->bobdeposit.I.destaddr,checkaddr) != 0 ) + { + printf("BOBDEPOSIT REDEEMADDR MISMATCH??? %s != %s\n",swap->bobdeposit.I.destaddr,checkaddr); + return(-1); + } LP_unspents_mark(swap->bobcoin.symbol,swap->bobdeposit.vins); - if ( swap->I.iambob != 0 ) - basilisk_bobdeposit_refund(swap,swap->I.putduration); printf("bobscripts set completed\n"); return(0); } @@ -1237,31 +1459,6 @@ int32_t basilisk_bobscripts_set(struct basilisk_swap *swap,int32_t depositflag,i /**/ -void LP_swap_coinaddr(struct basilisk_swap *swap,struct iguana_info *coin,char *coinaddr,uint8_t *data,int32_t datalen) -{ - cJSON *txobj,*vouts,*vout,*addresses,*item,*skey; uint8_t extraspace[8192]; bits256 signedtxid; struct iguana_msgtx msgtx; char *addr; int32_t n,m,suppress_pubkeys = 0; - if ( (txobj= bitcoin_data2json(coin->pubtype,coin->p2shtype,coin->isPoS,coin->longestchain,&signedtxid,&msgtx,extraspace,sizeof(extraspace),data,datalen,0,suppress_pubkeys)) != 0 ) - { - //char str[65]; printf("got txid.%s (%s)\n",bits256_str(str,signedtxid),jprint(txobj,0)); - if ( (vouts= jarray(&n,txobj,"vout")) != 0 && n > 0 ) - { - vout = jitem(vouts,0); - //printf("VOUT.(%s)\n",jprint(vout,0)); - if ( (skey= jobj(vout,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 ) - { - item = jitem(addresses,0); - //printf("item.(%s)\n",jprint(item,0)); - if ( (addr= jstr(item,0)) != 0 ) - { - safecopy(coinaddr,addr,64); - //printf("extracted.(%s)\n",coinaddr); - } - } - } - free_json(txobj); - } -} - #ifdef old int32_t basilisk_alicepayment_spend(struct basilisk_swap *swap,struct basilisk_rawtx *dest) { @@ -1295,16 +1492,16 @@ int32_t basilisk_alicepayment_spend(struct basilisk_swap *swap,struct basilisk_r void basilisk_alicepayment(struct basilisk_swap *swap,struct iguana_info *coin,struct basilisk_rawtx *alicepayment,bits256 pubAm,bits256 pubBn) { - int32_t i; char coinaddr[64]; - alicepayment->I.spendlen = basilisk_alicescript(alicepayment->redeemscript,&alicepayment->I.redeemlen,alicepayment->spendscript,0,alicepayment->I.destaddr,coin->p2shtype,pubAm,pubBn); - for (i=0; i<33; i++) + char coinaddr[64]; + alicepayment->I.spendlen = basilisk_alicescript(alicepayment->redeemscript,&alicepayment->I.redeemlen,alicepayment->spendscript,0,alicepayment->I.destaddr,coin->taddr,coin->p2shtype,pubAm,pubBn); + /*for (i=0; i<33; i++) printf("%02x",swap->persistent_pubkey33[i]); printf(" pubkey33, "); for (i=0; i<20; i++) printf("%02x",swap->changermd160[i]); - printf(" rmd160, "); - bitcoin_address(coinaddr,coin->pubtype,swap->changermd160,20); - printf("%s suppress.%d fee.%d\n",coinaddr,alicepayment->I.suppress_pubkeys,swap->myfee.I.suppress_pubkeys); + printf(" rmd160, ");*/ + bitcoin_address(coinaddr,coin->taddr,coin->pubtype,swap->changermd160,20); + //printf("%s suppress.%d fee.%d\n",coinaddr,alicepayment->I.suppress_pubkeys,swap->myfee.I.suppress_pubkeys); basilisk_rawtx_gen(swap->ctx,"alicepayment",swap->I.started,swap->persistent_pubkey33,0,1,alicepayment,alicepayment->I.locktime,alicepayment->spendscript,alicepayment->I.spendlen,coin->txfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr); } @@ -1317,19 +1514,24 @@ int32_t basilisk_alicetxs(int32_t pairsock,struct basilisk_swap *swap,uint8_t *d printf("error alice generating payment.%d\n",swap->alicepayment.I.spendlen); else { + bitcoin_address(swap->alicepayment.I.destaddr,swap->alicecoin.taddr,swap->alicecoin.p2shtype,swap->alicepayment.redeemscript,swap->alicepayment.I.redeemlen); + //LP_importaddress(swap->alicecoin.symbol,swap->alicepayment.I.destaddr); + strcpy(swap->alicepayment.p2shaddr,swap->alicepayment.I.destaddr); retval = 0; for (i=0; ialicepayment.I.datalen; i++) printf("%02x",swap->alicepayment.txbytes[i]); - printf(" ALICE PAYMENT created\n"); + printf(" ALICE PAYMENT created.(%s)\n",swap->alicepayment.I.destaddr); LP_unspents_mark(swap->alicecoin.symbol,swap->alicepayment.vins); + //LP_importaddress(swap->alicecoin.symbol,swap->alicepayment.I.destaddr); //basilisk_txlog(swap,&swap->alicepayment,-1); } if ( swap->myfee.I.datalen == 0 ) { - //printf("generate fee\n"); - bitcoin_address(coinaddr,swap->alicecoin.pubtype,swap->changermd160,20); + printf("generate fee\n"); + bitcoin_address(coinaddr,swap->alicecoin.taddr,swap->alicecoin.pubtype,swap->changermd160,20); if ( basilisk_rawtx_gen(swap->ctx,"myfee",swap->I.started,swap->persistent_pubkey33,swap->I.iambob,1,&swap->myfee,0,swap->myfee.spendscript,swap->myfee.I.spendlen,swap->myfee.coin->txfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr) == 0 ) { + printf("rawtxsend\n"); swap->I.statebits |= LP_swapdata_rawtxsend(pairsock,swap,0x80,data,maxlen,&swap->myfee,0x40,0); LP_unspents_mark(swap->I.iambob!=0?swap->bobcoin.symbol:swap->alicecoin.symbol,swap->myfee.vins); //basilisk_txlog(swap,&swap->myfee,-1); @@ -1358,74 +1560,6 @@ int32_t LP_verify_otherfee(struct basilisk_swap *swap,uint8_t *data,int32_t data return(0); } -int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys) -{ - bits256 otherhash,myhash,txid; int32_t i,offset=0,datalen=0,retval=-1,hexlen,n; uint8_t *data; cJSON *txobj,*skey,*vouts,*vout; char *hexstr; uint32_t quoteid,msgbits; - for (i=0; i<32; i++) - otherhash.bytes[i] = recvbuf[offset++]; - for (i=0; i<32; i++) - myhash.bytes[i] = recvbuf[offset++]; - offset += iguana_rwnum(0,&recvbuf[offset],sizeof(quoteid),"eid); - offset += iguana_rwnum(0,&recvbuf[offset],sizeof(msgbits),&msgbits); - datalen = recvbuf[offset++]; - datalen += (int32_t)recvbuf[offset++] << 8; - if ( datalen > 1024 ) - { - printf("LP_rawtx_spendscript %s datalen.%d too big\n",rawtx->name,datalen); - return(-1); - } - rawtx->I.redeemlen = recvbuf[offset++]; - data = &recvbuf[offset++]; - if ( rawtx->I.redeemlen > 0 && rawtx->I.redeemlen < 0x100 ) - memcpy(rawtx->redeemscript,&data[datalen],rawtx->I.redeemlen); - //printf("recvlen.%d datalen.%d redeemlen.%d\n",recvlen,datalen,rawtx->redeemlen); - if ( rawtx->I.datalen == 0 ) - { - //rawtx->txbytes = calloc(1,datalen); - memcpy(rawtx->txbytes,data,datalen); - rawtx->I.datalen = datalen; - } - else if ( datalen != rawtx->I.datalen || memcmp(rawtx->txbytes,data,datalen) != 0 ) - { - int32_t i; for (i=0; iI.datalen; i++) - printf("%02x",rawtx->txbytes[i]); - printf(" <- rawtx\n"); - printf("%s rawtx data compare error, len %d vs %d <<<<<<<<<< warning\n",rawtx->name,rawtx->I.datalen,datalen); - return(-1); - } - txid = bits256_doublesha256(0,data,datalen); - char str[65]; printf("rawtx.%s txid %s\n",rawtx->name,bits256_str(str,txid)); - if ( bits256_cmp(txid,rawtx->I.actualtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 ) - rawtx->I.actualtxid = txid; - if ( (txobj= bitcoin_data2json(rawtx->coin->pubtype,rawtx->coin->p2shtype,rawtx->coin->isPoS,height,&rawtx->I.signedtxid,&rawtx->msgtx,rawtx->extraspace,sizeof(rawtx->extraspace),data,datalen,0,suppress_pubkeys)) != 0 ) - { - rawtx->I.actualtxid = rawtx->I.signedtxid; - char str[65]; printf("got %s txid.%s (%s)\n",rawtx->name,bits256_str(str,rawtx->I.signedtxid),jprint(txobj,0)); - rawtx->I.locktime = rawtx->msgtx.lock_time; - if ( (vouts= jarray(&n,txobj,"vout")) != 0 && v < n ) - { - vout = jitem(vouts,v); - if ( j64bits(vout,"satoshis") == rawtx->I.amount && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 ) - { - if ( (hexlen= (int32_t)strlen(hexstr) >> 1) < sizeof(rawtx->spendscript) ) - { - decode_hex(rawtx->spendscript,hexlen,hexstr); - rawtx->I.spendlen = hexlen; - bitcoin_address(rawtx->p2shaddr,rawtx->coin->p2shtype,rawtx->spendscript,hexlen); - //if ( swap != 0 ) - // basilisk_txlog(swap->myinfoptr,swap,rawtx,-1); // bobdeposit, bobpayment or alicepayment - retval = 0; - } - } else printf("%s ERROR.(%s)\n",rawtx->name,jprint(txobj,0)); - } - free_json(txobj); - } - return(retval); -} - /* Bob deposit: OP_IF OP_CLTV OP_DROP OP_CHECKSIG @@ -1435,27 +1569,41 @@ int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct ba int32_t LP_verify_bobdeposit(struct basilisk_swap *swap,uint8_t *data,int32_t datalen) { - uint8_t userdata[512]; int32_t i,retval=-1,len = 0; static bits256 zero; + uint8_t userdata[512]; int32_t retval=-1,len = 0; static bits256 zero; if ( LP_rawtx_spendscript(swap,swap->bobcoin.longestchain,&swap->bobdeposit,0,data,datalen,0) == 0 ) { - swap->bobdeposit.I.signedtxid = LP_broadcast_tx(swap->bobdeposit.name,swap->bobcoin.symbol,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen); + swap->aliceclaim.utxovout = 0; + swap->aliceclaim.utxotxid = swap->bobdeposit.I.signedtxid = LP_broadcast_tx(swap->bobdeposit.name,swap->bobcoin.symbol,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen); if ( bits256_nonz(swap->bobdeposit.I.signedtxid) != 0 ) swap->depositunconf = 1; basilisk_dontforget_update(swap,&swap->bobdeposit); len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); memcpy(swap->I.userdata_aliceclaim,userdata,len); swap->I.userdata_aliceclaimlen = len; + bitcoin_address(swap->bobdeposit.p2shaddr,swap->bobcoin.taddr,swap->bobcoin.p2shtype,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); + strcpy(swap->bobdeposit.I.destaddr,swap->bobdeposit.p2shaddr); + //LP_importaddress(swap->bobcoin.symbol,swap->bobdeposit.I.destaddr); + /*for (i=0; ibobdeposit.I.datalen; i++) + printf("%02x",swap->bobdeposit.txbytes[i]); + printf(" <- bobdeposit.%d %s\n",swap->bobdeposit.I.datalen,bits256_str(str,swap->bobdeposit.I.signedtxid)); + for (i=0; ibobdeposit.I.redeemlen; i++) + printf("%02x",swap->bobdeposit.redeemscript[i]); + printf(" <- bobdeposit redeem %d %s suppress.%d\n",i,swap->bobdeposit.I.destaddr,swap->aliceclaim.I.suppress_pubkeys);*/ + memcpy(swap->aliceclaim.redeemscript,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); + swap->aliceclaim.I.redeemlen = swap->bobdeposit.I.redeemlen; + memcpy(swap->aliceclaim.I.pubkey33,swap->persistent_pubkey33,33); + bitcoin_address(swap->aliceclaim.I.destaddr,swap->alicecoin.taddr,swap->alicecoin.pubtype,swap->persistent_pubkey33,33); retval = 0; - if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->aliceclaim,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,1,swap->changermd160,swap->bobdeposit.I.destaddr)) == 0 ) + if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->aliceclaim,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,1,swap->changermd160,swap->bobdeposit.I.destaddr)) == 0 ) { - for (i=0; ibobdeposit.I.datalen; i++) + /*for (i=0; ibobdeposit.I.datalen; i++) printf("%02x",swap->bobdeposit.txbytes[i]); printf(" <- bobdeposit\n"); for (i=0; ialiceclaim.I.datalen; i++) printf("%02x",swap->aliceclaim.txbytes[i]); - printf(" <- aliceclaim\n"); + printf(" <- aliceclaim\n");*/ //basilisk_txlog(swap,&swap->aliceclaim,swap->I.putduration+swap->I.callduration); - return(retval); + return(LP_waitmempool(swap->bobcoin.symbol,swap->bobdeposit.I.signedtxid,10)); } else printf("error signing aliceclaim suppress.%d vin.(%s)\n",swap->aliceclaim.I.suppress_pubkeys,swap->bobdeposit.I.destaddr); } printf("error with bobdeposit\n"); @@ -1466,10 +1614,16 @@ int32_t LP_verify_alicepayment(struct basilisk_swap *swap,uint8_t *data,int32_t { if ( LP_rawtx_spendscript(swap,swap->alicecoin.longestchain,&swap->alicepayment,0,data,datalen,0) == 0 ) { - swap->alicepayment.I.signedtxid = LP_broadcast_tx(swap->alicepayment.name,swap->alicecoin.symbol,swap->alicepayment.txbytes,swap->alicepayment.I.datalen); + swap->bobspend.utxovout = 0; + swap->bobspend.utxotxid = swap->alicepayment.I.signedtxid = LP_broadcast_tx(swap->alicepayment.name,swap->alicecoin.symbol,swap->alicepayment.txbytes,swap->alicepayment.I.datalen); + bitcoin_address(swap->alicepayment.p2shaddr,swap->alicecoin.taddr,swap->alicecoin.p2shtype,swap->alicepayment.redeemscript,swap->alicepayment.I.redeemlen); + strcpy(swap->alicepayment.I.destaddr,swap->alicepayment.p2shaddr); if ( bits256_nonz(swap->alicepayment.I.signedtxid) != 0 ) swap->aliceunconf = 1; basilisk_dontforget_update(swap,&swap->alicepayment); + return(LP_waitmempool(swap->alicecoin.symbol,swap->alicepayment.I.signedtxid,10)); + //printf("import alicepayment address.(%s)\n",swap->alicepayment.p2shaddr); + //LP_importaddress(swap->alicecoin.symbol,swap->alicepayment.p2shaddr); return(0); } printf("error validating alicepayment\n"); @@ -1482,29 +1636,40 @@ int32_t LP_verify_bobpayment(struct basilisk_swap *swap,uint8_t *data,int32_t da memset(revAm.bytes,0,sizeof(revAm)); if ( LP_rawtx_spendscript(swap,swap->bobcoin.longestchain,&swap->bobpayment,0,data,datalen,0) == 0 ) { - swap->bobpayment.I.signedtxid = LP_broadcast_tx(swap->bobpayment.name,swap->bobpayment.coin->symbol,swap->bobpayment.txbytes,swap->bobpayment.I.datalen); + swap->alicespend.utxovout = 0; + swap->alicespend.utxotxid = swap->bobpayment.I.signedtxid = LP_broadcast_tx(swap->bobpayment.name,swap->bobpayment.coin->symbol,swap->bobpayment.txbytes,swap->bobpayment.I.datalen); if ( bits256_nonz(swap->bobpayment.I.signedtxid) != 0 ) swap->paymentunconf = 1; basilisk_dontforget_update(swap,&swap->bobpayment); for (i=0; i<32; i++) revAm.bytes[i] = swap->I.privAm.bytes[31-i]; len = basilisk_swapuserdata(userdata,revAm,0,swap->I.myprivs[0],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); + bitcoin_address(swap->bobpayment.p2shaddr,swap->bobcoin.taddr,swap->bobcoin.p2shtype,swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); + strcpy(swap->bobpayment.I.destaddr,swap->bobpayment.p2shaddr); + //LP_importaddress(swap->bobcoin.symbol,swap->bobpayment.I.destaddr); + /*for (i=0; ibobpayment.I.datalen; i++) + printf("%02x",swap->bobpayment.txbytes[i]); + printf(" <- bobpayment.%d\n",swap->bobpayment.I.datalen); + for (i=0; ibobpayment.I.redeemlen; i++) + printf("%02x",swap->bobpayment.redeemscript[i]); + printf(" <- bobpayment redeem %d %s %s\n",i,swap->bobpayment.I.destaddr,bits256_str(str,swap->bobpayment.I.signedtxid));*/ memcpy(swap->I.userdata_alicespend,userdata,len); swap->I.userdata_alicespendlen = len; retval = 0; - char str[65],str2[65]; printf("bobpaid privAm.(%s) myprivs[0].(%s)\n",bits256_str(str,swap->I.privAm),bits256_str(str2,swap->I.myprivs[0])); - if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->alicespend,&swap->bobpayment,swap->I.myprivs[0],0,userdata,len,1,swap->changermd160,swap->alicepayment.I.destaddr)) == 0 ) + memcpy(swap->alicespend.I.pubkey33,swap->persistent_pubkey33,33); + bitcoin_address(swap->alicespend.I.destaddr,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->persistent_pubkey33,33); + //char str[65],str2[65]; printf("bobpaid privAm.(%s) myprivs[0].(%s)\n",bits256_str(str,swap->I.privAm),bits256_str(str2,swap->I.myprivs[0])); + if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->alicespend,&swap->bobpayment,swap->I.myprivs[0],0,userdata,len,1,swap->changermd160,swap->alicepayment.I.destaddr)) == 0 ) { - for (i=0; ibobpayment.I.datalen; i++) + /*for (i=0; ibobpayment.I.datalen; i++) printf("%02x",swap->bobpayment.txbytes[i]); printf(" <- bobpayment\n"); for (i=0; ialicespend.I.datalen; i++) printf("%02x",swap->alicespend.txbytes[i]); - printf(" <- alicespend\n\n"); + printf(" <- alicespend\n\n");*/ swap->I.alicespent = 1; - //basilisk_txlog(swap,&swap->alicespend,-1); - return(retval); - } + return(LP_waitmempool(swap->bobcoin.symbol,swap->bobpayment.I.signedtxid,10)); + } else printf("error signing aliceclaim suppress.%d vin.(%s)\n",swap->alicespend.I.suppress_pubkeys,swap->bobpayment.I.destaddr); } printf("error validating bobpayment\n"); return(-1); diff --git a/iguana/exchanges/LP_utxos.c b/iguana/exchanges/LP_utxos.c index b10a7d93f..7cb030d60 100644 --- a/iguana/exchanges/LP_utxos.c +++ b/iguana/exchanges/LP_utxos.c @@ -18,35 +18,240 @@ // marketmaker // -struct LP_utxoinfo *LP_utxofind(bits256 txid,int32_t vout) +int32_t LP_ismine(struct LP_utxoinfo *utxo) +{ + if ( utxo != 0 && bits256_cmp(utxo->pubkey,LP_mypubkey) == 0 ) + return(1); + else return(0); +} + +int32_t LP_isavailable(struct LP_utxoinfo *utxo) +{ + if ( time(NULL) > utxo->T.swappending ) + utxo->T.swappending = 0; + if ( utxo != 0 && utxo->T.swappending == 0 && utxo->S.swap == 0 ) + return(1); + else return(0); +} + +int32_t LP_isunspent(struct LP_utxoinfo *utxo) +{ + if ( utxo != 0 && utxo->T.spentflag == 0 && LP_isavailable(utxo) > 0 ) + return(1); + else return(0); +} + +void LP_utxosetkey(uint8_t *key,bits256 txid,int32_t vout) { - struct LP_utxoinfo *utxo=0; uint8_t key[sizeof(txid) + sizeof(vout)]; memcpy(key,txid.bytes,sizeof(txid)); memcpy(&key[sizeof(txid)],&vout,sizeof(vout)); +} + +struct LP_utxoinfo *_LP_utxofind(int32_t iambob,bits256 txid,int32_t vout) +{ + struct LP_utxoinfo *utxo=0; uint8_t key[sizeof(txid) + sizeof(vout)]; + LP_utxosetkey(key,txid,vout); + HASH_FIND(hh,LP_utxoinfos[iambob],key,sizeof(key),utxo); + return(utxo); +} + +struct LP_utxoinfo *_LP_utxo2find(int32_t iambob,bits256 txid2,int32_t vout2) +{ + struct LP_utxoinfo *utxo=0; uint8_t key2[sizeof(txid2) + sizeof(vout2)]; + LP_utxosetkey(key2,txid2,vout2); + HASH_FIND(hh2,LP_utxoinfos2[iambob],key2,sizeof(key2),utxo); + return(utxo); +} + +struct LP_utxoinfo *LP_utxofind(int32_t iambob,bits256 txid,int32_t vout) +{ + struct LP_utxoinfo *utxo=0; portable_mutex_lock(&LP_utxomutex); - HASH_FIND(hh,LP_utxoinfos,key,sizeof(key),utxo); + 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; + portable_mutex_lock(&LP_utxomutex); + utxo = _LP_utxo2find(iambob,txid2,vout2); + portable_mutex_unlock(&LP_utxomutex); + return(utxo); +} + +struct LP_utxoinfo *LP_utxofinds(int32_t iambob,bits256 txid,int32_t vout,bits256 txid2,int32_t vout2) +{ + struct LP_utxoinfo *utxo; + if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 || (utxo= LP_utxofind(iambob,txid2,vout2)) != 0 || (utxo= LP_utxo2find(iambob,txid,vout)) != 0 || (utxo= LP_utxo2find(iambob,txid2,vout2)) != 0 ) + return(utxo); + else return(0); +} + +int32_t LP_utxoaddptrs(struct LP_utxoinfo *ptrs[],int32_t n,struct LP_utxoinfo *utxo) +{ + int32_t i; + for (i=0; ipayment.txid,refutxo->payment.vout)) != 0 && utxo != refutxo ) + n = LP_utxoaddptrs(ptrs,n,utxo); + if ( (utxo= _LP_utxo2find(iambob,refutxo->payment.txid,refutxo->payment.vout)) != 0 && utxo != refutxo ) + n = LP_utxoaddptrs(ptrs,n,utxo); + u = (refutxo->iambob != 0) ? refutxo->deposit : refutxo->fee; + if ( (utxo= _LP_utxofind(iambob,u.txid,u.vout)) != 0 && utxo != refutxo ) + n = LP_utxoaddptrs(ptrs,n,utxo); + if ( (utxo= _LP_utxo2find(iambob,u.txid,u.vout)) != 0 && utxo != refutxo ) + n = LP_utxoaddptrs(ptrs,n,utxo); + } + portable_mutex_unlock(&LP_utxomutex); + if ( 0 && n > 0 ) + printf("LP_utxocollisions n.%d\n",n); + return(n); +} + +int32_t _LP_availableset(struct LP_utxoinfo *utxo) +{ + int32_t flag = 0; + if ( utxo != 0 ) + { + if ( bits256_nonz(utxo->S.otherpubkey) != 0 ) + flag = 1, memset(&utxo->S.otherpubkey,0,sizeof(utxo->S.otherpubkey)); + if ( utxo->S.swap != 0 ) + flag = 1, utxo->S.swap = 0; + if ( utxo->T.swappending != 0 ) + flag = 1, utxo->T.swappending = 0; + return(flag); + } + return(0); +} + +void _LP_unavailableset(struct LP_utxoinfo *utxo,bits256 otherpubkey) +{ + if ( utxo != 0 ) + { + utxo->T.swappending = (uint32_t)(time(NULL) + LP_RESERVETIME); + utxo->S.otherpubkey = otherpubkey; + } +} + +void LP_unavailableset(struct LP_utxoinfo *utxo,bits256 otherpubkey) +{ + struct LP_utxoinfo *ptrs[8]; int32_t i,n; struct _LP_utxoinfo u; + memset(ptrs,0,sizeof(ptrs)); + if ( (n= LP_utxocollisions(ptrs,utxo)) > 0 ) + { + for (i=0; iiambob != 0) ? utxo->deposit : utxo->fee; + char str[65],str2[65]; printf("UTXO.[%d] RESERVED %s/v%d %s/v%d collisions.%d\n",utxo->iambob,bits256_str(str,utxo->payment.txid),utxo->payment.vout,bits256_str(str2,u.txid),u.vout,n); + _LP_unavailableset(utxo,otherpubkey); +} + +void LP_availableset(struct LP_utxoinfo *utxo) +{ + struct LP_utxoinfo *ptrs[8]; int32_t i,n,count = 0; struct _LP_utxoinfo u; + 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); + } +} + +int32_t LP_utxopurge(int32_t allutxos) +{ + char str[65]; struct LP_utxoinfo *utxo,*tmp; int32_t iambob,n = 0; + printf("LP_utxopurge mypub.(%s)\n",bits256_str(str,LP_mypubkey)); + portable_mutex_lock(&LP_utxomutex); + for (iambob=0; iambob<=1; iambob++) + { + HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) + { + if ( LP_isavailable(utxo) > 0 ) + { + if ( allutxos != 0 || LP_ismine(utxo) > 0 ) + { + printf("iambob.%d delete.(%s)\n",iambob,bits256_str(str,utxo->payment.txid)); + HASH_DELETE(hh,LP_utxoinfos[iambob],utxo); + //free(utxo); let the LP_utxoinfos2 free the utxo, should be 1:1 + } else n++; + } else n++; + } + HASH_ITER(hh,LP_utxoinfos2[iambob],utxo,tmp) + { + if ( LP_isavailable(utxo) > 0 ) + { + if ( allutxos != 0 || LP_ismine(utxo) > 0 ) + { + printf("iambob.%d delete2.(%s)\n",iambob,bits256_str(str,utxo->payment.txid)); + HASH_DELETE(hh2,LP_utxoinfos2[iambob],utxo); + free(utxo); + } else n++; + } else n++; + } + } + portable_mutex_unlock(&LP_utxomutex); + return(n); +} + cJSON *LP_inventoryjson(cJSON *item,struct LP_utxoinfo *utxo) { + struct _LP_utxoinfo u; + jaddstr(item,"method","notified"); + 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->txid); - jaddnum(item,"vout",utxo->vout); - jaddnum(item,"value",dstr(utxo->satoshis)); - jaddbits256(item,"txid2",utxo->txid2); - jaddnum(item,"vout2",utxo->vout2); - jaddnum(item,"value2",dstr(utxo->satoshis2)); - if ( utxo->swappending != 0 ) - jaddnum(item,"pending",utxo->swappending); - if ( bits256_nonz(utxo->otherpubkey) != 0 ) - jaddbits256(item,"desthash",utxo->otherpubkey); - if ( utxo->pair >= 0 ) - jaddnum(item,"socket",utxo->pair); - if ( utxo->swap != 0 ) + 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",LP_mypubkey); + if ( bits256_nonz(utxo->S.otherpubkey) != 0 ) + jaddbits256(item,"desthash",utxo->S.otherpubkey); + } + else + { + jaddbits256(item,"desthash",LP_mypubkey); + 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); return(item); } @@ -54,94 +259,276 @@ cJSON *LP_utxojson(struct LP_utxoinfo *utxo) { cJSON *item = cJSON_CreateObject(); item = LP_inventoryjson(item,utxo); - jaddstr(item,"ipaddr",utxo->ipaddr); - jaddnum(item,"port",utxo->port); - jaddnum(item,"profit",utxo->profitmargin); + jaddbits256(item,"pubkey",utxo->pubkey); + jaddnum(item,"profit",utxo->S.profitmargin); jaddstr(item,"base",utxo->coin); jaddstr(item,"script",utxo->spendscript); return(item); } -char *LP_utxos(struct LP_peerinfo *mypeer,char *coin,int32_t lastn) +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,bits256 pubkey) +{ + uint64_t val,val2=0,threshold; char destaddr[64],destaddr2[64]; + destaddr[0] = destaddr2[0] = 0; + if ( (val= LP_txvalue(destaddr,symbol,txid,vout)) >= satoshis ) + { + threshold = (iambob != 0) ? LP_DEPOSITSATOSHIS(satoshis) : LP_DEXFEE(satoshis); + if ( (val2= LP_txvalue(destaddr2,symbol,txid2,vout2)) >= threshold ) + { + if ( strcmp(destaddr,destaddr2) != 0 ) + printf("mismatched %s destaddr %s vs %s\n",symbol,destaddr,destaddr2); + else if ( (iambob == 0 && val2 > val) || (iambob != 0 && val2 <= satoshis) ) + printf("iambob.%d ineligible due to offsides: val %.8f and val2 %.8f vs %.8f diff %lld\n",iambob,dstr(val),dstr(val2),dstr(satoshis),(long long)(val2 - val)); + else + { + *valp = val; + *val2p = val2; + return(1); + } + } else printf("no val2\n"); + } else printf("mismatched %s txid value %.8f < %.8f\n",symbol,dstr(val),dstr(satoshis)); + *valp = val; + *val2p = val2; + return(0); +} + +char *LP_utxos(int32_t iambob,struct LP_peerinfo *mypeer,char *symbol,int32_t lastn) { - int32_t i,firsti; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray(); + int32_t i,firsti,n; uint64_t val,val2; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray(); i = 0; - if ( lastn >= mypeer->numutxos ) + n = mypeer != 0 ? mypeer->numutxos : 0; + if ( lastn <= 0 ) + lastn = LP_PROPAGATION_SLACK * 2; + if ( lastn >= n ) firsti = -1; - else firsti = (mypeer->numutxos - lastn); - HASH_ITER(hh,LP_utxoinfos,utxo,tmp) + else firsti = (lastn - n); + //printf("LP_utxos iambob.%d symbol.%s firsti.%d lastn.%d\n",iambob,symbol==0?"":symbol,firsti,lastn); + HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) { + //char str[65]; printf("check %s.%s\n",utxo->coin,bits256_str(str,utxo->payment.txid)); if ( i++ < firsti ) continue; - if ( coin == 0 || coin[0] == 0 || strcmp(coin,utxo->coin) == 0 ) + if ( (symbol == 0 || symbol[0] == 0 || strcmp(symbol,utxo->coin) == 0) && utxo->T.spentflag == 0 ) { - jaddi(utxosjson,LP_utxojson(utxo)); + 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,utxo->pubkey) == 0 ) + { + char str[65]; printf("iambob.%d not eligible (%.8f %.8f) %s %s/v%d\n",iambob,dstr(val),dstr(val2),utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout); + continue; + } else jaddi(utxosjson,LP_utxojson(utxo)); } } return(jprint(utxosjson,1)); } -struct LP_utxoinfo *LP_addutxo(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *coin,bits256 txid,int32_t vout,int64_t satoshis,bits256 deposittxid,int32_t depositvout,int64_t depositsatoshis,char *spendscript,char *coinaddr,char *ipaddr,uint16_t port,double profitmargin) +int32_t LP_inventory_prevent(int32_t iambob,bits256 txid,int32_t vout) { - struct LP_utxoinfo *utxo = 0; - if ( coin == 0 || coin[0] == 0 || spendscript == 0 || spendscript[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(deposittxid) == 0 || vout < 0 || depositvout < 0 || satoshis <= 0 || depositsatoshis <= 0 ) + struct LP_utxoinfo *utxo; + if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 || (utxo= LP_utxo2find(iambob,txid,vout)) != 0 ) { - printf("malformed addutxo %d %d %d %d %d %d %d %d %d\n", coin == 0,spendscript == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(deposittxid) == 0,vout < 0,depositvout < 0,satoshis <= 0,depositsatoshis <= 0); + //if ( utxo->T.spentflag != 0 ) + { + //char str[65]; printf("prevent adding %s/v%d to inventory\n",bits256_str(str,txid),vout); + return(1); + } + } + return(0); +} + +struct LP_utxoinfo *LP_utxo_bestfit(char *symbol,uint64_t destsatoshis) +{ + struct LP_utxoinfo *utxo,*tmp,*bestutxo = 0; + if ( symbol == 0 || destsatoshis == 0 ) return(0); + HASH_ITER(hh,LP_utxoinfos[0],utxo,tmp) + { + //char str[65]; printf("check %s.%s\n",utxo->coin,bits256_str(str,utxo->payment.txid)); + if ( strcmp(symbol,utxo->coin) == 0 && LP_isavailable(utxo) > 0 && LP_ismine(utxo) > 0 ) + { + if ( utxo->S.satoshis >= destsatoshis && (bestutxo == 0 || utxo->S.satoshis < bestutxo->S.satoshis) ) + bestutxo = utxo; + } } - if ( IAMCLIENT == 0 && strcmp(ipaddr,"127.0.0.1") == 0 ) + return(bestutxo); +} + +void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector) +{ + cJSON *argjson; struct _LP_utxoinfo u; char *msg; + utxo->T.spentflag = (uint32_t)time(NULL); + if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 ) + LP_mypeer->numutxos--; + if ( LP_mypubsock >= 0 ) + { + argjson = cJSON_CreateObject(); + jaddstr(argjson,"method","checktxid"); + jaddbits256(argjson,"txid",utxo->payment.txid); + jaddnum(argjson,"vout",utxo->payment.vout); + if ( selector != 0 ) + { + if ( bits256_nonz(utxo->deposit.txid) != 0 ) + u = utxo->deposit; + else u = utxo->fee; + jaddbits256(argjson,"checktxid",u.txid); + jaddnum(argjson,"checkvout",u.vout); + } + msg = jprint(argjson,1); + LP_send(LP_mypubsock,msg,(int32_t)strlen(msg)+1,1); + } +} + +char *LP_spentcheck(cJSON *argjson) +{ + char destaddr[64]; bits256 txid,checktxid; int32_t vout,checkvout; struct LP_utxoinfo *utxo; int32_t iambob,retval = 0; + txid = jbits256(argjson,"txid"); + vout = jint(argjson,"vout"); + for (iambob=0; iambob<=1; iambob++) { - printf("LP node got localhost utxo\n"); + if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 && utxo->T.spentflag == 0 ) + { + if ( jobj(argjson,"check") == 0 ) + checktxid = txid, checkvout = vout; + else + { + checktxid = jbits256(argjson,"checktxid"); + checkvout = jint(argjson,"checkvout"); + } + if ( LP_txvalue(destaddr,utxo->coin,checktxid,checkvout) == 0 ) + { + if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 ) + LP_mypeer->numutxos--; + utxo->T.spentflag = (uint32_t)time(NULL); + retval++; + //printf("indeed txid was spent\n"); + } + } + } + if ( retval > 0 ) + return(clonestr("{\"result\":\"marked as spent\"}")); + return(clonestr("{\"error\":\"cant find txid to check spent status\"}")); +} + +struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bits256 txid,int32_t vout,int64_t value,bits256 txid2,int32_t vout2,int64_t value2,char *spendscript,char *coinaddr,bits256 pubkey,double profitmargin,char *gui) +{ + uint64_t val,val2=0,tmpsatoshis,bigtxfee = 100000; int32_t spendvini,selector; bits256 spendtxid; char *msg; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo = 0; + if ( symbol == 0 || symbol[0] == 0 || spendscript == 0 || spendscript[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 || vout < 0 || vout2 < 0 || value <= 0 || value2 <= 0 ) + { + printf("malformed addutxo %d %d %d %d %d %d %d %d %d\n", symbol == 0,spendscript == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(txid2) == 0,vout < 0,vout2 < 0,value <= 0,value2 <= 0); + return(0); + } + if ( iambob != 0 && value2 < 9 * (value >> 3) + bigtxfee ) // big txfee padding + { + if ( value2 > bigtxfee+20000 ) + tmpsatoshis = (((value2 - bigtxfee) / 9) << 3); + else return(0); + } else tmpsatoshis = value; + char str[65],str2[65],dispflag = (iambob == 0); + if ( iambob == 0 && bits256_cmp(pubkey,LP_mypubkey) != 0 ) + { + printf("trying to add Alice utxo when not mine? %s/v%d\n",bits256_str(str,txid),vout); + return(0); + } + if ( LP_iseligible(&val,&val2,iambob,symbol,txid,vout,tmpsatoshis,txid2,vout2,pubkey) <= 0 ) + { + printf("iambob.%d utxoadd got ineligible txid value %.8f, value2 %.8f, tmpsatoshis %.8f\n",iambob,dstr(value),dstr(value2),dstr(tmpsatoshis)); + return(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 ( 0 && (selector= LP_mempool_vinscan(&spendtxid,&spendvini,symbol,txid,vout,txid2,vout2)) >= 0 ) + { + printf("utxoadd selector.%d in mempool %s vini.%d",selector,bits256_str(str,spendtxid),spendvini); return(0); } - if ( (utxo= LP_utxofind(txid,vout)) != 0 ) + if ( (utxo= LP_utxofinds(iambob,txid,vout,txid2,vout2)) != 0 ) { - if ( bits256_cmp(txid,utxo->txid) != 0 || bits256_cmp(deposittxid,utxo->txid2) != 0 || vout != utxo->vout || satoshis != utxo->satoshis || depositvout != utxo->vout2 || depositsatoshis != utxo->satoshis2 || strcmp(coin,utxo->coin) != 0 || strcmp(spendscript,utxo->spendscript) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || strcmp(ipaddr,utxo->ipaddr) != 0 || port != utxo->port ) + if ( 0 && LP_ismine(utxo) == 0 ) + { + char str2[65],str3[65]; printf("iambob.%d %s %s utxoadd.(%.8f %.8f) %s %s\n",iambob,bits256_str(str3,pubkey),symbol,dstr(value),dstr(value2),bits256_str(str,txid),bits256_str(str2,txid2)); + printf("duplicate %.8f %.8f %.8f vs utxo.(%.8f %.8f %.8f)\n",dstr(value),dstr(value2),dstr(tmpsatoshis),dstr(utxo->payment.value),dstr(utxo->deposit.value),dstr(utxo->S.satoshis)); + } + u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; + if ( bits256_cmp(txid,utxo->payment.txid) != 0 || bits256_cmp(txid2,u.txid) != 0 || vout != utxo->payment.vout || value != utxo->payment.value || tmpsatoshis != utxo->S.satoshis || vout2 != u.vout || value2 != u.value || strcmp(symbol,utxo->coin) != 0 || strcmp(spendscript,utxo->spendscript) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || bits256_cmp(pubkey,utxo->pubkey) != 0 ) { - utxo->errors++; - char str[65],str2[65]; printf("error on subsequent utxo add.(%s v %s) %d %d %d %d %d %d %d %d %d %d %d\n",bits256_str(str,txid),bits256_str(str2,utxo->txid),bits256_cmp(txid,utxo->txid) != 0,bits256_cmp(deposittxid,utxo->txid2) != 0,vout != utxo->vout,satoshis != utxo->satoshis,depositvout != utxo->vout2,depositsatoshis != utxo->satoshis2,strcmp(coin,utxo->coin) != 0,strcmp(spendscript,utxo->spendscript) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,strcmp(ipaddr,utxo->ipaddr) != 0,port != utxo->port); + utxo->T.errors++; + char str[65],str2[65],str3[65],str4[65],str5[65],str6[65]; + if ( dispflag != 0 ) + printf("error on subsequent utxo iambob.%d %.8f %.8f add.(%s %s) when.(%s %s) %d %d %d %d %d %d %d %d %d %d %d pubkeys.(%s vs %s)\n",iambob,dstr(val),dstr(val2),bits256_str(str,txid),bits256_str(str2,txid2),bits256_str(str3,utxo->payment.txid),bits256_str(str4,utxo->deposit.txid),bits256_cmp(txid,utxo->payment.txid) != 0,bits256_cmp(txid2,u.txid) != 0,vout != utxo->payment.vout,tmpsatoshis != utxo->S.satoshis,vout2 != u.vout,value2 != u.value,strcmp(symbol,utxo->coin) != 0,strcmp(spendscript,utxo->spendscript) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,bits256_cmp(pubkey,utxo->pubkey) != 0,value != utxo->payment.value,bits256_str(str5,pubkey),bits256_str(str6,utxo->pubkey)); + if ( utxo->T.spentflag != 0 || LP_txvalue(utxo->coinaddr,utxo->coin,utxo->payment.txid,utxo->payment.vout) < utxo->payment.value || LP_txvalue(utxo->coinaddr,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"); + utxo = 0; + } } - else if ( profitmargin != 0. ) - utxo->profitmargin = profitmargin; + else if ( profitmargin > SMALLVAL ) + utxo->S.profitmargin = profitmargin; + if ( utxo != 0 ) + return(utxo); + } + utxo = calloc(1,sizeof(*utxo)); + utxo->S.profitmargin = profitmargin; + utxo->pubkey = pubkey; + safecopy(utxo->gui,gui,sizeof(utxo->gui)); + safecopy(utxo->coin,symbol,sizeof(utxo->coin)); + safecopy(utxo->coinaddr,coinaddr,sizeof(utxo->coinaddr)); + safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript)); + utxo->payment.txid = txid; + utxo->payment.vout = vout; + utxo->payment.value = value; + utxo->S.satoshis = tmpsatoshis; + if ( (utxo->iambob= iambob) != 0 ) + { + utxo->deposit.txid = txid2; + utxo->deposit.vout = vout2; + utxo->deposit.value = value2; } else { - utxo = calloc(1,sizeof(*utxo)); - utxo->pair = -1; - utxo->profitmargin = profitmargin; - strcpy(utxo->ipaddr,ipaddr); - utxo->port = port; - safecopy(utxo->coin,coin,sizeof(utxo->coin)); - safecopy(utxo->coinaddr,coinaddr,sizeof(utxo->coinaddr)); - safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript)); - utxo->txid = txid; - utxo->vout = vout; - utxo->satoshis = satoshis; - utxo->txid2 = deposittxid; - utxo->vout2 = depositvout; - utxo->satoshis2 = depositsatoshis; - memcpy(utxo->key,txid.bytes,sizeof(txid)); - memcpy(&utxo->key[sizeof(txid)],&vout,sizeof(vout)); - portable_mutex_lock(&LP_utxomutex); - HASH_ADD_KEYPTR(hh,LP_utxoinfos,utxo->key,sizeof(utxo->key),utxo); - if ( mypeer != 0 ) - mypeer->numutxos++; - portable_mutex_unlock(&LP_utxomutex); + utxo->fee.txid = txid2; + utxo->fee.vout = vout2; + utxo->fee.value = value2; + } + LP_utxosetkey(utxo->key,txid,vout); + LP_utxosetkey(utxo->key2,txid2,vout2); + portable_mutex_lock(&LP_utxomutex); + HASH_ADD_KEYPTR(hh,LP_utxoinfos[iambob],utxo->key,sizeof(utxo->key),utxo); + if ( _LP_utxo2find(iambob,txid2,vout2) == 0 ) + HASH_ADD_KEYPTR(hh2,LP_utxoinfos2[iambob],utxo->key2,sizeof(utxo->key2),utxo); + portable_mutex_unlock(&LP_utxomutex); + if ( iambob != 0 ) + { if ( mypubsock >= 0 ) - LP_send(mypubsock,jprint(LP_utxojson(utxo),1),1); - char str[65],str2[65]; printf("amclient.%d %s:%u %s LP_addutxo.(%.8f %.8f) numutxos.%d %s %s\n",IAMCLIENT,ipaddr,port,utxo->coin,dstr(satoshis),dstr(depositsatoshis),mypeer!=0?mypeer->numutxos:0,bits256_str(str,utxo->txid),bits256_str(str2,txid)); + { + msg = jprint(LP_utxojson(utxo),1); + LP_send(mypubsock,msg,(int32_t)strlen(msg)+1,1); + } else LP_utxo_clientpublish(utxo); + if ( LP_mypeer != 0 && LP_ismine(utxo) > 0 ) + LP_mypeer->numutxos++; } return(utxo); } -int32_t LP_utxosparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now) +struct LP_utxoinfo *LP_utxoaddjson(int32_t iambob,int32_t pubsock,cJSON *argjson) { - struct LP_peerinfo *peer,*destpeer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; bits256 txid; struct LP_utxoinfo *utxo; - if ( amclient != 0 ) + struct LP_utxoinfo *utxo; + if ( jobj(argjson,"iambob") == 0 || iambob != jint(argjson,"iambob") ) { - printf("LP_utxosparse not for clientside\n"); - return(-1); + printf("LP_utxoaddjson: iambob.%d != arg.%d obj.%p (%s)\n",iambob,jint(argjson,"iambob"),jobj(argjson,"iambob"),jprint(argjson,0)); + return(0); } + portable_mutex_lock(&LP_UTXOmutex); + utxo = LP_utxoadd(iambob,pubsock,jstr(argjson,"coin"),jbits256(argjson,"txid"),jint(argjson,"vout"),j64bits(argjson,"value"),jbits256(argjson,"txid2"),jint(argjson,"vout2"),j64bits(argjson,"value2"),jstr(argjson,"script"),jstr(argjson,"address"),jbits256(argjson,"pubkey"),jdouble(argjson,"profit"),jstr(argjson,"gui")); + portable_mutex_unlock(&LP_UTXOmutex); + return(utxo); +} + +int32_t LP_utxosparse(char *destipaddr,uint16_t destport,char *retstr,uint32_t now) +{ + struct LP_peerinfo *destpeer,*peer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; bits256 txid; struct LP_utxoinfo *utxo; + //printf("parse.(%s)\n",retstr); if ( (array= cJSON_Parse(retstr)) != 0 ) { if ( (n= cJSON_GetArraySize(array)) > 0 ) @@ -157,24 +544,23 @@ int32_t LP_utxosparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubs subport = argport + 2; argipbits = (uint32_t)calc_ipbits(argipaddr); if ( (peer= LP_peerfind(argipbits,argport)) == 0 ) - peer = LP_addpeer(amclient,mypeer,mypubsock,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos")); - if ( jobj(item,"txid") != 0 ) + peer = LP_addpeer(0,-1,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos")); + } + if ( jobj(item,"txid") != 0 ) + { + txid = jbits256(item,"txid"); + //printf("parse.(%s)\n",jprint(item,0)); + if ( (utxo= LP_utxoaddjson(1,-1,item)) != 0 ) { - txid = jbits256(item,"txid"); - utxo = LP_addutxo(amclient,mypeer,mypubsock,jstr(item,"coin"),txid,jint(item,"vout"),SATOSHIDEN*jdouble(item,"value"),jbits256(item,"txid2"),jint(item,"vout2"),SATOSHIDEN * jdouble(item,"value2"),jstr(item,"script"),jstr(item,"address"),argipaddr,argport,jdouble(item,"profit")); - if ( utxo != 0 ) - utxo->lasttime = now; + //if ( strcmp(utxo->coin,"HUSH") == 0 ) + // printf("%s set lasttime (%s)\n",destipaddr,jprint(item,0)); + utxo->T.lasttime = now; } } } if ( (destpeer= LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport)) != 0 ) { destpeer->numutxos = n; - if ( destpeer->numutxos < n ) - { - //destpeer->numutxos = n; - //printf("got.(%s) from %s numutxos.%d\n",retstr,destpeer->ipaddr,destpeer->numutxos); - } } } free_json(array); @@ -182,29 +568,27 @@ int32_t LP_utxosparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubs return(n); } -void LP_utxosquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *coin,int32_t lastn,char *myipaddr,uint16_t myport,double myprofit) +int32_t LP_utxosquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *coin,int32_t lastn,char *myipaddr,uint16_t myport,double myprofit) { - char *retstr; struct LP_peerinfo *peer; int32_t i,firsti; uint32_t now; - if ( amclient != 0 ) - { - printf("LP_utxosquery not for clientside\n"); - return; - } + char *retstr; struct LP_peerinfo *peer; uint32_t now; int32_t retval = -1; peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); - if ( mypeer == 0 ) //(peer != 0 && peer->errors > 0) || - return; if ( coin == 0 ) coin = ""; - if ( (retstr= issue_LP_getutxos(destipaddr,destport,coin,lastn,myipaddr,myport,myprofit,mypeer->numpeers,mypeer->numutxos)) != 0 ) + //printf("utxo query.(%s)\n",destipaddr); + if ( IAMLP != 0 ) + retstr = issue_LP_getutxos(destipaddr,destport,coin,lastn,myipaddr,myport,myprofit,mypeer != 0 ? mypeer->numpeers : 0,mypeer != 0 ? mypeer->numutxos : 0); + else retstr = issue_LP_clientgetutxos(destipaddr,destport,coin,100); + if ( retstr != 0 ) { now = (uint32_t)time(NULL); - LP_utxosparse(amclient,mypeer,mypubsock,destipaddr,destport,retstr,now); + retval = LP_utxosparse(destipaddr,destport,retstr,now); + //printf("got.(%s)\n",retstr); free(retstr); - i = 0; + /*i = 0; if ( lastn >= mypeer->numutxos ) firsti = -1; else firsti = (mypeer->numutxos - lastn); - /*HASH_ITER(hh,LP_utxoinfos,utxo,tmp) + HASH_ITER(hh,LP_utxoinfos,utxo,tmp) { if ( i++ < firsti ) continue; @@ -218,22 +602,25 @@ void LP_utxosquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock } if ( flag != 0 ) printf(" <- missing utxos\n");*/ - } else if ( peer != 0 ) - peer->errors++; + } + return(retval); } -char *LP_inventory(char *symbol) +cJSON *LP_inventory(char *symbol,int32_t iambob) { - struct LP_utxoinfo *utxo,*tmp; char *myipaddr; cJSON *array = cJSON_CreateArray(); + struct LP_utxoinfo *utxo,*tmp; char *myipaddr; cJSON *array; + array = cJSON_CreateArray(); if ( LP_mypeer != 0 ) myipaddr = LP_mypeer->ipaddr; else myipaddr = "127.0.0.1"; - HASH_ITER(hh,LP_utxoinfos,utxo,tmp) + HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) { - if ( strcmp(symbol,utxo->coin) == 0 && (IAMCLIENT != 0 || strcmp(utxo->ipaddr,myipaddr) == 0) ) + //char str[65]; printf("iambob.%d iterate %s\n",iambob,bits256_str(str,LP_mypubkey)); + if ( LP_isunspent(utxo) != 0 && strcmp(symbol,utxo->coin) == 0 && utxo->iambob == iambob && LP_ismine(utxo) > 0 ) jaddi(array,LP_inventoryjson(cJSON_CreateObject(),utxo)); + //else printf("skip %s %d %d %d %d\n",bits256_str(str,utxo->pubkey),LP_isunspent(utxo) != 0,strcmp(symbol,utxo->coin) == 0,utxo->iambob == iambob,LP_ismine(utxo) > 0); } - return(jprint(array,1)); + return(array); } int32_t LP_maxvalue(uint64_t *values,int32_t n) @@ -265,102 +652,145 @@ int32_t LP_nearestvalue(uint64_t *values,int32_t n,uint64_t targetval) return(mini); } -uint64_t LP_privkey_init(struct LP_peerinfo *mypeer,int32_t mypubsock,char *symbol,char *passphrase,char *wifstr,int32_t amclient) +uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 myprivkey,bits256 mypub,uint8_t *pubkey33) { - static uint32_t counter; - char coinaddr[64],*script; struct LP_utxoinfo *utxo; cJSON *array,*item,*retjson; bits256 userpass,userpub,txid,deposittxid; int32_t used,i,n,vout,depositvout; uint64_t *values,satoshis,depositval,targetval,value,total = 0; bits256 privkey,pubkey; uint8_t pubkey33[33],tmptype,rmd160[20]; struct iguana_info *coin = LP_coinfind(symbol); + char *script; struct LP_utxoinfo *utxo; cJSON *array,*item; bits256 txid,deposittxid; int32_t used,i,n,iambob,vout,depositvout; uint64_t *values=0,satoshis,depositval,targetval,value,total = 0; if ( coin == 0 ) { - printf("cant add privkey for %s, coin not active\n",symbol); + printf("coin not active\n"); return(0); } - if ( passphrase != 0 ) - conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); - else privkey = iguana_wif2privkey(wifstr); - iguana_priv2pub(pubkey33,coinaddr,privkey,coin->pubtype); - if ( strcmp("BTC",symbol) == 0 ) - strcpy(BTCADDR,coinaddr); - else if ( strcmp("KMD",symbol) == 0 ) - strcpy(KMDADDR,coinaddr); - if ( counter == 0 ) - { - char tmpstr[128]; - counter++; - bitcoin_priv2wif(USERPASS_WIFSTR,privkey,188); - bitcoin_priv2wif(tmpstr,privkey,coin->wiftype); - conv_NXTpassword(userpass.bytes,pubkey.bytes,(uint8_t *)tmpstr,(int32_t)strlen(tmpstr)); - userpub = curve25519(userpass,curve25519_basepoint9()); - printf("userpass.(%s)\n",bits256_str(USERPASS,userpub)); - printf("%s (%s) %d wif.(%s) (%s)\n",symbol,coinaddr,coin->pubtype,tmpstr,passphrase); - if ( (retjson= LP_importprivkey(coin->symbol,tmpstr,coinaddr,-1)) != 0 ) - printf("importprivkey -> (%s)\n",jprint(retjson,1)); - } - bitcoin_addr2rmd160(&tmptype,rmd160,coinaddr); - LP_privkeyadd(privkey,rmd160); - if ( (array= LP_listunspent(symbol,coinaddr)) != 0 ) + //printf("privkey init.(%s) %s\n",coin->symbol,coin->smartaddr); + if ( coin->inactive == 0 && (array= LP_listunspent(coin->symbol,coin->smartaddr)) != 0 ) { if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) { - values = calloc(n,sizeof(*values)); - for (i=0; i= 0 ) + if ( iambob == 0 ) + values = calloc(n,sizeof(*values)); + else memset(values,0,n * sizeof(*values)); + //if ( iambob == 0 && IAMLP != 0 ) + // continue; + used = 0; + for (i=0; i= 0 ) + satoshis = SATOSHIDEN * jdouble(item,"amount"); + if ( LP_inventory_prevent(iambob,jbits256(item,"txid"),juint(item,"vout")) == 0 ) + values[i] = satoshis; + else used++; + //printf("%.8f ",dstr(satoshis)); + } + //printf("array.%d\n",n); + while ( used < n-1 ) + { + //printf("used.%d of n.%d\n",used,n); + if ( (i= LP_maxvalue(values,n)) >= 0 ) { item = jitem(array,i); - txid = jbits256(item,"txid"); - vout = juint(item,"vout"); - if ( jstr(item,"scriptPubKey") != 0 && strcmp(script,jstr(item,"scriptPubKey")) == 0 ) + deposittxid = jbits256(item,"txid"); + depositvout = juint(item,"vout"); + script = jstr(item,"scriptPubKey"); + depositval = values[i]; + values[i] = 0, used++; + if ( iambob == 0 ) + targetval = (depositval / 776) + 100000; + else targetval = (depositval / 9) * 8 + 100000; + //printf("i.%d %.8f target %.8f\n",i,dstr(depositval),dstr(targetval)); + if ( (i= LP_nearestvalue(values,n,targetval)) < 0 && iambob != 0 ) + targetval /= 4; + if ( (i= LP_nearestvalue(values,n,targetval)) >= 0 ) { - value = values[i]; - values[i] = 0, used++; - if ( amclient == 0 ) - { - if ( (utxo= LP_addutxo(amclient,mypeer,mypubsock,symbol,txid,vout,value,deposittxid,depositvout,depositval,script,coinaddr,LP_peerinfos[0].ipaddr,LP_peerinfos[0].port,LP_peerinfos[0].profitmargin)) != 0 ) - utxo->mypub = curve25519(privkey,curve25519_basepoint9()); - } - else + item = jitem(array,i); + txid = jbits256(item,"txid"); + vout = juint(item,"vout"); + if ( jstr(item,"scriptPubKey") != 0 && strcmp(script,jstr(item,"scriptPubKey")) == 0 ) { - if ( (utxo= LP_addutxo(amclient,mypeer,mypubsock,symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coinaddr,"127.0.0.1",0,0)) != 0 ) - utxo->mypub = curve25519(privkey,curve25519_basepoint9()); + value = values[i]; + values[i] = 0, used++; + portable_mutex_lock(&LP_UTXOmutex); + if ( iambob != 0 ) + { + if ( (utxo= LP_utxoadd(1,mypubsock,coin->symbol,txid,vout,value,deposittxid,depositvout,depositval,script,coin->smartaddr,mypub,LP_mypeer != 0 ? LP_mypeer->profitmargin : 0.01,LP_gui)) != 0 ) + { + } + } + else + { + if ( (utxo= LP_utxoadd(0,mypubsock,coin->symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coin->smartaddr,mypub,0.,LP_gui)) != 0 ) + { + } + } + portable_mutex_unlock(&LP_UTXOmutex); + total += value; } - total += value; } - } - } else break; + } else break; + } + if ( iambob == 1 ) + free(values); } - free(values); } free_json(array); } + //printf("privkey.%s %.8f\n",symbol,dstr(total)); return(total); } -void LP_privkey_updates(struct LP_peerinfo *mypeer,int32_t pubsock,char *passphrase,int32_t amclient) +bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguana_info *coin,char *passphrase,char *wifstr) { - int32_t i; - for (i=0; ibytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); + else + { + privkey = iguana_wif2privkey(wifstr); + //printf("WIF.(%s) -> %s\n",wifstr,bits256_str(str,privkey)); + } + iguana_priv2pub(ctx,pubkey33,coin->smartaddr,privkey,coin->taddr,coin->pubtype); + if ( coin->counter == 0 ) + { + coin->counter++; + bitcoin_priv2wif(tmpstr,privkey,coin->wiftype); + bitcoin_addr2rmd160(coin->taddr,&tmptype,rmd160,coin->smartaddr); + LP_privkeyadd(privkey,rmd160); + if ( 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 ( coin->inactive == 0 ) + printf("importprivkey: %s\n",jprint(LP_importprivkey(coin->symbol,tmpstr,"",-1),1)); + if ( counter++ == 0 ) + { + bitcoin_priv2wif(USERPASS_WIFSTR,privkey,188); + conv_NXTpassword(userpass.bytes,pubkeyp->bytes,(uint8_t *)USERPASS_WIFSTR,(int32_t)strlen(USERPASS_WIFSTR)); + userpub = curve25519(userpass,curve25519_basepoint9()); + printf("userpass.(%s)\n",bits256_str(USERPASS,userpub)); + } + if ( coin->inactive == 0 && (retjson= LP_importprivkey(coin->symbol,tmpstr,coin->smartaddr,-1)) != 0 ) + printf("importprivkey -> (%s)\n",jprint(retjson,1)); + } + LP_mypubkey = *pubkeyp = curve25519(privkey,curve25519_basepoint9()); + //printf("privkey.(%s) -> LP_mypubkey.(%s)\n",bits256_str(str,privkey),bits256_str(str2,LP_mypubkey)); + return(privkey); +} + +void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase,int32_t initonly) +{ + int32_t i; struct iguana_info *coin; bits256 pubkey,privkey; uint8_t pubkey33[33]; + memset(privkey.bytes,0,sizeof(privkey)); + pubkey = privkey; + for (i=0; ismartaddr[0] == 0 ) + privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,coin,passphrase,""); + if ( coin->inactive == 0 && initonly == 0 ) + LP_privkey_init(pubsock,coin,privkey,pubkey,pubkey33); + } + } } diff --git a/iguana/exchanges/autotrade b/iguana/exchanges/autotrade index c24a0a89a..371532304 100755 --- a/iguana/exchanges/autotrade +++ b/iguana/exchanges/autotrade @@ -1,2 +1,2 @@ source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autotrade\",\"txid\":\"$1\",\"vout\":$2,\"coin\":\"REVS\",\"maxprice\":$3}" +curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autotrade\",\"base\":\"REVS\",\"rel\":\"KMD\",\"volume\":1.01,\"price\":1.234}" diff --git a/iguana/exchanges/bitcoin.c b/iguana/exchanges/bitcoin.c index 452c8c075..62c0ed592 100755 --- a/iguana/exchanges/bitcoin.c +++ b/iguana/exchanges/bitcoin.c @@ -19,7 +19,7 @@ cJSON *instantdex_statemachinejson(struct bitcoin_swapinfo *swap); char *bitcoind_passthru(char *coinstr,char *serverport,char *userpass,char *method,char *params) { - return(bitcoind_RPC(0,coinstr,serverport,userpass,method,params)); + return(bitcoind_RPC(0,coinstr,serverport,userpass,method,params,0)); } int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr) diff --git a/iguana/exchanges/client b/iguana/exchanges/client index 261b1d36a..6582e2c82 100755 --- a/iguana/exchanges/client +++ b/iguana/exchanges/client @@ -1,2 +1,24 @@ source randval -pkill -15 marketmaker; git pull; cd ..; ./m_mm; ./marketmaker "{\"client\":1,\"passphrase\":\"$randval\"}" & +pkill -15 marketmaker; +git pull; + cd ..; +./m_mm; +./marketmaker "{\"gui\":\"nogui\",\"client\":1,\"coins\":[{\"coin\":\"REVS\",\"active\":1, \"asset\":\"REVS\",\"rpcport\":10196},{\"coin\":\"JUMBLR\",\"active\":1, \"asset\":\"JUMBLR\",\"rpcport\":15106}, +{\"coin\":\"DOGE\", \"name\":\"dogecoin\", \"pubtype\":30, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000000}, +{\"active\":0,\"coin\":\"HUSH\",\"name\":\"hush\",\"rpcport\":8822,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000 }, +{\"active\":0,\"coin\":\"ZEC\",\"name\":\"zcash\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000 }, +{\"coin\":\"DGB\", \"name\":\"digibyte\", \"pubtype\":30, \"p2shtype\":5, \"wiftype\":128, \"txfee\":10000}, +{\"coin\":\"MZC\", \"name\":\"mazacoin\", \"pubtype\":50, \"p2shtype\":9, \"wiftype\":224, \"txfee\":0}, +{\"coin\":\"SYS\", \"name\":\"syscoin\", \"pubtype\":0, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000}, +{\"coin\":\"UNO\", \"name\":\"unobtanium\", \"pubtype\":130, \"p2shtype\":30, \"wiftype\":224, \"txfee\":1000000}, +{\"coin\":\"ZET\", \"name\":\"zetacoin\", \"pubtype\":80, \"p2shtype\":9, \"wiftype\":224, \"txfee\":10000}, +{\"coin\":\"ZEC\", \"name\":\"zcash\", \"pubtype\":184, \"p2shtype\":189, \"wiftype\":128, \"txfee\":10000}, +{\"coin\":\"BTM\", \"name\":\"bitmark\", \"pubtype\":85, \"p2shtype\":5, \"wiftype\":213, \"txfee\":0}, +{\"coin\":\"CARB\", \"name\":\"carboncoin\", \"pubtype\":47, \"p2shtype\":5, \"wiftype\":175, \"txfee\":0}, +{\"coin\":\"ANC\", \"name\":\"anoncoin\", \"pubtype\":23, \"p2shtype\":5, \"wiftype\":151, \"txfee\":2000000}, +{\"coin\":\"FRK\", \"name\":\"franko\", \"pubtype\":35, \"p2shtype\":5, \"wiftype\":163, \"txfee\":0}, +{\"coin\":\"GAME\", \"name\":\"gamecredits\", \"pubtype\":38, \"p2shtype\":5, \"wiftype\":166, \"txfee\":100000}, +{\"coin\":\"LTC\", \"name\":\"litecoin\", \"rpcport\":9332, \"pubtype\":48, \"p2shtype\":5, \"wiftype\":176, \"txfee\":100000 }, +{\"coin\":\"SUPERNET\",\"asset\":\"SUPERNET\",\"rpcport\":11341},{\"coin\":\"WLC\",\"asset\":\"WLC\",\"rpcport\":12167},{\"coin\":\"PANGEA\",\"asset\":\"PANGEA\",\"rpcport\":14068},{\"coin\":\"DEX\",\"asset\":\"DEX\",\"rpcport\":11890},{\"coin\":\"BET\",\"asset\":\"BET\",\"rpcport\":14250},{\"coin\":\"CRYPTO\",\"asset\":\"CRYPTO\",\"rpcport\":8516},{\"coin\":\"HODL\",\"asset\":\"HODL\",\"rpcport\":14431},{\"coin\":\"SHARK\",\"asset\":\"SHARK\",\"rpcport\":10114},{\"coin\":\"BOTS\",\"asset\":\"BOTS\",\"rpcport\":11964},{\"coin\":\"MGW\",\"asset\":\"MGW\",\"rpcport\":12386},{\"coin\":\"COQUI\",\"asset\":\"COQUI\",\"rpcport\":12456},{\"coin\":\"KV\",\"asset\":\"KV\",\"rpcport\":9747},{\"coin\":\"CEAL\",\"asset\":\"CEAL\",\"rpcport\":11116},{\"coin\":\"MESH\",\"asset\":\"MESH\",\"rpcport\":9455} +], \"userhome\":\"/${HOME#"/"}\",\"passphrase\":\"$randval\"}" & + diff --git a/iguana/exchanges/client_osx b/iguana/exchanges/client_osx new file mode 100755 index 000000000..a46cbff64 --- /dev/null +++ b/iguana/exchanges/client_osx @@ -0,0 +1,22 @@ +source randval +pkill -15 marketmaker; +git pull; + cd ..; +./m_mm; +./marketmaker "{\"client\":1,\"coins\":[{\"coin\":\"REVS\",\"active\":1, \"asset\":\"REVS\",\"rpcport\":10196},{\"coin\":\"JUMBLR\",\"active\":1, \"asset\":\"JUMBLR\",\"rpcport\":15106}, +{\"coin\":\"DOGE\", \"name\":\"dogecoin\", \"pubtype\":30, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000000}, +{\"coin\":\"DGB\", \"name\":\"digibyte\", \"pubtype\":30, \"p2shtype\":5, \"wiftype\":128, \"txfee\":10000}, +{\"coin\":\"MZC\", \"name\":\"mazacoin\", \"pubtype\":50, \"p2shtype\":9, \"wiftype\":224, \"txfee\":0}, +{\"coin\":\"SYS\", \"name\":\"syscoin\", \"pubtype\":0, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000}, +{\"coin\":\"UNO\", \"name\":\"unobtanium\", \"pubtype\":130, \"p2shtype\":30, \"wiftype\":224, \"txfee\":1000000}, +{\"coin\":\"ZET\", \"name\":\"zetacoin\", \"pubtype\":80, \"p2shtype\":9, \"wiftype\":224, \"txfee\":10000}, +{\"coin\":\"ZEC\", \"name\":\"zcash\", \"pubtype\":184, \"p2shtype\":189, \"wiftype\":128, \"txfee\":10000}, +{\"coin\":\"BTM\", \"name\":\"bitmark\", \"pubtype\":85, \"p2shtype\":5, \"wiftype\":213, \"txfee\":0}, +{\"coin\":\"CARB\", \"name\":\"carboncoin\", \"pubtype\":47, \"p2shtype\":5, \"wiftype\":175, \"txfee\":0}, +{\"coin\":\"ANC\", \"name\":\"anoncoin\", \"pubtype\":23, \"p2shtype\":5, \"wiftype\":151, \"txfee\":2000000}, +{\"coin\":\"FRK\", \"name\":\"franko\", \"pubtype\":35, \"p2shtype\":5, \"wiftype\":163, \"txfee\":0}, +{\"coin\":\"GAME\", \"name\":\"gamecredits\", \"pubtype\":38, \"p2shtype\":5, \"wiftype\":166, \"txfee\":100000}, +{\"coin\":\"LTC\", \"name\":\"litecoin\", \"rpcport\":9332, \"pubtype\":48, \"p2shtype\":5, \"wiftype\":176, \"txfee\":100000 }, +{\"coin\":\"SUPERNET\",\"asset\":\"SUPERNET\",\"rpcport\":11341},{\"coin\":\"WLC\",\"asset\":\"WLC\",\"rpcport\":12167},{\"coin\":\"PANGEA\",\"asset\":\"PANGEA\",\"rpcport\":14068},{\"coin\":\"DEX\",\"asset\":\"DEX\",\"rpcport\":11890},{\"coin\":\"BET\",\"asset\":\"BET\",\"rpcport\":14250},{\"coin\":\"CRYPTO\",\"asset\":\"CRYPTO\",\"rpcport\":8516},{\"coin\":\"HODL\",\"asset\":\"HODL\",\"rpcport\":14431},{\"coin\":\"SHARK\",\"asset\":\"SHARK\",\"rpcport\":10114},{\"coin\":\"BOTS\",\"asset\":\"BOTS\",\"rpcport\":11964},{\"coin\":\"MGW\",\"asset\":\"MGW\",\"rpcport\":12386},{\"coin\":\"MVP\",\"asset\":\"MVP\",\"rpcport\":8655},{\"coin\":\"KV\",\"asset\":\"KV\",\"rpcport\":9747},{\"coin\":\"CEAL\",\"asset\":\"CEAL\",\"rpcport\":11116},{\"coin\":\"MESH\",\"asset\":\"MESH\",\"rpcport\":9455} +], \"userhome\":\"/${HOME#"/"}/Library/Application\ Support\", \"passphrase\":\"$randval\"}" & + diff --git a/iguana/exchanges/getprice b/iguana/exchanges/disable similarity index 54% rename from iguana/exchanges/getprice rename to iguana/exchanges/disable index 4b9614be7..c74b84fd5 100755 --- a/iguana/exchanges/getprice +++ b/iguana/exchanges/disable @@ -1,2 +1,2 @@ source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"REVS\",\"rel\":\"KMD\"}" +curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"disable\",\"coin\":\"REVS\"}" diff --git a/iguana/exchanges/enable b/iguana/exchanges/enable new file mode 100755 index 000000000..a974c1860 --- /dev/null +++ b/iguana/exchanges/enable @@ -0,0 +1,2 @@ +source userpass +curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"BTC\"}" diff --git a/iguana/exchanges/forward b/iguana/exchanges/forward new file mode 100755 index 000000000..966e6af67 --- /dev/null +++ b/iguana/exchanges/forward @@ -0,0 +1,2 @@ +source userpass +curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"6578099f6474d9b8bd66a7a136b922029a989818ec0309aee962dd6ac1862b74\",\"method\":\"forward\",\"method2\":\"getprice\",\"base\":\"REVS\",\"rel\":\"KMD\"}" diff --git a/iguana/exchanges/getcoins b/iguana/exchanges/getcoins new file mode 100755 index 000000000..132e9a9c0 --- /dev/null +++ b/iguana/exchanges/getcoins @@ -0,0 +1,2 @@ +source userpass +curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"getcoins\"}" diff --git a/iguana/exchanges/getprices b/iguana/exchanges/getprices new file mode 100755 index 000000000..216b2b86c --- /dev/null +++ b/iguana/exchanges/getprices @@ -0,0 +1,2 @@ +source userpass +curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"getprices\",\"coin\":\"REVS\"}" diff --git a/iguana/exchanges/getutxos b/iguana/exchanges/getutxos new file mode 100755 index 000000000..a84c72fb0 --- /dev/null +++ b/iguana/exchanges/getutxos @@ -0,0 +1,2 @@ +source userpass +curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"getutxos\",\"coin\":\"REVS\"}" diff --git a/iguana/exchanges/help b/iguana/exchanges/help new file mode 100755 index 000000000..a5f08aa50 --- /dev/null +++ b/iguana/exchanges/help @@ -0,0 +1,2 @@ +source userpass +curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"help\"}" diff --git a/iguana/exchanges/inv b/iguana/exchanges/inv index b0b5e52b1..3d6669329 100755 --- a/iguana/exchanges/inv +++ b/iguana/exchanges/inv @@ -1,2 +1,2 @@ source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"inventory\",\"coin\":\"KMD\"}" +curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"inventory\",\"coin\":\"BTC\"}" diff --git a/iguana/exchanges/lookup b/iguana/exchanges/lookup new file mode 100755 index 000000000..af9cdd645 --- /dev/null +++ b/iguana/exchanges/lookup @@ -0,0 +1,2 @@ +source userpass +curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"6578099f6474d9b8bd66a7a136b922029a989818ec0309aee962dd6ac1862b74\",\"method\":\"forward\",\"method2\":\"lookup\",\"client\":\"$1\"}" diff --git a/iguana/exchanges/loop b/iguana/exchanges/loop new file mode 100755 index 000000000..8703827ba --- /dev/null +++ b/iguana/exchanges/loop @@ -0,0 +1,7 @@ +while true +do +source userpass +#curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"setprice\",\"base\":\"REVS\",\"rel\":\"KMD\",\"price\":1.234}" +./s +sleep 3600 +done diff --git a/iguana/exchanges/mm.c b/iguana/exchanges/mm.c index c69d170f0..1babc9d76 100644 --- a/iguana/exchanges/mm.c +++ b/iguana/exchanges/mm.c @@ -24,11 +24,12 @@ #include #include "OS_portable.h" #define MAX(a,b) ((a) > (b) ? (a) : (b)) -char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port); +char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,cJSON *argjson,char *remoteaddr,uint16_t port); #include "stats.c" void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32]); -#if defined(__APPLE__) || defined(WIN32) || defined(USE_STATIC_NANOMSG) +//defined(__APPLE__) || +#if defined(WIN32) || defined(USE_STATIC_NANOMSG) #include "../../crypto777/nanosrc/nn.h" #include "../../crypto777/nanosrc/bus.h" #include "../../crypto777/nanosrc/pubsub.h" @@ -70,7 +71,7 @@ char *DEX_swapstatus() char url[512],postdata[1024]; sprintf(url,"%s/?",IGUANA_URL); sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"getswaplist\"}"); - return(bitcoind_RPC(0,"InstantDEX",url,0,"getswaplist",postdata)); + return(bitcoind_RPC(0,"InstantDEX",url,0,"getswaplist",postdata,0)); } char *DEX_amlp(char *blocktrail) @@ -78,7 +79,7 @@ char *DEX_amlp(char *blocktrail) char url[512],postdata[1024]; sprintf(url,"%s/?",IGUANA_URL); sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"amlp\",\"blocktrail\":\"%s\"}",blocktrail); - return(bitcoind_RPC(0,"tradebot",url,0,"amlp",postdata)); + return(bitcoind_RPC(0,"tradebot",url,0,"amlp",postdata,0)); } char *DEX_openorders(char *exchange) @@ -86,7 +87,7 @@ char *DEX_openorders(char *exchange) char url[512],postdata[1024]; sprintf(url,"%s/?",IGUANA_URL); sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"openorders\",\"exchange\":\"%s\"}",exchange); - return(bitcoind_RPC(0,"InstantDEX",url,0,"openorders",postdata)); + return(bitcoind_RPC(0,"InstantDEX",url,0,"openorders",postdata,0)); } char *DEX_tradehistory(char *exchange) @@ -94,7 +95,7 @@ char *DEX_tradehistory(char *exchange) char url[512],postdata[1024]; sprintf(url,"%s/?",IGUANA_URL); sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"tradehistory\",\"exchange\":\"%s\"}",exchange); - return(bitcoind_RPC(0,"InstantDEX",url,0,"tradehistory",postdata)); + return(bitcoind_RPC(0,"InstantDEX",url,0,"tradehistory",postdata,0)); } char *DEX_orderstatus(char *exchange,char *orderid) @@ -102,7 +103,7 @@ char *DEX_orderstatus(char *exchange,char *orderid) char url[512],postdata[1024]; sprintf(url,"%s/?",IGUANA_URL); sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"orderstatus\",\"exchange\":\"%s\",\"orderid\":\"%s\"}",exchange,orderid); - return(bitcoind_RPC(0,"InstantDEX",url,0,"orderstatus",postdata)); + return(bitcoind_RPC(0,"InstantDEX",url,0,"orderstatus",postdata,0)); } char *DEX_cancelorder(char *exchange,char *orderid) @@ -110,7 +111,7 @@ char *DEX_cancelorder(char *exchange,char *orderid) char url[512],postdata[1024]; sprintf(url,"%s/?",IGUANA_URL); sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"cancelorder\",\"exchange\":\"%s\",\"orderid\":\"%s\"}",exchange,orderid); - return(bitcoind_RPC(0,"InstantDEX",url,0,"cancelorder",postdata)); + return(bitcoind_RPC(0,"InstantDEX",url,0,"cancelorder",postdata,0)); } char *DEX_balance(char *exchange,char *base,char *coinaddr) @@ -120,12 +121,12 @@ char *DEX_balance(char *exchange,char *base,char *coinaddr) if ( strcmp(exchange,"DEX") == 0 ) { sprintf(postdata,"{\"agent\":\"dex\",\"method\":\"getbalance\",\"address\":\"%s\",\"symbol\":\"%s\"}",coinaddr,base); - return(bitcoind_RPC(0,"dex",url,0,"getbalance",postdata)); + return(bitcoind_RPC(0,"dex",url,0,"getbalance",postdata,0)); } else { sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"balance\",\"exchange\":\"%s\",\"base\":\"%s\"}",exchange,base); - return(bitcoind_RPC(0,"InstantDEX",url,0,"balance",postdata)); + return(bitcoind_RPC(0,"InstantDEX",url,0,"balance",postdata,0)); } } @@ -134,7 +135,7 @@ char *DEX_apikeypair(char *exchange,char *apikey,char *apisecret) char url[512],postdata[1024]; sprintf(url,"%s/?",IGUANA_URL); sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"apikeypair\",\"exchange\":\"%s\",\"apikey\":\"%s\",\"apisecret\":\"%s\"}",exchange,apikey,apisecret); - return(bitcoind_RPC(0,"InstantDEX",url,0,"apikeypair",postdata)); + return(bitcoind_RPC(0,"InstantDEX",url,0,"apikeypair",postdata,0)); } char *DEX_setuserid(char *exchange,char *userid,char *tradepassword) @@ -142,7 +143,7 @@ char *DEX_setuserid(char *exchange,char *userid,char *tradepassword) char url[512],postdata[1024]; sprintf(url,"%s/?",IGUANA_URL); sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"setuserid\",\"exchange\":\"%s\",\"userid\":\"%s\",\"tradepassword\":\"%s\"}",exchange,userid,tradepassword); - return(bitcoind_RPC(0,"InstantDEX",url,0,"setuserid",postdata)); + return(bitcoind_RPC(0,"InstantDEX",url,0,"setuserid",postdata,0)); } char *DEX_trade(char *exchange,char *base,char *rel,int32_t dir,double price,double volume) @@ -151,7 +152,7 @@ char *DEX_trade(char *exchange,char *base,char *rel,int32_t dir,double price,dou sprintf(url,"%s/?",IGUANA_URL); sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"%s\",\"exchange\":\"%s\",\"base\":\"%s\",\"rel\":\"%s\",\"price\":%.8f,\"volume\":%.8f,\"dotrade\":1}",dir>0?"buy":"sell",exchange,base,rel,price,volume); //printf("DEX_trade.(%s)\n",postdata); - return(bitcoind_RPC(0,"InstantDEX",url,0,dir>0?"buy":"sell",postdata)); + return(bitcoind_RPC(0,"InstantDEX",url,0,dir>0?"buy":"sell",postdata,0)); } char *DEX_withdraw(char *exchange,char *base,char *destaddr,double amount) @@ -159,7 +160,7 @@ char *DEX_withdraw(char *exchange,char *base,char *destaddr,double amount) char url[512],postdata[1024]; sprintf(url,"%s/?",IGUANA_URL); sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"withdraw\",\"exchange\":\"%s\",\"destaddr\":\"%s\",\"amount\":%.8f}",exchange,destaddr,amount); - return(bitcoind_RPC(0,"InstantDEX",url,0,"withdraw",postdata)); + return(bitcoind_RPC(0,"InstantDEX",url,0,"withdraw",postdata,0)); } char *iguana_walletpassphrase(char *passphrase,int32_t timeout) @@ -167,7 +168,7 @@ char *iguana_walletpassphrase(char *passphrase,int32_t timeout) char url[512],postdata[1024]; sprintf(url,"%s/coin=KMD&agent=bitcoinrpc&method=walletpassphrase?",IGUANA_URL); sprintf(postdata,"[\"%s\", %d]",passphrase,timeout); - return(bitcoind_RPC(0,"",url,0,"walletpassphrase",postdata)); + return(bitcoind_RPC(0,"",url,0,"walletpassphrase",postdata,0)); } /*char *iguana_listunspent(char *coin,char *coinaddr) @@ -194,7 +195,7 @@ char *DEX_listunspent(char *coin,char *coinaddr) char url[512],postdata[1024]; sprintf(url,"%s/?",IGUANA_URL); sprintf(postdata,"{\"agent\":\"dex\",\"method\":\"listunspent\",\"address\":\"%s\",\"symbol\":\"%s\",\"timeout\":60000}",coinaddr,coin); - return(bitcoind_RPC(0,"dex",url,0,"listunspent",postdata)); + return(bitcoind_RPC(0,"dex",url,0,"listunspent",postdata,0)); } bits256 iguana_wif2privkey(char *wifstr) @@ -203,7 +204,7 @@ bits256 iguana_wif2privkey(char *wifstr) memset(privkey.bytes,0,sizeof(privkey)); sprintf(url,"%s/?",IGUANA_URL); sprintf(postdata,"{\"agent\":\"SuperNET\",\"method\":\"wif2priv\",\"wif\":\"%s\"}",wifstr); - if ( (retstr= bitcoind_RPC(0,"SuperNET",url,0,"wif2priv",postdata)) != 0 ) + if ( (retstr= bitcoind_RPC(0,"SuperNET",url,0,"wif2priv",postdata,0)) != 0 ) { if ( (retjson= cJSON_Parse(retstr)) != 0 ) { @@ -219,28 +220,6 @@ bits256 iguana_wif2privkey(char *wifstr) return(privkey); } -void iguana_priv2pub(uint8_t *pubkey33,char *coinaddr,bits256 privkey,uint8_t addrtype) -{ - char privstr[65],url[512],postdata[1024],*retstr,*pubstr,*addr; cJSON *retjson; - memset(pubkey33,0,33); - coinaddr[0] = 0; - bits256_str(privstr,privkey); - sprintf(url,"%s/?",IGUANA_URL); - sprintf(postdata,"{\"agent\":\"SuperNET\",\"method\":\"priv2pub\",\"privkey\":\"%s\",\"addrtype\":%u}",privstr,addrtype); - if ( (retstr= bitcoind_RPC(0,"SuperNET",url,0,"priv2pub",postdata)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( (pubstr= jstr(retjson,"secp256k1")) != 0 && strlen(pubstr) == 66 ) - decode_hex(pubkey33,33,pubstr); - if ( (addr= jstr(retjson,"result")) != 0 && strlen(addr) < 64 ) - strcpy(coinaddr,addr); - free_json(retjson); - } - free(retstr); - } -} - double bittrex_balance(char *base,char *coinaddr) { char *retstr; cJSON *retjson; double balance = 0.; @@ -623,7 +602,7 @@ int32_t marketmaker_spread(char *exchange,char *base,char *rel,double bid,double sprintf(url,"%s/?",IGUANA_URL); sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"%s\",\"vals\":%s}",base,jprint(vals,1)); //printf("(%s)\n",postdata); - if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata)) != 0 ) + if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata,0)) != 0 ) { //printf("(%s) -> (%s)\n",postdata,retstr); free(retstr); @@ -643,7 +622,7 @@ int32_t marketmaker_spread(char *exchange,char *base,char *rel,double bid,double jaddnum(vals,"minvol",MAX(1,(int32_t)(vol * 0.01 * PAXPRICES[i]))); sprintf(url,"%s/?",IGUANA_URL); sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"%s\",\"vals\":%s}","KMD",jprint(vals,1)); - if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata)) != 0 ) + if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata,0)) != 0 ) { //printf("(%s) -> (%s)\n",postdata,retstr); free(retstr); @@ -811,15 +790,15 @@ void LP_main(void *ptr) if ( (passphrase= jstr(argjson,"passphrase")) != 0 ) { profitmargin = jdouble(argjson,"profitmargin"); - LPinit(7779,7780,7781,profitmargin,passphrase,jint(argjson,"client"),jstr(argjson,"userhome")); + LPinit(7779,7780,7781,profitmargin,passphrase,jint(argjson,"client"),jstr(argjson,"userhome"),argjson); } } int main(int argc, const char * argv[]) { char *base,*rel,*name,*exchange,*apikey,*apisecret,*blocktrail,*retstr,*baseaddr,*reladdr,*passphrase; - double profitmargin,maxexposure,incrratio,start_rel,start_base,minask,maxbid,incr,theoretical = 0.; - cJSON *retjson,*loginjson,*matchjson; int32_t i; + double profitmargin,maxexposure,incrratio,start_rel,start_base,minask,maxbid,incr; + cJSON *retjson,*loginjson; int32_t i; if ( argc > 1 && (retjson= cJSON_Parse(argv[1])) != 0 ) { if ( (passphrase= jstr(retjson,"passphrase")) == 0 ) @@ -829,29 +808,7 @@ int main(int argc, const char * argv[]) printf("error launching LP_main (%s)\n",jprint(retjson,0)); exit(-1); } else printf("(%s) launched.(%s)\n",argv[1],passphrase); - if ( (0) && (retstr= basilisk_swaplist()) != 0 ) - { - printf("%s\ngetchar to continue\n",retstr); - getchar(); - free(retstr); - } incr = 100.; - while ( (0) && IAMCLIENT != 0 ) - { - theoretical = marketmaker_updateprice("komodo","REVS","KMD",theoretical,&incr); - sleep(3); - LP_privkey_updates(0,-1,passphrase,1); - if ( jint(retjson,"client") != 0 ) - { - struct LP_utxoinfo *utxo,*utmp; - HASH_ITER(hh,LP_utxoinfos,utxo,utmp) - { - if ( strcmp(utxo->coin,"REVS") == 0 && (matchjson= LP_autotrade(utxo,"KMD",0.)) != 0 ) - printf("bestprice (%s)\n",jprint(matchjson,1)); - } - } - sleep(1000); - } while ( 1 ) sleep(1); profitmargin = jdouble(retjson,"profitmargin"); diff --git a/iguana/exchanges/myprices b/iguana/exchanges/myprices new file mode 100755 index 000000000..7333d682b --- /dev/null +++ b/iguana/exchanges/myprices @@ -0,0 +1,2 @@ +source userpass +curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"myprices\"}" diff --git a/iguana/exchanges/nxtae.c b/iguana/exchanges/nxtae.c index 03e2c1eee..d6fe1080c 100755 --- a/iguana/exchanges/nxtae.c +++ b/iguana/exchanges/nxtae.c @@ -14,7 +14,7 @@ ******************************************************************************/ #define DEFAULT_NXT_DEADLINE 720 -#define issue_NXTPOST(cmdstr) bitcoind_RPC(0,"curl",myinfo->NXTAPIURL,0,0,cmdstr) +#define issue_NXTPOST(cmdstr) bitcoind_RPC(0,"curl",myinfo->NXTAPIURL,0,0,cmdstr,0) #define NXT_MSTYPE 5 #define NXT_ASSETTYPE 2 #define NXT_GENESISTIME 1385294400 diff --git a/iguana/exchanges/orderbook b/iguana/exchanges/orderbook index 4d2367a42..a2110f07b 100755 --- a/iguana/exchanges/orderbook +++ b/iguana/exchanges/orderbook @@ -1,2 +1,2 @@ source userpass -curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"orderbook\",\"base\":\"REVS\",\"rel\":\"KMD\"}" +curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"orderbook\",\"base\":\"KMD\",\"rel\":\"BTC\"}" diff --git a/iguana/exchanges/pub b/iguana/exchanges/pub new file mode 100755 index 000000000..edafc5b98 --- /dev/null +++ b/iguana/exchanges/pub @@ -0,0 +1,2 @@ +source userpass +curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"6578099f6474d9b8bd66a7a136b922029a989818ec0309aee962dd6ac1862b74\",\"method\":\"forward\",\"method2\":\"publish\",\"data\":\"nonsense\"}" diff --git a/iguana/exchanges/registerall b/iguana/exchanges/registerall new file mode 100755 index 000000000..9024b8230 --- /dev/null +++ b/iguana/exchanges/registerall @@ -0,0 +1,3 @@ + +source userpass +curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"registerall\",\"numnodes\":10}" diff --git a/iguana/exchanges/run b/iguana/exchanges/run index ccc62231a..a81c74556 100755 --- a/iguana/exchanges/run +++ b/iguana/exchanges/run @@ -1,2 +1,19 @@ source randval -pkill -15 marketmaker; git pull; cd ..; ./m_mm; ./marketmaker "{\"profitmargin\":0.01,\"passphrase\":\"$randval\"}" & +pkill -15 marketmaker; git pull; cd ..; ./m_mm; $1 ./marketmaker "{\"gui\":\"nogui\",\"profitmargin\":0.01,\"passphrase\":\"$randval\",\"coins\":[{\"coin\":\"REVS\",\"active\":1, \"asset\":\"REVS\",\"rpcport\":10196},{\"coin\":\"JUMBLR\",\"active\":1, \"asset\":\"JUMBLR\",\"rpcport\":15106}, +{\"coin\":\"DOGE\", \"name\":\"dogecoin\", \"pubtype\":30, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000000}, +{\"coin\":\"HUSH\",\"name\":\"hush\",\"rpcport\":8822,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000 }, +{\"active\":0,\"coin\":\"ZEC\",\"name\":\"zcash\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000 }, +{\"coin\":\"DGB\", \"name\":\"digibyte\", \"pubtype\":30, \"p2shtype\":5, \"wiftype\":128, \"txfee\":10000}, +{\"coin\":\"MZC\", \"name\":\"mazacoin\", \"pubtype\":50, \"p2shtype\":9, \"wiftype\":224, \"txfee\":0}, +{\"coin\":\"SYS\", \"name\":\"syscoin\", \"pubtype\":0, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000}, +{\"coin\":\"UNO\", \"name\":\"unobtanium\", \"pubtype\":130, \"p2shtype\":30, \"wiftype\":224, \"txfee\":1000000}, +{\"coin\":\"ZET\", \"name\":\"zetacoin\", \"pubtype\":80, \"p2shtype\":9, \"wiftype\":224, \"txfee\":10000}, +{\"coin\":\"ZEC\", \"name\":\"zcash\", \"pubtype\":184, \"p2shtype\":189, \"wiftype\":128, \"txfee\":10000}, +{\"coin\":\"BTM\", \"name\":\"bitmark\", \"pubtype\":85, \"p2shtype\":5, \"wiftype\":213, \"txfee\":0}, +{\"coin\":\"CARB\", \"name\":\"carboncoin\", \"pubtype\":47, \"p2shtype\":5, \"wiftype\":175, \"txfee\":0}, +{\"coin\":\"ANC\", \"name\":\"anoncoin\", \"pubtype\":23, \"p2shtype\":5, \"wiftype\":151, \"txfee\":2000000}, +{\"coin\":\"FRK\", \"name\":\"franko\", \"pubtype\":35, \"p2shtype\":5, \"wiftype\":163, \"txfee\":0}, +{\"coin\":\"GAME\", \"name\":\"gamecredits\", \"pubtype\":38, \"p2shtype\":5, \"wiftype\":166, \"txfee\":100000}, +{\"coin\":\"LTC\", \"name\":\"litecoin\", \"rpcport\":9332, \"pubtype\":48, \"p2shtype\":5, \"wiftype\":176, \"txfee\":100000 }, +{\"coin\":\"SUPERNET\",\"asset\":\"SUPERNET\",\"rpcport\":11341},{\"coin\":\"WLC\",\"asset\":\"WLC\",\"rpcport\":12167},{\"coin\":\"PANGEA\",\"asset\":\"PANGEA\",\"rpcport\":14068},{\"coin\":\"DEX\",\"asset\":\"DEX\",\"rpcport\":11890},{\"coin\":\"BET\",\"asset\":\"BET\",\"rpcport\":14250},{\"coin\":\"CRYPTO\",\"asset\":\"CRYPTO\",\"rpcport\":8516},{\"coin\":\"HODL\",\"asset\":\"HODL\",\"rpcport\":14431},{\"coin\":\"SHARK\",\"asset\":\"SHARK\",\"rpcport\":10114},{\"coin\":\"BOTS\",\"asset\":\"BOTS\",\"rpcport\":11964},{\"coin\":\"MGW\",\"asset\":\"MGW\",\"rpcport\":12386},{\"coin\":\"COQUI\",\"asset\":\"COQUI\",\"rpcport\":12456},{\"coin\":\"KV\",\"asset\":\"KV\",\"rpcport\":9747},{\"coin\":\"CEAL\",\"asset\":\"CEAL\",\"rpcport\":11116},{\"coin\":\"MESH\",\"asset\":\"MESH\",\"rpcport\":9455} +]}" & diff --git a/iguana/exchanges/run_osx b/iguana/exchanges/run_osx new file mode 100755 index 000000000..e39934a75 --- /dev/null +++ b/iguana/exchanges/run_osx @@ -0,0 +1,17 @@ +source randval +pkill -15 marketmaker; git pull; cd ..; ./m_mm; ./marketmaker "{\"profitmargin\":0.01,\"userhome\":\"/${HOME#"/"}/Library/Application\ Support\",\"passphrase\":\"$randval\",\"coins\":[{\"coin\":\"REVS\",\"active\":1, \"asset\":\"REVS\",\"rpcport\":10196},{\"coin\":\"JUMBLR\",\"active\":1, \"asset\":\"JUMBLR\",\"rpcport\":15106}, +{\"coin\":\"DOGE\", \"name\":\"dogecoin\", \"pubtype\":30, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000000}, +{\"coin\":\"DGB\", \"name\":\"digibyte\", \"pubtype\":30, \"p2shtype\":5, \"wiftype\":128, \"txfee\":10000}, +{\"coin\":\"MZC\", \"name\":\"mazacoin\", \"pubtype\":50, \"p2shtype\":9, \"wiftype\":224, \"txfee\":0}, +{\"coin\":\"SYS\", \"name\":\"syscoin\", \"pubtype\":0, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000}, +{\"coin\":\"UNO\", \"name\":\"unobtanium\", \"pubtype\":130, \"p2shtype\":30, \"wiftype\":224, \"txfee\":1000000}, +{\"coin\":\"ZET\", \"name\":\"zetacoin\", \"pubtype\":80, \"p2shtype\":9, \"wiftype\":224, \"txfee\":10000}, +{\"coin\":\"ZEC\", \"name\":\"zcash\", \"pubtype\":184, \"p2shtype\":189, \"wiftype\":128, \"txfee\":10000}, +{\"coin\":\"BTM\", \"name\":\"bitmark\", \"pubtype\":85, \"p2shtype\":5, \"wiftype\":213, \"txfee\":0}, +{\"coin\":\"CARB\", \"name\":\"carboncoin\", \"pubtype\":47, \"p2shtype\":5, \"wiftype\":175, \"txfee\":0}, +{\"coin\":\"ANC\", \"name\":\"anoncoin\", \"pubtype\":23, \"p2shtype\":5, \"wiftype\":151, \"txfee\":2000000}, +{\"coin\":\"FRK\", \"name\":\"franko\", \"pubtype\":35, \"p2shtype\":5, \"wiftype\":163, \"txfee\":0}, +{\"coin\":\"GAME\", \"name\":\"gamecredits\", \"pubtype\":38, \"p2shtype\":5, \"wiftype\":166, \"txfee\":100000}, +{\"coin\":\"LTC\", \"name\":\"litecoin\", \"rpcport\":9332, \"pubtype\":48, \"p2shtype\":5, \"wiftype\":176, \"txfee\":100000 }, +{\"coin\":\"SUPERNET\",\"asset\":\"SUPERNET\",\"rpcport\":11341},{\"coin\":\"WLC\",\"asset\":\"WLC\",\"rpcport\":12167},{\"coin\":\"PANGEA\",\"asset\":\"PANGEA\",\"rpcport\":14068},{\"coin\":\"DEX\",\"asset\":\"DEX\",\"rpcport\":11890},{\"coin\":\"BET\",\"asset\":\"BET\",\"rpcport\":14250},{\"coin\":\"CRYPTO\",\"asset\":\"CRYPTO\",\"rpcport\":8516},{\"coin\":\"HODL\",\"asset\":\"HODL\",\"rpcport\":14431},{\"coin\":\"SHARK\",\"asset\":\"SHARK\",\"rpcport\":10114},{\"coin\":\"BOTS\",\"asset\":\"BOTS\",\"rpcport\":11964},{\"coin\":\"MGW\",\"asset\":\"MGW\",\"rpcport\":12386},{\"coin\":\"MVP\",\"asset\":\"MVP\",\"rpcport\":8655},{\"coin\":\"KV\",\"asset\":\"KV\",\"rpcport\":9747},{\"coin\":\"CEAL\",\"asset\":\"CEAL\",\"rpcport\":11116},{\"coin\":\"MESH\",\"asset\":\"MESH\",\"rpcport\":9455} +]}" & diff --git a/iguana/exchanges/stats.c b/iguana/exchanges/stats.c index 8af29db0e..64e4f985e 100644 --- a/iguana/exchanges/stats.c +++ b/iguana/exchanges/stats.c @@ -302,11 +302,15 @@ cJSON *SuperNET_urlconv(char *value,int32_t bufsize,char *urlstr) return(json); } +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) { - cJSON *tokens,*argjson,*origargjson,*tmpjson=0,*json = 0; long filesize; - char symbol[64],buf[4096],*userpass=0,urlmethod[16],*data,url[8192],furl[8192],*retstr,*filestr,*token = 0; int32_t i,j,n,num=0; + static void *ctx; + cJSON *tokens,*argjson,*origargjson,*tmpjson=0,*json = 0; long filesize; double profitmargin = 0.; 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); + if ( ctx == 0 ) + ctx = bitcoin_ctx(); for (i=0; i