Browse Source

Merge pull request #343 from jl777/dev

Dev
beta
jl777 8 years ago
committed by GitHub
parent
commit
6c1468aec4
  1. 6
      .gitignore
  2. 1
      basilisk/basilisk_tradebot.c
  3. 56
      basilisk/jumblr.c
  4. 3
      crypto777/OS_portable.h
  5. 7
      crypto777/bitcoind_RPC.c
  6. 2
      crypto777/nanosrc/aio/worker_posix.c
  7. 46
      crypto777/nanosrc/core/global.c
  8. 4
      crypto777/nanosrc/utils/efd_pipe.c
  9. 2
      iguana/coins/basilisk/coqui
  10. 1
      iguana/coins/coqui_7776
  11. 2
      iguana/coins/genltc
  12. 2
      iguana/coins/revs
  13. 4
      iguana/dpow/dpow_rpc.c
  14. 2
      iguana/exchanges/DEXstats.h
  15. 172
      iguana/exchanges/LP_bitcoin.c
  16. 209
      iguana/exchanges/LP_coins.c
  17. 745
      iguana/exchanges/LP_commands.c
  18. 349
      iguana/exchanges/LP_forwarding.c
  19. 119
      iguana/exchanges/LP_include.h
  20. 496
      iguana/exchanges/LP_nativeDEX.c
  21. 396
      iguana/exchanges/LP_network.c
  22. 690
      iguana/exchanges/LP_ordermatch.c
  23. 55
      iguana/exchanges/LP_peers.c
  24. 490
      iguana/exchanges/LP_prices.c
  25. 97
      iguana/exchanges/LP_remember.c
  26. 226
      iguana/exchanges/LP_rpc.c
  27. 180
      iguana/exchanges/LP_statemachine.c
  28. 354
      iguana/exchanges/LP_swap.c
  29. 583
      iguana/exchanges/LP_transaction.c
  30. 694
      iguana/exchanges/LP_utxos.c
  31. 2
      iguana/exchanges/autotrade
  32. 2
      iguana/exchanges/bitcoin.c
  33. 24
      iguana/exchanges/client
  34. 22
      iguana/exchanges/client_osx
  35. 2
      iguana/exchanges/disable
  36. 2
      iguana/exchanges/enable
  37. 2
      iguana/exchanges/forward
  38. 2
      iguana/exchanges/getcoins
  39. 2
      iguana/exchanges/getprices
  40. 2
      iguana/exchanges/getutxos
  41. 2
      iguana/exchanges/help
  42. 2
      iguana/exchanges/inv
  43. 2
      iguana/exchanges/lookup
  44. 7
      iguana/exchanges/loop
  45. 89
      iguana/exchanges/mm.c
  46. 2
      iguana/exchanges/myprices
  47. 2
      iguana/exchanges/nxtae.c
  48. 2
      iguana/exchanges/orderbook
  49. 2
      iguana/exchanges/pub
  50. 3
      iguana/exchanges/registerall
  51. 19
      iguana/exchanges/run
  52. 17
      iguana/exchanges/run_osx
  53. 12
      iguana/exchanges/stats.c
  54. 2
      iguana/exchanges/status
  55. 2
      iguana/exchanges/swapstatus
  56. 2
      iguana/exchanges/utxos
  57. 2
      iguana/iguana_notary.c
  58. 3
      iguana/m_notary
  59. 2
      iguana/tests/dexlistunspent
  60. 2
      includes/cJSON.h

6
.gitignore

@ -465,3 +465,9 @@ iguana/DB/SWAPS/3085356347-2346291696
iguana/DB/SWAPS/1819165332-1507632737 iguana/DB/SWAPS/1819165332-1507632737
iguana/DB/SWAPS/283982730-556239841 iguana/DB/SWAPS/283982730-556239841
iguana/marketmaker.dSYM/Contents/Info.plist
iguana/client
iguana/marketmaker.dSYM/Contents/Resources/DWARF/marketmaker

1
basilisk/basilisk_tradebot.c

@ -316,7 +316,6 @@ double basilisk_request_listprocess(struct supernet_info *myinfo,struct basilisk
} }
} else noquoteflag++; } 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; struct iguana_info *coin; char coinaddr[64]; double retvals[4],refprice=0.,profitmargin,aveprice,destvolume;
destvolume = dstr(maxamount); destvolume = dstr(maxamount);
//printf("destvolume <- %.8f\n",dstr(destvolume)); //printf("destvolume <- %.8f\n",dstr(destvolume));

56
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) void jumblr_iteration(struct supernet_info *myinfo,struct iguana_info *coin,int32_t selector,int32_t modval)
{ {
//static uint32_t lasttime; //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 ) if ( myinfo->IAMNOTARY != 0 )
return; return;
fee = JUMBLR_INCR * JUMBLR_FEE; fee = JUMBLR_INCR * JUMBLR_FEE;
OS_randombytes(&r,sizeof(r)); OS_randombytes(&r,sizeof(r));
//r = 0; //r = 0;
// randomize size chosen and order of chunks
if ( strcmp(coin->symbol,"KMD") == 0 && coin->FULLNODE < 0 ) 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); //printf("JUMBLR selector.%d modval.%d r.%d\n",selector,modval,r&7);
switch ( selector ) switch ( s )
{ {
case 0: // public -> z, need to importprivkey case 0: // public -> z, need to importprivkey
jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,JUMBLR_DEPOSITPREFIX); 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 ) if ( (zaddr= jumblr_zgetnewaddress(myinfo,coin)) != 0 )
{ {
amount = 0;
if ( total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE) ) if ( total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE) )
amount = 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); amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE);
else amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE); if ( (r & 4) != 0 )
if ( (retstr= jumblr_sendt_to_z(myinfo,coin,KMDaddr,zaddr,dstr(amount))) != 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); printf("sendt_to_z.(%s)\n",retstr);
free(retstr); free(retstr);
@ -678,17 +682,23 @@ void jumblr_iteration(struct supernet_info *myinfo,struct iguana_info *coin,int3
break; break;
case 1: // z -> z case 1: // z -> z
jumblr_opidsupdate(myinfo,coin); jumblr_opidsupdate(myinfo,coin);
chosen_one = -1;
for (iter=counter=0; iter<2; iter++)
{
counter = n = 0;
HASH_ITER(hh,myinfo->jumblrs,ptr,tmp) HASH_ITER(hh,myinfo->jumblrs,ptr,tmp)
{ {
if ( jumblr_addresstype(myinfo,coin,ptr->src) == 't' && jumblr_addresstype(myinfo,coin,ptr->dest) == 'z' ) if ( jumblr_addresstype(myinfo,coin,ptr->src) == 't' && jumblr_addresstype(myinfo,coin,ptr->dest) == 'z' )
{ {
if ( (r & 1) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) if ( (r & 1) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN )
{
if ( iter == 1 && counter == chosen_one )
{ {
if ( (zaddr= jumblr_zgetnewaddress(myinfo,coin)) != 0 ) if ( (zaddr= jumblr_zgetnewaddress(myinfo,coin)) != 0 )
{ {
if ( (retstr= jumblr_sendz_to_z(myinfo,coin,ptr->dest,zaddr,dstr(total))) != 0 ) if ( (retstr= jumblr_sendz_to_z(myinfo,coin,ptr->dest,zaddr,dstr(total))) != 0 )
{ {
printf("sendz_to_z.(%s)\n",retstr); printf("n.%d counter.%d chosen_one.%d sendz_to_z.(%s)\n",n,counter,chosen_one,retstr);
free(retstr); free(retstr);
} }
ptr->spent = (uint32_t)time(NULL); ptr->spent = (uint32_t)time(NULL);
@ -696,6 +706,20 @@ void jumblr_iteration(struct supernet_info *myinfo,struct iguana_info *coin,int3
break; 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; break;
@ -703,11 +727,17 @@ void jumblr_iteration(struct supernet_info *myinfo,struct iguana_info *coin,int3
if ( myinfo->runsilent == 0 ) if ( myinfo->runsilent == 0 )
{ {
jumblr_opidsupdate(myinfo,coin); jumblr_opidsupdate(myinfo,coin);
chosen_one = -1;
for (iter=0; iter<2; iter++)
{
counter = n = 0;
HASH_ITER(hh,myinfo->jumblrs,ptr,tmp) HASH_ITER(hh,myinfo->jumblrs,ptr,tmp)
{ {
if ( jumblr_addresstype(myinfo,coin,ptr->src) == 'z' && jumblr_addresstype(myinfo,coin,ptr->dest) == 'z' ) if ( jumblr_addresstype(myinfo,coin,ptr->src) == 'z' && jumblr_addresstype(myinfo,coin,ptr->dest) == 'z' )
{ {
if ( (r & 1) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) if ( (r & 1) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN )
{
if ( iter == 1 && n == chosen_one )
{ {
privkey = jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,""); privkey = jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,"");
if ( (retstr= jumblr_sendz_to_t(myinfo,coin,ptr->dest,KMDaddr,dstr(total))) != 0 ) if ( (retstr= jumblr_sendz_to_t(myinfo,coin,ptr->dest,KMDaddr,dstr(total))) != 0 )
@ -718,6 +748,20 @@ void jumblr_iteration(struct supernet_info *myinfo,struct iguana_info *coin,int3
ptr->spent = (uint32_t)time(NULL); ptr->spent = (uint32_t)time(NULL);
break; 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->t chosen_one.%d of %d, from %d\n",chosen_one,counter,n);
} }
} }
} }

3
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 portable_mutex_unlock pthread_mutex_unlock
#define OS_thread_create pthread_create #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 allocitem { uint32_t allocsize,type; } PACKED;
struct queueitem { struct queueitem *next,*prev; uint32_t allocsize,type; } PACKED; struct queueitem { struct queueitem *next,*prev; uint32_t allocsize,type; } PACKED;

7
crypto777/bitcoind_RPC.c

@ -115,7 +115,7 @@ char *Jay_NXTrequest(char *command,char *params)
return(retstr); 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; 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; 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_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_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_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 ) if ( strncmp(url,"https",5) == 0 )
{ {
curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0); curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0);
@ -201,7 +202,7 @@ try_again:
if ( res != CURLE_OK ) if ( res != CURLE_OK )
{ {
numretries++; 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); printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res);
free(s.ptr); free(s.ptr);

2
crypto777/nanosrc/aio/worker_posix.c

@ -103,7 +103,7 @@ int nn_worker_init(struct nn_worker *self)
{ {
int32_t rc; int32_t rc;
PNACL_message("nn_worker_init %p\n",self); PNACL_message("nn_worker_init %p\n",self);
sleep(1); //sleep(1);
rc = nn_efd_init(&self->efd); rc = nn_efd_init(&self->efd);
PNACL_message("efd init: rc.%d\n",rc); PNACL_message("efd init: rc.%d\n",rc);
if ( rc < 0 ) if ( rc < 0 )

46
crypto777/nanosrc/core/global.c

@ -240,7 +240,7 @@ PNACL_message("list init\n");
// Initialise other parts of the global state. // Initialise other parts of the global state.
nn_list_init(&SELF.transports); nn_list_init(&SELF.transports);
nn_list_init(&SELF.socktypes); nn_list_init(&SELF.socktypes);
sleep(1); //sleep(1);
PNACL_message("transports init\n"); PNACL_message("transports init\n");
// Plug in individual transports. // Plug in individual transports.
//nn_global_add_transport(nn_ipc); //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_inproc);
//nn_global_add_transport(nn_ws); //nn_global_add_transport(nn_ws);
//nn_global_add_transport(nn_tcpmux); //nn_global_add_transport(nn_tcpmux);
sleep(1); //sleep(1);
PNACL_message("socktypes init\n"); PNACL_message("socktypes init\n");
// Plug in individual socktypes // Plug in individual socktypes
nn_global_add_socktype(nn_pair_socktype); nn_global_add_socktype(nn_pair_socktype);
sleep(1); //sleep(1);
PNACL_message("nn_xpair_socktype init\n"); PNACL_message("nn_xpair_socktype init\n");
nn_global_add_socktype(nn_xpair_socktype); nn_global_add_socktype(nn_xpair_socktype);
PNACL_message("did nn_xpair_socktype init\n"); PNACL_message("did nn_xpair_socktype init\n");
//nn_global_add_socktype(nn_rep_socktype); nn_global_add_socktype(nn_rep_socktype);
//nn_global_add_socktype(nn_req_socktype); nn_global_add_socktype(nn_req_socktype);
//nn_global_add_socktype(nn_xrep_socktype); nn_global_add_socktype(nn_xrep_socktype);
//nn_global_add_socktype(nn_xreq_socktype); nn_global_add_socktype(nn_xreq_socktype);
//nn_global_add_socktype(nn_respondent_socktype); nn_global_add_socktype(nn_respondent_socktype);
//nn_global_add_socktype(nn_surveyor_socktype); nn_global_add_socktype(nn_surveyor_socktype);
//nn_global_add_socktype(nn_xrespondent_socktype); nn_global_add_socktype(nn_xrespondent_socktype);
//nn_global_add_socktype(nn_xsurveyor_socktype); nn_global_add_socktype(nn_xsurveyor_socktype);
//nn_global_add_socktype(nn_pub_socktype); nn_global_add_socktype(nn_pub_socktype);
//nn_global_add_socktype(nn_sub_socktype); nn_global_add_socktype(nn_sub_socktype);
//nn_global_add_socktype(nn_xpub_socktype); nn_global_add_socktype(nn_xpub_socktype);
//nn_global_add_socktype(nn_xsub_socktype); nn_global_add_socktype(nn_xsub_socktype);
//nn_global_add_socktype(nn_push_socktype); nn_global_add_socktype(nn_push_socktype);
//nn_global_add_socktype(nn_xpush_socktype); nn_global_add_socktype(nn_xpush_socktype);
//nn_global_add_socktype(nn_pull_socktype); nn_global_add_socktype(nn_pull_socktype);
//nn_global_add_socktype(nn_xpull_socktype); nn_global_add_socktype(nn_xpull_socktype);
//nn_global_add_socktype(nn_bus_socktype); nn_global_add_socktype(nn_bus_socktype);
//nn_global_add_socktype(nn_xbus_socktype); nn_global_add_socktype(nn_xbus_socktype);
sleep(1); //sleep(1);
PNACL_message("do pool init\n"); PNACL_message("do pool init\n");
nn_pool_init(&SELF.pool); // Start the worker threads nn_pool_init(&SELF.pool); // Start the worker threads
sleep(1); //sleep(1);
PNACL_message("do FSM init\n"); PNACL_message("do FSM init\n");
nn_fsm_init_root(&SELF.fsm,nn_global_handler,nn_global_shutdown,&SELF.ctx); // Start FSM nn_fsm_init_root(&SELF.fsm,nn_global_handler,nn_global_shutdown,&SELF.ctx); // Start FSM
SELF.state = NN_GLOBAL_STATE_IDLE; SELF.state = NN_GLOBAL_STATE_IDLE;

4
crypto777/nanosrc/utils/efd_pipe.c

@ -34,14 +34,14 @@ int nn_efd_init(struct nn_efd *self)
{ {
int rc,flags,p[2]; int rc,flags,p[2];
PNACL_message("inside efd_init: pipe\n"); PNACL_message("inside efd_init: pipe\n");
sleep(1); //sleep(1);
#if defined NN_HAVE_PIPE2 #if defined NN_HAVE_PIPE2
rc = pipe2(p, O_NONBLOCK | O_CLOEXEC); rc = pipe2(p, O_NONBLOCK | O_CLOEXEC);
#else #else
rc = pipe(p); rc = pipe(p);
#endif #endif
PNACL_message("rc efd_init: %d\n",rc); PNACL_message("rc efd_init: %d\n",rc);
sleep(1); //sleep(1);
if (rc != 0 && (errno == EMFILE || errno == ENFILE)) if (rc != 0 && (errno == EMFILE || errno == ENFILE))
return -EMFILE; return -EMFILE;
errno_assert (rc == 0); errno_assert (rc == 0);

2
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\"}"

1
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\"}"

2
iguana/coins/genltc

@ -1,4 +1,4 @@
#!/bin/bash #!/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}"

2
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\"}" 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\"}"

4
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) 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(url,(char *)"http://127.0.0.1:%u",port);
sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params); sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params);
//printf("postdata.(%s) USERPASS.(%s)\n",postdata,KMDUSERPASS); //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); return(retstr2);
} }

2
iguana/exchanges/DEXstats.h

@ -927,7 +927,7 @@ char *stats_prices(char *symbol,char *dest,struct DEXstats_disp *prices,int32_t
} }
#ifndef FROM_MARKETMAKER #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; 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 ) if ( (method= jstr(argjson,"method")) == 0 )

172
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) 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); memset(rmd160,0,20);
*addrtypep = 0; *addrtypep = 0;
buf = _buf; buf = _buf;
if ( (len= bitcoin_base58decode(buf,coinaddr)) >= 4 ) if ( (len= bitcoin_base58decode(buf,coinaddr)) >= 4 )
{ {
// validate with trailing hash, then remove hash // validate with trailing hash, then remove hash
hash = bits256_doublesha256(0,buf,21); hash = bits256_doublesha256(0,buf,20+offset);
*addrtypep = *buf; *addrtypep = (taddr == 0) ? *buf : buf[1];
memcpy(rmd160,buf+1,20); memcpy(rmd160,buf+offset,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] ) 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); //printf("coinaddr.(%s) valid checksum addrtype.%02x\n",coinaddr,*addrtypep);
return(20); return(20);
@ -2054,61 +2055,94 @@ int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr
} }
for (i=0; i<len; i++) for (i=0; i<len; i++)
printf("%02x ",buf[i]); printf("%02x ",buf[i]);
char str[65]; printf("\nhex checkhash.(%s) len.%d mismatch %02x %02x %02x %02x vs %02x %02x %02x %02x (%s)\n",coinaddr,len,buf[len-1]&0xff,buf[len-2]&0xff,buf[len-3]&0xff,buf[len-4]&0xff,hash.bytes[31],hash.bytes[30],hash.bytes[29],hash.bytes[28],bits256_str(str,hash)); char str[65]; printf("\ntaddr.%02x checkhash.(%s) len.%d mismatch %02x %02x %02x %02x vs %02x %02x %02x %02x (%s)\n",taddr,coinaddr,len,buf[len-1]&0xff,buf[len-2]&0xff,buf[len-3]&0xff,buf[len-4]&0xff,hash.bytes[31],hash.bytes[30],hash.bytes[29],hash.bytes[28],bits256_str(str,hash));
} }
} }
return(0); return(0);
} }
char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len) char *bitcoin_address(char *coinaddr,uint8_t taddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len)
{ {
int32_t i; uint8_t data[25]; bits256 hash;// char checkaddr[65]; int32_t offset,i; uint8_t data[26]; bits256 hash;// char checkaddr[65];
offset = 1 + (taddr != 0);
if ( len != 20 ) if ( len != 20 )
calc_rmd160_sha256(data+1,pubkey_or_rmd160,len); calc_rmd160_sha256(data+offset,pubkey_or_rmd160,len);
else memcpy(data+1,pubkey_or_rmd160,20); else memcpy(data+offset,pubkey_or_rmd160,20);
//btc_convrmd160(checkaddr,addrtype,data+1); //btc_convrmd160(checkaddr,addrtype,data+1);
data[0] = addrtype; if ( taddr != 0 )
hash = bits256_doublesha256(0,data,21); {
data[0] = taddr;
data[1] = addrtype;
} else data[0] = addrtype;
hash = bits256_doublesha256(0,data,20+offset);
for (i=0; i<4; i++) for (i=0; i<4; i++)
data[21+i] = hash.bytes[31-i]; data[20+offset+i] = hash.bytes[31-i];
if ( (coinaddr= bitcoin_base58encode(coinaddr,data,25)) != 0 ) if ( (coinaddr= bitcoin_base58encode(coinaddr,data,24+offset)) != 0 )
{ {
//uint8_t checktype,rmd160[20]; } else printf("null coinaddr taddr.%02x\n",taddr);
//bitcoin_addr2rmd160(&checktype,rmd160,coinaddr);
//if ( strcmp(checkaddr,coinaddr) != 0 )
// printf("checkaddr.(%s) vs coinaddr.(%s) %02x vs [%02x] memcmp.%d\n",checkaddr,coinaddr,addrtype,checktype,memcmp(rmd160,data+1,20));
}
return(coinaddr); return(coinaddr);
} }
int32_t bitcoin_validaddress(uint8_t pubtype,uint8_t p2shtype,char *coinaddr) void iguana_priv2pub(void *ctx,uint8_t *pubkey33,char *coinaddr,bits256 privkey,uint8_t taddr,uint8_t addrtype)
{
bits256 pub; //char privstr[65],url[512],postdata[1024],*retstr,*pubstr,*addr; cJSON *retjson;
memset(pubkey33,0,33);
coinaddr[0] = 0;
crypto_box_priv2pub(pub.bytes,privkey.bytes);
//jaddbits256(retjson,"curve25519",pub);
bitcoin_pubkey33(ctx,pubkey33,privkey);
bitcoin_address(coinaddr,taddr,addrtype,pubkey33,33);
/*bits256_str(privstr,privkey);
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"SuperNET\",\"method\":\"priv2pub\",\"privkey\":\"%s\",\"addrtype\":%u,\"taddr\":%u}",privstr,addrtype,taddr);
if ( (retstr= bitcoind_RPC(0,"SuperNET",url,0,"priv2pub",postdata,0)) != 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);
}*/
}
int32_t bitcoin_validaddress(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,char *coinaddr)
{ {
uint8_t rmd160[20],addrtype; char checkaddr[128]; uint8_t rmd160[20],addrtype; char checkaddr[128];
if ( coinaddr == 0 || coinaddr[0] == 0 ) if ( coinaddr == 0 || coinaddr[0] == 0 )
return(-1); return(-1);
else if ( bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr) < 0 ) else if ( bitcoin_addr2rmd160(taddr,&addrtype,rmd160,coinaddr) < 0 )
return(-1); return(-1);
else if ( addrtype != pubtype && addrtype != p2shtype ) else if ( addrtype != pubtype && addrtype != p2shtype )
return(-1); return(-1);
else if ( bitcoin_address(checkaddr,addrtype,rmd160,sizeof(rmd160)) != checkaddr || strcmp(checkaddr,coinaddr) != 0 ) else if ( bitcoin_address(checkaddr,addrtype,taddr,rmd160,sizeof(rmd160)) != checkaddr || strcmp(checkaddr,coinaddr) != 0 )
return(-1); return(-1);
return(0); return(0);
} }
int32_t base58encode_checkbuf(uint8_t addrtype,uint8_t *data,int32_t data_len) int32_t base58encode_checkbuf(uint8_t taddr,uint8_t addrtype,uint8_t *data,int32_t data_len)
{
uint8_t i,offset; bits256 hash;
offset = 1 + (taddr != 0);
if ( taddr != 0 )
{ {
uint8_t i; bits256 hash; data[0] = taddr;
data[0] = addrtype; data[1] = addrtype;
} else data[0] = addrtype;
//for (i=0; i<data_len+1; i++) //for (i=0; i<data_len+1; i++)
// printf("%02x",data[i]); // printf("%02x",data[i]);
//printf(" extpriv -> "); //printf(" extpriv -> ");
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++) //for (i=0; i<32; i++)
// printf("%02x",hash.bytes[i]); // printf("%02x",hash.bytes[i]);
//printf(" checkhash\n"); //printf(" checkhash\n");
for (i=0; i<4; i++) for (i=0; i<4; i++)
data[data_len+i+1] = hash.bytes[31-i]; data[data_len+i+offset] = hash.bytes[31-i];
return(data_len + 5); return(data_len + 4 + offset);
} }
int32_t bitcoin_wif2priv(uint8_t *addrtypep,bits256 *privkeyp,char *wifstr) 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; uint8_t data[128]; int32_t len = 32;
memcpy(data+1,privkey.bytes,sizeof(privkey)); memcpy(data+1,privkey.bytes,sizeof(privkey));
data[1 + len++] = 1; data[1 + len++] = 1;
len = base58encode_checkbuf(addrtype,data,len); len = base58encode_checkbuf(0,addrtype,data,len);
if ( bitcoin_base58encode(wifstr,data,len) == 0 ) if ( bitcoin_base58encode(wifstr,data,len) == 0 )
return(-1); return(-1);
if ( 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; uint8_t data[128]; int32_t len = 32;
memcpy(data+1,privkey.bytes,sizeof(privkey)); 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 ) if ( bitcoin_base58encode(wifstr,data,len) == 0 )
return(-1); return(-1);
if ( 1 ) if ( 1 )
@ -2180,10 +2214,10 @@ int32_t bitcoin_priv2wiflong(char *wifstr,bits256 privkey,uint8_t addrtype)
return((int32_t)strlen(wifstr)); 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]; bits256 privkey; uint8_t addrtype,rmd160[20];
bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr); bitcoin_addr2rmd160(taddr,&addrtype,rmd160,coinaddr);
privkey = LP_privkeyfind(rmd160); privkey = LP_privkeyfind(rmd160);
return(privkey); 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; uint8_t addrtype; char rmd160str[41],pubkeystr[256]; int32_t plen,i,m,n,flag = 0,scriptlen = 0;
m = n = 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 ) if ( type == IGUANA_SCRIPT_76A988AC || type == IGUANA_SCRIPT_AC || type == IGUANA_SCRIPT_76AC || type == IGUANA_SCRIPT_P2SH )
{ {
init_hexbytes_noT(rmd160str,rmd160,20); init_hexbytes_noT(rmd160str,rmd160,20);
bitcoin_address(coinaddr,addrtype,rmd160,20); bitcoin_address(coinaddr,taddr,addrtype,rmd160,20);
} }
switch ( type ) 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: case IGUANA_SCRIPT_OPRETURN:
if ( asmstr != 0 ) if ( asmstr != 0 )
strcpy(asmstr,"OP_RETURN "); 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++; flag++;
break; break;
case IGUANA_SCRIPT_3of3: m = 3, n = 3; 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: case IGUANA_SCRIPT_DATA:
if ( asmstr != 0 ) if ( asmstr != 0 )
strcpy(asmstr,"DATA ONLY"); 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++; flag++;
break; break;
case IGUANA_SCRIPT_STRANGE: case IGUANA_SCRIPT_STRANGE:
if ( asmstr != 0 ) if ( asmstr != 0 )
strcpy(asmstr,"STRANGE SCRIPT "); 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++; flag++;
break; break;
default: break;//printf("unexpected script type.%d\n",type); 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 ) if ( n > 0 )
{ {
scriptlen = bitcoin_MofNspendscript(rmd160,script,0,vp); scriptlen = bitcoin_MofNspendscript(rmd160,script,0,vp);
bitcoin_address(coinaddr,p2shtype,script,scriptlen); bitcoin_address(coinaddr,taddr,p2shtype,script,scriptlen);
if ( asmstr != 0 ) if ( asmstr != 0 )
{ {
sprintf(asmstr,"%d ",m); 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); 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; int32_t j,n,siglen,plen; uint8_t *p2shscript;
j = n = 0; 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"); decode_hex(vp->rmd160,20,"010966776006953d5567439e5e39f86a0d273bee");//3564a74f9ddb4372301c49154605573d7d1a88fe");
vp->type = IGUANA_SCRIPT_76A988AC; 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); //printf("type.%d asmstr.(%s) spendlen.%d\n",vp->type,asmstr,vp->spendlen);
return(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]; static uint8_t zero_rmd160[20];
char hexstr[8192]; uint8_t *script,type; int32_t i,n,m,plen; 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); memcpy(vp->signers[i].pubkey,script,plen);
calc_rmd160_sha256(vp->signers[i].rmd160,vp->signers[i].pubkey,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 ) 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); 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]; int32_t scriptlen; uint8_t script[IGUANA_MAXSCRIPTSIZE];
memset(vp,0,sizeof(*vp)); 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->spendlen = pk_scriptlen;
vp->vin.sequence = sequence; vp->vin.sequence = sequence;
memcpy(vp->spendscript,pk_script,pk_scriptlen); 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 ) if ( vp->M == 0 && vp->N == 0 )
{ {
vp->M = vp->N = 1; vp->M = vp->N = 1;
@ -2578,11 +2612,11 @@ cJSON *bitcoin_txscript(char *asmstr,char **vardata,int32_t numvars)
return(scriptjson); 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]; int32_t type,i,n,plen; struct vin_info V; cJSON *pubkeys; char pubkeystr[256];
pubkeys = cJSON_CreateArray(); 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 ) if ( (n= V.N) == 0 )
n = 1; n = 1;
@ -2634,7 +2668,7 @@ cJSON *iguana_pubkeysjson(uint8_t *pubkeyptrs[],int32_t numpubkeys)
return(pubkeysjson); 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; cJSON *item,*vins; char p2shscriptstr[IGUANA_MAXSCRIPTSIZE*2+1]; uint8_t *script,len=0;
vins = jduplicate(jobj(txobj,"vin")); 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; script = redeemscript, len = p2shlen;
} else script = 0; } else script = 0;
if ( script != 0 && numpubkeys == 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 ) else if ( pubkeys != 0 && numpubkeys > 0 )
jadd(item,"pubkeys",iguana_pubkeysjson(pubkeys,numpubkeys)); jadd(item,"pubkeys",iguana_pubkeysjson(pubkeys,numpubkeys));
jaddbits256(item,"txid",txid); jaddbits256(item,"txid",txid);
@ -2698,12 +2732,12 @@ cJSON *bitcoin_txoutput(cJSON *txobj,uint8_t *paymentscript,int32_t len,uint64_t
return(txobj); 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; 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); scriptlen = bitcoin_standardspend(outputscript,0,rmd160);
bitcoin_txoutput(txobj,outputscript,scriptlen,satoshis); bitcoin_txoutput(txobj,outputscript,scriptlen,satoshis);
return(0); return(0);
@ -3130,7 +3164,7 @@ int32_t iguana_parsevoutobj(uint8_t *serialized,int32_t maxsize,struct iguana_ms
return(len); 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 // 035f1321ed17d387e4433b2fa229c53616057964af065f98bfcae2233c5108055e OP_CHECKSIG
char scriptstr[IGUANA_MAXSCRIPTSIZE+1],asmstr[2*IGUANA_MAXSCRIPTSIZE+1]; int32_t i,m,n,scriptlen,asmtype; struct vin_info *vp; char scriptstr[IGUANA_MAXSCRIPTSIZE+1],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) ) if ( vout->pk_script != 0 && vout->pk_scriptlen*2+1 < sizeof(scriptstr) )
{ {
memset(vp,0,sizeof(*vp)); 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(); 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 ) if ( asmstr[0] != 0 )
jaddstr(skey,"asm",asmstr); jaddstr(skey,"asm",asmstr);
addrs = cJSON_CreateArray(); addrs = cJSON_CreateArray();
@ -3223,9 +3257,9 @@ int32_t iguana_vinarray_check(cJSON *vinarray,bits256 txid,int32_t vout)
return(-1); 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; int32_t i,len; bits256 sigtxid,txid,revsigtxid; struct iguana_msgtx dest;
dest = *msgtx; 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].userdata = 0;
dest.vins[i].userdatalen = 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; i<len; i++) //for (i=0; i<len; i++)
// printf("%02x",serialized[i]); // printf("%02x",serialized[i]);
//printf(" <- sigtx len.%d supp.%d user[0].%d\n",len,suppress_pubkeys,dest.vins[0].userdatalen); //printf(" <- sigtx len.%d supp.%d user[0].%d\n",len,suppress_pubkeys,dest.vins[0].userdatalen);
@ -3280,7 +3314,7 @@ bits256 bitcoin_sigtxid(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t h
return(sigtxid); return(sigtxid);
} }
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)
{ {
int32_t i,n,len = 0,extraused=0; uint8_t spendscript[IGUANA_MAXSCRIPTSIZE],*txstart = serialized,*sigser=0; char txidstr[65]; cJSON *vinarray=0,*voutarray=0; bits256 sigtxid; int32_t i,n,len = 0,extraused=0; uint8_t spendscript[IGUANA_MAXSCRIPTSIZE],*txstart = serialized,*sigser=0; char txidstr[65]; cJSON *vinarray=0,*voutarray=0; bits256 sigtxid;
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->version),&msg->version); len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->version),&msg->version);
@ -3366,7 +3400,7 @@ int32_t iguana_rwmsgtx(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t he
return(-1); return(-1);
} }
if ( voutarray != 0 ) 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); len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->lock_time),&msg->lock_time);
//printf("lock_time.%08x len.%d\n",msg->lock_time,len); //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 ) if ( vins != 0 && jitem(vins,i) != 0 )
{ {
iguana_vinobjset(&msg->vins[i],jitem(vins,i),spendscript,sizeof(spendscript)); 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)); //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 ) if ( iguana_vinarray_check(vinarray,msg->vins[i].prev_hash,msg->vins[i].prev_vout) < 0 )
jaddi(vinarray,iguana_vinjson(&msg->vins[i],sigtxid)); 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); 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; int32_t n; char *txbytes = 0,vpnstr[64]; uint8_t *serialized;
serialized = malloc(IGUANA_MAXPACKETSIZE); serialized = malloc(IGUANA_MAXPACKETSIZE);
vpnstr[0] = 0; vpnstr[0] = 0;
//char str[65]; printf("%d of %d: %s\n",i,msg.txn_count,bits256_str(str,tx.txid)); //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); txbytes = malloc(n*2+1);
init_hexbytes_noT(txbytes,serialized,n); 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); 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; int32_t n; char vpnstr[64]; struct iguana_msgtx M; cJSON *txobj;
if ( serialized == 0 ) 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)); memset(msgtx,0,sizeof(M));
vpnstr[0] = 0; vpnstr[0] = 0;
memset(txidp,0,sizeof(*txidp)); 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)); printf("errortxobj.(%s)\n",jprint(txobj,0));
free_json(txobj); free_json(txobj);
@ -3558,7 +3592,7 @@ cJSON *bitcoin_data2json(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t
return(txobj); 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; int32_t len; uint8_t *serialized; cJSON *txobj;
if ( txbytes == 0 ) 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 ) if ( (serialized= origserialized) == 0 )
serialized = calloc(1,len+4096); serialized = calloc(1,len+4096);
decode_hex(serialized,len,txbytes); 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 ) if ( serialized != origserialized )
free(serialized); free(serialized);
return(txobj); return(txobj);

209
iguana/exchanges/LP_coins.c

@ -18,7 +18,16 @@
// marketmaker // 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; i<sizeof(portstrs)/sizeof(*portstrs); i++)
if ( strcmp(portstrs[i][0],symbol) == 0 )
return(atoi(portstrs[i][1]));
return(0);
}
char *parse_conf_line(char *line,char *field) char *parse_conf_line(char *line,char *field)
{ {
@ -36,7 +45,7 @@ char *parse_conf_line(char *line,char *field)
return(clonestr(line)); return(clonestr(line));
} }
void LP_userpassfp(char *username,char *password,FILE *fp) void LP_userpassfp(char *symbol,char *username,char *password,FILE *fp)
{ {
char *rpcuser,*rpcpassword,*str,line[8192]; char *rpcuser,*rpcpassword,*str,line[8192];
rpcuser = rpcpassword = 0; rpcuser = rpcpassword = 0;
@ -56,14 +65,14 @@ void LP_userpassfp(char *username,char *password,FILE *fp)
strcpy(username,rpcuser); strcpy(username,rpcuser);
strcpy(password,rpcpassword); strcpy(password,rpcpassword);
} }
//printf("rpcuser.(%s) rpcpassword.(%s) KMDUSERPASS.(%s) %u\n",rpcuser,rpcpassword,KMDUSERPASS,port); //printf("%s rpcuser.(%s) rpcpassword.(%s)\n",symbol,rpcuser,rpcpassword);
if ( rpcuser != 0 ) if ( rpcuser != 0 )
free(rpcuser); free(rpcuser);
if ( rpcpassword != 0 ) if ( rpcpassword != 0 )
free(rpcpassword); free(rpcpassword);
} }
void LP_statefname(char *fname,char *symbol,char *assetname,char *str) void LP_statefname(char *fname,char *symbol,char *assetname,char *str,char *name)
{ {
sprintf(fname,"%s",LP_getdatadir()); sprintf(fname,"%s",LP_getdatadir());
#ifdef WIN32 #ifdef WIN32
@ -79,13 +88,21 @@ void LP_statefname(char *fname,char *symbol,char *assetname,char *str)
strcat(fname,".bitcoin"); strcat(fname,".bitcoin");
#endif #endif
} }
else if ( strcmp(symbol,"LTC") == 0 ) else if ( name != 0 )
{ {
char name2[64];
#ifdef __APPLE__ #ifdef __APPLE__
strcat(fname,"Litecoin"); int32_t len;
strcpy(name2,name);
name2[0] = toupper(name2[0]);
len = (int32_t)strlen(name2);
if ( strcmp(&name2[len-4],"coin") == 0 )
name2[len - 4] = 'C';
#else #else
strcat(fname,".litecoin"); name2[0] = '.';
strcpy(name2+1,name);
#endif #endif
strcat(fname,name2);
} }
else else
{ {
@ -110,80 +127,172 @@ void LP_statefname(char *fname,char *symbol,char *assetname,char *str)
strcat(fname,"/"); strcat(fname,"/");
#endif #endif
strcat(fname,str); strcat(fname,str);
printf("LP_statefname.(%s) <- %s %s %s\n",fname,symbol,assetname,str);
} }
int32_t LP_userpass(char *userpass,char *symbol,char *assetname,char *confroot) int32_t LP_userpass(char *userpass,char *symbol,char *assetname,char *confroot,char *name)
{ {
FILE *fp; char fname[512],username[512],password[512],confname[16]; FILE *fp; char fname[512],username[512],password[512],confname[16];
userpass[0] = 0; userpass[0] = 0;
sprintf(confname,"%s.conf",confroot); sprintf(confname,"%s.conf",confroot);
#ifdef __APPLE__ #ifdef __APPLE__
int32_t len;
confname[0] = toupper(confname[0]); confname[0] = toupper(confname[0]);
len = (int32_t)strlen(confname);
if ( strcmp(&confname[len-4],"coin") == 0 )
confname[len - 4] = 'C';
#endif #endif
LP_statefname(fname,symbol,assetname,confname); LP_statefname(fname,symbol,assetname,confname,name);
if ( (fp= fopen(fname,"rb")) != 0 ) if ( (fp= fopen(fname,"rb")) != 0 )
{ {
LP_userpassfp(username,password,fp); LP_userpassfp(symbol,username,password,fp);
sprintf(userpass,"%s:%s",username,password); sprintf(userpass,"%s:%s",username,password);
fclose(fp); fclose(fp);
if ( 0 && strcmp(symbol,"HUSH") == 0 )
printf("LP_statefname.(%s) <- %s %s %s (%s)\n",fname,name,symbol,assetname,userpass);
return((int32_t)strlen(userpass)); return((int32_t)strlen(userpass));
} } else printf("cant open.(%s)\n",fname);
return(-1); return(-1);
} }
uint16_t LP_rpcport(char *symbol) cJSON *LP_coinjson(struct iguana_info *coin)
{ {
int32_t i; cJSON *item = cJSON_CreateObject();
for (i=0; i<sizeof(portstrs)/sizeof(*portstrs); i++) jaddstr(item,"coin",coin->symbol);
if ( strcmp(portstrs[i][0],symbol) == 0 ) if ( coin->inactive != 0 )
return(atoi(portstrs[i][1])); jaddstr(item,"status","inactive");
return(0); 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; static struct iguana_info *LP_coins; static int32_t LP_numcoins;
struct iguana_info *coin,cdata; int32_t i; uint16_t port; cJSON *LP_coinsjson()
{
int32_t i; cJSON *array = cJSON_CreateArray();
for (i=0; i<LP_numcoins; i++)
jaddi(array,LP_coinjson(&LP_coins[i]));
return(array);
}
void LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *assetname,int32_t isPoS,uint16_t port,uint8_t pubtype,uint8_t p2shtype,uint8_t wiftype,uint64_t txfee,double estimatedrate,int32_t longestchain,uint8_t taddr)
{
char *name2;
memset(coin,0,sizeof(*coin));
safecopy(coin->symbol,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)
{
int32_t i;
for (i=0; i<LP_numcoins; i++) for (i=0; i<LP_numcoins; i++)
if ( strcmp(LP_coins[i].symbol,symbol) == 0 ) if ( strcmp(LP_coins[i].symbol,symbol) == 0 )
return(&LP_coins[i]); return(&LP_coins[i]);
memset(&cdata,0,sizeof(cdata)); return(0);
coin = &cdata;
safecopy(cdata.symbol,symbol,sizeof(cdata.symbol));
port = LP_rpcport(symbol);
sprintf(cdata.serverport,"127.0.0.1:%u",port);
cdata.longestchain = 100000;
cdata.txfee = 10000;
cdata.estimatedrate = 20;
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 )
int32_t LP_isdisabled(char *base,char *rel)
{ {
cdata.pubtype = 48; struct iguana_info *coin;
cdata.p2shtype = 5; if ( base != 0 && (coin= LP_coinsearch(base)) != 0 && coin->inactive != 0 )
cdata.wiftype = 176; return(1);
LP_userpass(cdata.userpass,symbol,"","litecoin"); else if ( rel != 0 && (coin= LP_coinsearch(rel)) != 0 && coin->inactive != 0 )
return(1);
else return(0);
} }
else
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.pubtype = 60; txfee = 50000;
cdata.p2shtype = 85; estimatedrate = 300;
cdata.wiftype = 188; pubtype = 0;
LP_userpass(cdata.userpass,symbol,symbol,strcmp(symbol,"KMD") == 0 ? "komodo" : symbol); p2shtype = 5;
wiftype = 128;
name = "bitcoin";
} }
//printf("%s: (%s) (%s)\n",symbol,cdata.serverport,cdata.userpass); else if ( strcmp(symbol,"KMD") == 0 )
LP_coins = realloc(LP_coins,sizeof(*LP_coins) * (LP_numcoins+1)); name = "komodo";
coin = &LP_coins[LP_numcoins++]; else return(0);
*coin = cdata; 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); return(coin);
} }
// "coins":[{"coin":"<assetchain>", "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);
}

745
iguana/exchanges/LP_commands.c

@ -18,526 +18,74 @@
// marketmaker // 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)
{
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) char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port
{ {
cJSON *reqjson; struct LP_peerinfo *peer; int32_t i,flag = 0,pushsock = -1; double price = 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;
if ( ipaddr != 0 && port >= 1000 ) //printf("stats_JSON(%s)\n",jprint(argjson,0));
{ if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 )
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 ) if ( strcmp(ipaddr,"127.0.0.1") != 0 && argport >= 1000 )
{ {
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; flag = 1;
jaddstr(reqjson,"method",method); if ( (pushport= juint(argjson,"push")) == 0 )
LP_send(pushsock,jprint(reqjson,1),1); pushport = argport + 1;
for (i=0; i<30; i++) if ( (subport= juint(argjson,"sub")) == 0 )
{ subport = argport + 2;
if ( (price= LP_pricecache(qp,base,rel,qp->txid,qp->vout)) != 0. ) if ( (peer= LP_peerfind((uint32_t)calc_ipbits(ipaddr),argport)) != 0 )
{ {
if ( flag == 0 || bits256_nonz(qp->desthash) != 0 ) if ( 0 && (otherpeers= jint(argjson,"numpeers")) > peer->numpeers )
peer->numpeers = otherpeers;
if ( 0 && (othernumutxos= jint(argjson,"numutxos")) > peer->numutxos )
{ {
//printf("break out of loop.%d price %.8f\n",i,price); printf("change.(%s) numutxos.%d -> %d mynumutxos.%d\n",peer->ipaddr,peer->numutxos,othernumutxos,LP_mypeer != 0 ? LP_mypeer->numutxos:0);
break; peer->numutxos = othernumutxos;
}
}
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); //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"));
} }
int32_t LP_sizematch(uint64_t mysatoshis,uint64_t othersatoshis)
{
if ( mysatoshis >= othersatoshis )
return(0);
else return(-1);
} }
if ( (method= jstr(argjson,"method")) == 0 )
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); if ( flag == 0 || jobj(argjson,"result") != 0 )
return(0); printf("stats_JSON no method: (%s) (%s:%u)\n",jprint(argjson,0),ipaddr,argport);
}
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); 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; i<n; i++)
{
item = jitem(array,i);
//printf("%s\n",jprint(item,0));
safecopy(coinstr,jstr(item,"base"),sizeof(coinstr));
if ( strcmp(coinstr,base) == 0 && LP_sizematch(estimatedbase,j64bits(item,"satoshis")) == 0 )
{
icopy = 0;
if ( (price= LP_pricecache(&Q,base,myutxo->coin,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 )
{
printf("candidates.(%s)\n",jprint(array,0));
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
memset(prices,0,sizeof(prices));
memset(Q,0,sizeof(Q));
for (i=0; i<n && i<sizeof(prices)/sizeof(*prices); i++)
{
item = jitem(array,i);
LP_quoteparse(&Q[i],item);
if ( (price= jdouble(item,"price")) == 0. )
{
price = LP_query("price",&Q[i],jstr(item,"ipaddr"),jint(item,"port"),base,myutxo->coin,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. )
{
bestmetric = 0.;
besti = -1;
for (i=0; i<n && i<sizeof(prices)/sizeof(*prices); i++)
{
if ( (price= prices[i]) != 0. && Q[i].destsatoshis != 0 )
{
metric = price / bestprice;
printf("%f ",metric);
if ( metric > 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 )
{
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");
}
} }
} if ( strcmp(method,"hello") == 0 )
free_json(array);
}
}
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. )
{ {
price *= (1. + profitmargin); //printf("got hello from %s:%u\n",ipaddr!=0?ipaddr:"",argport);
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;
return(0); return(0);
} }
return(-1); else if ( strcmp(method,"nn_tests") == 0 )
} return(clonestr("{\"result\":\"success\"}"));
else if ( strcmp(method,"help") == 0 )
int32_t LP_command(struct LP_peerinfo *mypeer,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin) return(clonestr("{\"result\":\" \
{ available localhost RPC commands:\n \
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; setprice(base, rel, price)\n\
if ( IAMCLIENT == 0 && (method= jstr(argjson,"method")) != 0 ) myprice(base, rel)\n\
{ enable(coin)\n\
txid = jbits256(argjson,"txid"); disable(coin)\n\
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 ) inventory(coin)\n\
{ autotrade(base, rel, price, volume, timeout)\n\
//printf("LP_command.(%s)\n",jprint(argjson,0)); swapstatus()\n\
if ( time(NULL) > utxo->swappending ) swapstatus(requestid, quoteid)\n\
utxo->swappending = 0; public API:\n \
if ( strcmp(method,"price") == 0 || strcmp(method,"request") == 0 ) getcoins()\n\
{ getpeers()\n\
retval = 1; getutxos()\n\
if ( utxo->swappending == 0 ) getutxos(coin, lastn)\n\
{ orderbook(base, rel)\n\
if ( strcmp(method,"request") == 0 && utxo->pair >= 0 ) getprices(base, rel)\n\
nn_close(utxo->pair), utxo->pair = -1; trust(pubkey, trust)\n\
if ( (price= LP_price(base,rel)) != 0. ) register(pubkey,pushaddr)\n\
{ registerall(numnodes)\n\
price *= (1. + profitmargin); lookup(pubkey)\n\
if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 ) forward(pubkey,method2,<argjson>)\n\
return(-1); forward(pubkey,method2=publish,<argjson>)\n\
if ( strcmp(method,"price") == 0 ) forwardhex(pubkey,hex)\n\
Q.timestamp = (uint32_t)time(NULL); \"}"));
retjson = LP_quotejson(&Q); base = jstr(argjson,"base");
if ( strcmp(method,"request") == 0 ) rel = jstr(argjson,"rel");
{
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");
}
}
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\"}"));
if ( USERPASS[0] != 0 && strcmp(remoteaddr,"127.0.0.1") == 0 && port != 0 ) if ( USERPASS[0] != 0 && strcmp(remoteaddr,"127.0.0.1") == 0 && port != 0 )
{ {
if ( USERPASS_COUNTER == 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; USERPASS_COUNTER = 1;
retjson = cJSON_CreateObject(); retjson = cJSON_CreateObject();
jaddstr(retjson,"userpass",USERPASS); jaddstr(retjson,"userpass",USERPASS);
jaddstr(retjson,"BTC",BTCADDR); jaddbits256(retjson,"mypubkey",LP_mypubkey);
jaddstr(retjson,"KMD",KMDADDR); jadd(retjson,"coins",LP_coinsjson());
return(jprint(retjson,1)); return(jprint(retjson,1));
} }
if ( (userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,USERPASS) != 0 ) if ( (userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,USERPASS) != 0 )
return(clonestr("{\"error\":\"authentication error\"}")); 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 ( strcmp(method,"setprice") == 0 )
{ {
if ( LP_mypriceset(base,rel,jdouble(argjson,"price")) < 0 ) if ( price > SMALLVAL )
{
if ( LP_mypriceset(base,rel,price) < 0 )
return(clonestr("{\"error\":\"couldnt set price\"}")); return(clonestr("{\"error\":\"couldnt set price\"}"));
else return(clonestr("{\"result\":\"success\"}")); 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 ) else if ( strcmp(method,"myprice") == 0 )
{ {
double bid,ask; double bid,ask;
if ( LP_myprice(&bid,&ask,base,rel) != 0. ) if ( LP_myprice(&bid,&ask,base,rel) > SMALLVAL )
{ {
retjson = cJSON_CreateObject(); retjson = cJSON_CreateObject();
jaddstr(retjson,"base",base); 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)); return(jprint(retjson,1));
} else return(clonestr("{\"error\":\"no price set\"}")); } 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 ) else if ( (coin= jstr(argjson,"coin")) != 0 )
{ {
if ( strcmp(method,"enable") == 0 )
{
if ( (ptr= LP_coinsearch(coin)) != 0 )
ptr->inactive = 0;
return(jprint(LP_coinsjson(),1));
}
else if ( strcmp(method,"disable") == 0 )
{
if ( (ptr= LP_coinsearch(coin)) != 0 )
ptr->inactive = (uint32_t)time(NULL);
return(jprint(LP_coinsjson(),1));
}
if ( LP_isdisabled(coin,0) != 0 )
return(clonestr("{\"error\":\"coin is disabled\"}"));
if ( strcmp(method,"inventory") == 0 ) if ( strcmp(method,"inventory") == 0 )
{ {
LP_privkey_init(0,-1,coin,0,USERPASS_WIFSTR,1); struct iguana_info *ptr; bits256 privkey,pubkey; uint8_t pubkey33[33];
return(LP_inventory(coin)); if ( (ptr= LP_coinfind(coin)) != 0 )
{
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));
}
}
} }
else if ( IAMCLIENT != 0 && (strcmp(method,"candidates") == 0 || strcmp(method,"autotrade") == 0) ) else if ( strcmp(method,"swapstatus") == 0 )
{ {
bits256 txid; int32_t vout; struct LP_utxoinfo *utxo; uint32_t requestid,quoteid;
txid = jbits256(argjson,"txid"); if ( (requestid= juint(argjson,"requestid")) != 0 && (quoteid= juint(argjson,"quoteid")) != 0 )
if ( bits256_nonz(txid) == 0 ) return(basilisk_swapentry(requestid,quoteid));
return(clonestr("{\"error\":\"invalid or missing txid\"}")); else return(basilisk_swaplist());
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));
} }
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")));
} }
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_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 )
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\"}");
} }
amclient = (LP_mypeer == 0); else if ( strcmp(method,"keepalive") == 0 )
if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 )
{ {
if ( strcmp(ipaddr,"127.0.0.1") != 0 && port >= 1000 ) 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 )
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 )
{ {
if ( (pushport= juint(argjson,"push")) == 0 ) if ( LP_utxoaddjson(1,LP_mypubsock,argjson) != 0 )
pushport = argport + 1; return(clonestr("{\"result\":\"success\",\"notifyutxo\":\"received\"}"));
if ( (subport= juint(argjson,"sub")) == 0 ) else return(clonestr("{\"error\":\"couldnt add utxo\"}"));
subport = argport + 2; }
if ( (peer= LP_peerfind((uint32_t)calc_ipbits(ipaddr),argport)) != 0 ) else if ( IAMLP != 0 )
{ {
if ( 0 && (otherpeers= jint(argjson,"numpeers")) > peer->numpeers ) if ( strcmp(method,"register") == 0 )
peer->numpeers = otherpeers;
if ( 0 && (othernumutxos= jint(argjson,"numutxos")) > peer->numutxos )
{ {
printf("change.(%s) numutxos.%d -> %d mynumutxos.%d\n",peer->ipaddr,peer->numutxos,othernumutxos,LP_mypeer != 0 ? LP_mypeer->numutxos:0); retstr = LP_register(jbits256(argjson,"client"),jstr(argjson,"pushaddr"),juint(argjson,"pushport"));
peer->numutxos = othernumutxos; //printf("got (%s) from register\n",retstr!=0?retstr:"");
return(retstr);
} }
//printf("peer.(%s) found (%d %d) (%d %d) (%s)\n",peer->ipaddr,peer->numpeers,peer->numutxos,otherpeers,othernumutxos,jprint(argjson,0)); else if ( strcmp(method,"lookup") == 0 )
} else LP_addpeer(amclient,LP_mypeer,LP_mypubsock,ipaddr,argport,pushport,subport,jdouble(argjson,"profit"),jint(argjson,"numpeers"),jint(argjson,"numutxos")); 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")));
} }
//printf("CMD.(%s)\n",jprint(argjson,0)); else if ( strcmp(method,"notify") == 0 )
if ( strcmp(method,"quote") == 0 || 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"));
else if ( strcmp(method,"orderbook") == 0 )
retstr = LP_orderbook(jstr(argjson,"base"),jstr(argjson,"rel"));
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\"}"); retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}");
else if ( IAMCLIENT == 0 && strcmp(method,"notifyutxo") == 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 ( retstr != 0 ) if ( retstr != 0 )
return(retstr); {
retjson = cJSON_CreateObject(); free(retstr);
jaddstr(retjson,"error","unrecognized command"); return(0);
}
printf("ERROR.(%s)\n",jprint(argjson,0)); printf("ERROR.(%s)\n",jprint(argjson,0));
return(clonestr(jprint(retjson,1))); return(0);
} }

349
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<n; i++)
{
if ( nn_poll(&pfd,1,1) > 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; i++)
if ( (n= LP_forwarding_register(LP_mypubkey,LP_publicaddr,LP_publicport,numnodes)) >= 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\"}"));
}

119
iguana/exchanges/LP_include.h

@ -21,6 +21,29 @@
#ifndef LP_INCLUDE_H #ifndef LP_INCLUDE_H
#define 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_DECKSIZE 1000
#define INSTANTDEX_LOCKTIME (3600*2 + 300*2) #define INSTANTDEX_LOCKTIME (3600*2 + 300*2)
#define INSTANTDEX_INSURANCEDIV 777 #define INSTANTDEX_INSURANCEDIV 777
@ -31,19 +54,19 @@
#define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu" #define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu"
#define INSTANTDEX_BTCD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf" #define INSTANTDEX_BTCD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf"
#define BASILISK_DISABLEWAITTX //#define BASILISK_DISABLEWAITTX
#define BASILISK_DISABLESENDTX //#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_RESERVETIME 60
#define LP_AVETXSIZE 200 #define LP_AVETXSIZE 200
#define LP_CACHEDURATION 60 #define LP_CACHEDURATION 60
#define BASILISK_DEFAULT_NUMCONFIRMS 5 #define BASILISK_DEFAULT_NUMCONFIRMS 1
#define DEX_SLEEP 3 #define DEX_SLEEP 3
#define BASILISK_KEYSIZE ((int32_t)(2*sizeof(bits256)+sizeof(uint32_t)*2)) #define BASILISK_KEYSIZE ((int32_t)(2*sizeof(bits256)+sizeof(uint32_t)*2))
extern char GLOBAL_DBDIR[],USERPASS[],USERPASS_WIFSTR[]; 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; }; 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 struct iguana_info
{ {
uint64_t txfee; double estimatedrate; uint64_t txfee; double estimatedrate,profitmargin;
int32_t longestchain; int32_t longestchain; uint32_t counter,inactive;
uint8_t pubtype,p2shtype,isPoS,wiftype; uint8_t pubtype,p2shtype,isPoS,wiftype,taddr;
char symbol[16],changeaddr[64],userpass[1024],serverport[128]; char symbol[16],smartaddr[64],userpass[1024],serverport[128];
}; };
struct basilisk_swap struct _LP_utxoinfo { bits256 txid; uint64_t value; int32_t vout; };
{
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_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 struct LP_utxoinfo
{ {
UT_hash_handle hh; UT_hash_handle hh,hh2;
bits256 txid,txid2,feetxid,otherpubkey,mypub; bits256 pubkey;
void *swap; struct _LP_utxoinfo payment,deposit,fee;
uint64_t satoshis,satoshis2; struct LP_utxostats T;
struct LP_utxoswap S;
//struct LP_utxonetwork N;
int32_t iambob,iamlp;
uint8_t key[sizeof(bits256) + sizeof(int32_t)]; uint8_t key[sizeof(bits256) + sizeof(int32_t)];
int32_t vout,vout2,pair; uint8_t key2[sizeof(bits256) + sizeof(int32_t)];
uint32_t lasttime,errors,swappending,published; char coin[16],coinaddr[64],spendscript[256],gui[16];
double profitmargin;
char ipaddr[64],coinaddr[64],spendscript[256],coin[16];
uint16_t port;
}; };
struct LP_peerinfo struct LP_peerinfo
@ -178,7 +194,7 @@ struct LP_peerinfo
UT_hash_handle hh; UT_hash_handle hh;
uint64_t ip_port; uint64_t ip_port;
double profitmargin; 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; int32_t pushsock,subsock;
uint16_t port; uint16_t port;
char ipaddr[64]; char ipaddr[64];
@ -188,16 +204,49 @@ struct LP_quoteinfo
{ {
struct basilisk_request R; struct basilisk_request R;
bits256 srchash,desthash,txid,txid2,desttxid,feetxid,privkey; 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; uint32_t timestamp,quotetime; int32_t vout,vout2,destvout,feevout,pair;
char srccoin[16],coinaddr[64],destcoin[16],destaddr[64]; 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); void basilisk_dontforget_update(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx);
uint32_t basilisk_requestid(struct basilisk_request *rp); uint32_t basilisk_requestid(struct basilisk_request *rp);
uint32_t basilisk_quoteid(struct basilisk_request *rp); uint32_t basilisk_quoteid(struct basilisk_request *rp);
struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp); struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp);
char *bitcoind_passthru(char *coinstr,char *serverport,char *userpass,char *method,char *params); 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); 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 #endif

496
iguana/exchanges/LP_nativeDEX.c

@ -17,33 +17,32 @@
// LP_nativeDEX.c // LP_nativeDEX.c
// marketmaker // marketmaker
// //
// jl777: fix price calcs based on specific txfees
#include <stdio.h> #include <stdio.h>
#include "LP_include.h" #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" #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_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 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 LP_mypubsock = -1;
int32_t Client_connections; int32_t USERPASS_COUNTER,IAMLP = 0;
int32_t USERPASS_COUNTER,IAMCLIENT = 0;
double LP_profitratio = 1.; double LP_profitratio = 1.;
bits256 LP_mypubkey;
// stubs // 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) 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 // add to trades
} }
char *LP_getdatadir() char *LP_getdatadir()
{ {
return(USERHOME); return(USERHOME);
@ -74,179 +74,375 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_
#include "LP_swap.c" #include "LP_swap.c"
#include "LP_peers.c" #include "LP_peers.c"
#include "LP_utxos.c" #include "LP_utxos.c"
#include "LP_forwarding.c"
#include "LP_ordermatch.c"
#include "LP_commands.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=0;
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 ( jobj(argjson,"result") != 0 || jobj(argjson,"error") != 0 )
if ( amclient == 0 ) return(0);
if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,data,datalen,profitmargin) <= 0 )
{ {
for (i=0; i<sizeof(default_LPnodes)/sizeof(*default_LPnodes); i++) if ( (retstr= stats_JSON(ctx,myipaddr,pubsock,profitmargin,argjson,"127.0.0.1",0)) != 0 )
{ {
if ( (rand() % 100) > 25 ) //printf("%s PULL.[%d]-> (%s)\n",myipaddr != 0 ? myipaddr : "127.0.0.1",datalen,retstr);
continue; if ( pubsock >= 0 ) //strncmp("{\"error\":",retstr,strlen("{\"error\":")) != 0 &&
LP_peersquery(amclient,mypeer,pubsock,default_LPnodes[i],myport,mypeer->ipaddr,myport,profitmargin); 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)
{ {
OS_randombytes((void *)&r,sizeof(r)); int32_t len,datalen=0; char *msg,*retstr=0,*jsonstr=0; cJSON *argjson,*reqjson;
for (j=0; j<sizeof(default_LPnodes)/sizeof(*default_LPnodes); j++) if ( (datalen= is_hexstr((char *)ptr,0)) > 0 )
{
datalen >>= 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 )
{ {
i = (r + j) % (sizeof(default_LPnodes)/sizeof(*default_LPnodes));
LP_peersquery(amclient,mypeer,pubsock,default_LPnodes[i],myport,"127.0.0.1",myport,profitmargin);
} }
} }
//if ( amclient != 0 ) else if ( jstr(argjson,"method") != 0 && strcmp(jstr(argjson,"method"),"publish") == 0 )
// tmpport = myport + 10;
//else tmpport = myport;
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); printf("got publish\n");
exit(-1); 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);
} }
for (i=0; i<sizeof(activecoins)/sizeof(*activecoins); i++) }
else if ( (retstr= LP_command_process(ctx,myipaddr,pubsock,argjson,&((uint8_t *)ptr)[len],recvlen - len,profitmargin)) != 0 )
{ {
LP_coinfind(activecoins[i]);
LP_priceinfoadd(activecoins[i]);
} }
LP_privkey_updates(mypeer,pubsock,passphrase,amclient); portable_mutex_unlock(&LP_commandmutex);
HASH_ITER(hh,LP_peerinfos,peer,tmp) if ( LP_COMMAND_RECVSOCK == NN_REP )
{
if ( retstr != 0 )
{
if ( strcmp("PULL",typestr) == 0 )
{ {
if ( strcmp(peer->ipaddr,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1") != 0 ) printf("%d got REQ.(%s) -> (%s)\n",recvsock,jprint(argjson,0),retstr);
LP_utxosquery(0,mypeer,pubsock,peer->ipaddr,peer->port,"",100,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,profitmargin); LP_send(recvsock,retstr,(int32_t)strlen(retstr)+1,0);
} }
if ( amclient != 0 ) }
else if ( strcmp("PULL",typestr) == 0 )
{ {
while ( 1 ) 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)
{ {
nonz = n = 0; void *ptr; int32_t recvlen=-1,nonz = 0;
if ( (++counter % 3600) == 0 ) *retstrp = 0;
LP_privkey_updates(mypeer,pubsock,passphrase,amclient); if ( pullsock >= 0 )
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{ {
n++; while ( (recvlen= nn_recv(pullsock,&ptr,NN_MSG,0)) > 0 )
while ( peer->subsock >= 0 && (recvsize= nn_recv(peer->subsock,&ptr,NN_MSG,0)) >= 0 )
{ {
nonz++; nonz++;
if ( (argjson= cJSON_Parse((char *)ptr)) != 0 ) *retstrp = LP_process_message(ctx,"PULL",myipaddr,pubsock,profitmargin,ptr,recvlen,pullsock);
}
}
return(nonz);
}
int32_t LP_subsock_check(void *ctx,char *myipaddr,int32_t pubsock,int32_t sock,double profitmargin)
{ {
portable_mutex_lock(&LP_commandmutex); int32_t recvlen,nonz = 0; void *ptr; char *retstr;
if ( (retstr= stats_JSON(argjson,"127.0.0.1",0)) != 0 ) if ( sock >= 0 )
{
while ( (recvlen= nn_recv(sock,&ptr,NN_MSG,0)) > 0 )
{ {
//printf("%s RECV.[%d] %s\n",peer->ipaddr,recvsize,(char *)ptr); nonz++;
if ( (retstr= LP_process_message(ctx,"SUB",myipaddr,pubsock,profitmargin,ptr,recvlen,sock)) != 0 )
free(retstr); 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;
} }
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);
} }
if ( nonz == 0 )
usleep(100000);
} }
} }
else
void LP_myutxo_updates(void *ctx,int32_t pubsock,char *passphrase,double profitmargin)
{ {
while ( 1 ) //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 )
{ {
nonz = 0; //lastn = peer->numutxos - mypeer->numutxos + LP_PROPAGATION_SLACK;
if ( (++counter % 2000) == 0 ) //if ( lastn < LP_PROPAGATION_SLACK * 2 )
LP_privkey_updates(mypeer,pubsock,passphrase,amclient); lastn = LP_PROPAGATION_SLACK * 2;
if ( (counter % 500) == 0 ) if ( mypeer == 0 || strcmp(peer->ipaddr,mypeer->ipaddr) != 0 )
{ {
HASH_ITER(hh,LP_utxoinfos,utxo,utmp) 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 ( strcmp(utxo->ipaddr,mypeer->ipaddr) == 0 && utxo->port == mypeer->port ) if ( peer->errors >= LP_MAXPEER_ERRORS )
{ {
if ( strcmp(utxo->coin,"KMD") == 0 ) if ( (rand() % 10000) == 0 )
LP_priceping(pubsock,utxo,"BTC",profitmargin); peer->errors--;
else LP_priceping(pubsock,utxo,"KMD",profitmargin); 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);
} }
HASH_ITER(hh,LP_peerinfos,peer,tmp) 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 )
{ {
if ( peer->numpeers != mypeer->numpeers || (rand() % 10000) == 0 ) LP_myutxo_updates(ctx,pubsock,passphrase,profitmargin);
if ( lastforward < now-3600 )
{ {
if ( peer->numpeers != mypeer->numpeers ) if ( (retstr= LP_registerall(0)) != 0 )
printf("%s num.%d vs %d\n",peer->ipaddr,peer->numpeers,mypeer->numpeers); free(retstr);
if ( strcmp(peer->ipaddr,mypeer->ipaddr) != 0 ) //LP_forwarding_register(LP_mypubkey,pushaddr,pushport,10);
LP_peersquery(amclient,mypeer,pubsock,peer->ipaddr,peer->port,mypeer->ipaddr,myport,profitmargin); lastforward = now;
} }
if ( peer->numutxos != mypeer->numutxos ) }
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d utxos\n",counter,LP_canbind);
if ( (counter % 600) == 60 )
{ {
lastn = peer->numutxos - mypeer->numutxos + LP_PROPAGATION_SLACK; HASH_ITER(hh,LP_utxoinfos[0],utxo,utmp)
if ( lastn < LP_PROPAGATION_SLACK * 2 ) {
lastn = LP_PROPAGATION_SLACK * 2; LP_utxo_spentcheck(pubsock,utxo,profitmargin);
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 ) HASH_ITER(hh,LP_utxoinfos[1],utxo,utmp)
{ {
nonz++; //char str[65];
if ( (argjson= cJSON_Parse((char *)ptr)) != 0 ) 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 )
{ {
portable_mutex_lock(&LP_commandmutex); if ( (retstr= basilisk_swapentry(0,0)) != 0 )
if ( (retstr= stats_JSON(argjson,"127.0.0.1",0)) != 0 )
{ {
//printf("%s RECV.[%d] %s\n",peer->ipaddr,recvsize,(char *)ptr); //printf("SWAPS.(%s)\n",retstr);
free(retstr); free(retstr);
} }
portable_mutex_unlock(&LP_commandmutex); }
free_json(argjson); //if ( LP_canbind == 0 ) printf("counter.%d canbind.%d pullsock check\n",counter,LP_canbind);
} else printf("error parsing.(%s)\n",(char *)ptr); nonz += LP_pullsock_check(ctx,&retstr,myipaddr,pubsock,pullsock,profitmargin);
if ( ptr != 0 ) if ( retstr != 0 )
nn_freemsg(ptr), ptr = 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;
} }
} }
while ( pullsock >= 0 && (recvsize= nn_recv(pullsock,&ptr,NN_MSG,0)) >= 0 ) counter++;
return(nonz);
}
void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins,char *passphrase)
{ {
nonz++; int32_t i,n; cJSON *item;
if ( (argjson= cJSON_Parse((char *)ptr)) != 0 ) for (i=0; i<sizeof(activecoins)/sizeof(*activecoins); i++)
{ {
len = (int32_t)strlen((char *)ptr) + 1; fprintf(stderr,"%s ",activecoins[i]);
portable_mutex_lock(&LP_commandmutex); LP_coinfind(activecoins[i]);
if ( LP_command(mypeer,pubsock,argjson,&((uint8_t *)ptr)[len],recvsize - len,profitmargin) == 0 ) LP_priceinfoadd(activecoins[i]);
}
if ( (n= cJSON_GetArraySize(coins)) > 0 )
{ {
if ( (retstr= stats_JSON(argjson,"127.0.0.1",0)) != 0 ) for (i=0; i<n; i++)
{ {
//printf("%s RECV.[%d] %s\n",peer->ipaddr,recvsize,(char *)ptr); item = jitem(coins,i);
free(retstr); fprintf(stderr,"%s ",jstr(item,"coin"));
LP_coincreate(item);
LP_priceinfoadd(jstr(item,"coin"));
} }
} }
portable_mutex_unlock(&LP_commandmutex); fprintf(stderr,"privkey updates\n");
free_json(argjson); LP_privkey_updates(ctx,pubsock,passphrase,1);
} }
if ( ptr != 0 )
nn_freemsg(ptr), ptr = 0; void LP_initpeers(int32_t pubsock,struct LP_peerinfo *mypeer,char *myipaddr,uint16_t myport,char *seednode,double profitmargin)
{
int32_t i,j; uint32_t r;
if ( IAMLP != 0 )
{
LP_mypeer = mypeer = LP_addpeer(mypeer,pubsock,myipaddr,myport,0,0,profitmargin,0,0);
if ( myipaddr == 0 || mypeer == 0 )
{
printf("couldnt get myipaddr or null mypeer.%p\n",mypeer);
exit(-1);
}
if ( seednode == 0 || seednode[0] == 0 )
{
for (i=0; i<sizeof(default_LPnodes)/sizeof(*default_LPnodes); i++)
{
if ( (rand() % 100) > 25 )
continue;
LP_peersquery(mypeer,pubsock,default_LPnodes[i],myport,mypeer->ipaddr,myport,profitmargin);
} }
if ( nonz == 0 ) } else LP_peersquery(mypeer,pubsock,seednode,myport,mypeer->ipaddr,myport,profitmargin);
usleep(50000);
} }
else
{
if ( myipaddr == 0 )
{
printf("couldnt get myipaddr\n");
exit(-1);
}
if ( seednode == 0 || seednode[0] == 0 )
{
OS_randombytes((void *)&r,sizeof(r));
for (j=0; j<sizeof(default_LPnodes)/sizeof(*default_LPnodes); j++)
{
i = (r + j) % (sizeof(default_LPnodes)/sizeof(*default_LPnodes));
LP_peersquery(mypeer,pubsock,default_LPnodes[i],myport,"127.0.0.1",myport,profitmargin);
}
} 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,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 )
{ {
char *myipaddr=0; long filesize,n; int32_t timeout,maxsize,pullsock=-1,pubsock=-1; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128]; printf("must run a unix node for LP node\n");
IAMCLIENT = amclient; exit(-1);
}
#endif
LP_profitratio += profitmargin; LP_profitratio += profitmargin;
OS_randombytes((void *)&n,sizeof(n)); 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); srand((int32_t)n);
if ( userhome != 0 && userhome[0] != 0 ) if ( userhome != 0 && userhome[0] != 0 )
{
safecopy(USERHOME,userhome,sizeof(USERHOME)); safecopy(USERHOME,userhome,sizeof(USERHOME));
#ifdef __APPLE__
strcat(USERHOME,"/Library/Application Support");
#endif
}
portable_mutex_init(&LP_peermutex); portable_mutex_init(&LP_peermutex);
portable_mutex_init(&LP_utxomutex); portable_mutex_init(&LP_utxomutex);
portable_mutex_init(&LP_UTXOmutex);
portable_mutex_init(&LP_commandmutex); portable_mutex_init(&LP_commandmutex);
portable_mutex_init(&LP_swaplistmutex);
portable_mutex_init(&LP_cachemutex); 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; profitmargin = 0.01 + (double)(rand() % 100)/100000;
@ -259,44 +455,70 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profit
n = strlen(myipaddr); n = strlen(myipaddr);
if ( myipaddr[n-1] == '\n' ) if ( myipaddr[n-1] == '\n' )
myipaddr[--n] = 0; myipaddr[--n] = 0;
pullsock = pubsock = -1; strcpy(LP_myipaddr,myipaddr);
nanomsg_tcpname(pushaddr,myipaddr,mypullport); } else printf("error getting myipaddr\n");
nanomsg_tcpname(subaddr,myipaddr,mypubport); } else printf("error issuing curl\n");
printf(">>>>>>>>> myipaddr.%s (%s %s)\n",myipaddr,pushaddr,subaddr); if ( IAMLP != 0 )
if ( (pullsock= nn_socket(AF_SP,NN_PULL)) >= 0 && (pubsock= nn_socket(AF_SP,NN_PUB)) >= 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 ( nn_bind(pullsock,pushaddr) >= 0 && nn_bind(pubsock,subaddr) >= 0 ) if ( nn_bind(pubsock,bindaddr) >= 0 )
{ {
timeout = 10; timeout = 10;
nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); 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 else
{ {
printf("error binding to (%s).%d (%s).%d\n",pushaddr,pullsock,subaddr,pubsock); printf("error binding to (%s).%d\n",subaddr,pubsock);
if ( pullsock >= 0 )
nn_close(pullsock), pullsock = -1;
if ( pubsock >= 0 ) if ( pubsock >= 0 )
nn_close(pubsock), pubsock = -1; nn_close(pubsock), pubsock = -1;
} }
} else printf("error getting sockets %d %d\n",pullsock,pubsock); } else printf("error getting pubsock %d\n",pubsock);
printf(">>>>>>>>> myipaddr.%s (%s) pullsock.%d\n",myipaddr,subaddr,pubsock);
LP_mypubsock = 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:""); LP_initpeers(pubsock,mypeer,myipaddr,myport,jstr(argjson,"seednode"),profitmargin);
} else printf("error getting myipaddr\n"); pullsock = LP_initpublicaddr(ctx,&mypullport,pushaddr,myipaddr,mypullport,0);
} else printf("error issuing curl\n"); strcpy(LP_publicaddr,pushaddr);
if ( myipaddr == 0 || mypeer == 0 ) 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("couldnt get myipaddr or null mypeer.%p\n",mypeer); printf("error launching LP_psockloop for (%s)\n",myipaddr);
exit(-1); exit(-1);
} }
printf("utxos.(%s)\n",LP_utxos(mypeer,"",10000)); 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);
} }
LP_mainloop(mypeer,mypubport,pubsock,pullsock,myport,amclient,passphrase,profitmargin); 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("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);
} }
}
}
}

396
iguana/exchanges/LP_network.c

@ -18,39 +18,52 @@
// marketmaker // 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); 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 ) 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 ) if ( freeflag != 0 )
free(msg); free(msg);
return(-1); 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.fd = sock;
pfd.events = NN_POLLOUT; 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,sendlen,0)) != sendlen )
if ( (sentbytes= nn_send(sock,msg,len,0)) != len ) printf("LP_send sent %d instead of %d\n",sentbytes,sendlen);
printf("LP_send sent %d instead of %d\n",sentbytes,len); //else printf("SENT.(%s)\n",msg);
else printf("SENT.(%s)\n",msg);
if ( freeflag != 0 ) if ( freeflag != 0 )
free(msg); free(msg);
//portable_mutex_unlock(&LP_networkmutex);
return(sentbytes); return(sentbytes);
} }
//portable_mutex_unlock(&LP_networkmutex);
usleep(1000); 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 ) if ( freeflag != 0 )
free(msg); free(msg);
return(-1); 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); //else printf("send.[%d] %x offset.%d datalen.%d [%llx]\n",sentbytes,msgbits,offset,datalen,*(long long *)data);
free(buf); free(buf);
return(nextbits); 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; i<Numpsocks; i++)
{
ptr = &PSOCKS[i];
if ( iter == 0 )
{
pfds[n].fd = ptr->publicsock;
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<Numpsocks; i++)
{
if ( i < Numpsocks )
{
ptr = &PSOCKS[i];
if ( now > 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; i<Numpsocks; i++)
{
ptr = &PSOCKS[i];
if ( strcmp(publicaddr,ptr->publicaddr) == 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<maxiters; i++,publicport+=2,subport+=2)
{
if ( publicport < MIN_PSOCK_PORT )
publicport = MIN_PSOCK_PORT+1;
if ( subport <= publicport )
subport = publicport + 1;
pullsock = pubsock = -1;
nanomsg_transportname(1,pushaddr,myipaddr,publicport);
nanomsg_transportname(1,subaddr,myipaddr,subport);
if ( (pullsock= nn_socket(AF_SP,ispaired!=0?NN_PAIR:NN_PULL)) >= 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);
}

690
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; i<n; i++)
{
item = jitem(array,i);
if ( vout == jint(item,"vout") && bits256_cmp(txid,jbits256(item,"txid")) == 0 )
return(i);
}
return(-1);
}
double LP_query(void *ctx,char *myipaddr,int32_t mypubsock,double profitmargin,char *method,struct LP_quoteinfo *qp)
{
cJSON *reqjson; char *msg; int32_t i,flag = 0; double price = 0.; struct LP_utxoinfo *utxo;
if ( strcmp(method,"request") == 0 )
{
if ( (utxo= LP_utxofind(0,qp->desttxid,qp->destvout)) != 0 && LP_ismine(utxo) > 0 && LP_isavailable(utxo) > 0 )
LP_unavailableset(utxo,qp->srchash);
else
{
printf("couldnt find my txid to make request\n");
return(0.);
}
}
reqjson = LP_quotejson(qp);
if ( bits256_nonz(qp->desthash) != 0 )
flag = 1;
//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<numasks; i++)
{
item = jitem(asks,i);
if ( (price= jdouble(item,"price")) > 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));
}

55
iguana/exchanges/LP_peers.c

@ -42,21 +42,22 @@ char *LP_peers()
struct LP_peerinfo *peer,*tmp; cJSON *peersjson = cJSON_CreateArray(); struct LP_peerinfo *peer,*tmp; cJSON *peersjson = cJSON_CreateArray();
HASH_ITER(hh,LP_peerinfos,peer,tmp) HASH_ITER(hh,LP_peerinfos,peer,tmp)
{ {
//if ( peer->errors < LP_MAXPEER_ERRORS )
jaddi(peersjson,LP_peerjson(peer)); jaddi(peersjson,LP_peerjson(peer));
} }
return(jprint(peersjson,1)); 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); ipbits = (uint32_t)calc_ipbits(ipaddr);
expand_ipbits(checkip,ipbits); expand_ipbits(checkip,ipbits);
if ( strcmp(checkip,ipaddr) == 0 ) if ( strcmp(checkip,ipaddr) == 0 )
{ {
if ( (peer= LP_peerfind(ipbits,port)) != 0 ) if ( (peer= LP_peerfind(ipbits,port)) != 0 )
{ {
if ( peer->profitmargin == 0. ) if ( profitmargin != 0. )
peer->profitmargin = profitmargin; peer->profitmargin = profitmargin;
if ( numpeers > peer->numpeers ) if ( numpeers > peer->numpeers )
peer->numpeers = numpeers; peer->numpeers = numpeers;
@ -65,34 +66,32 @@ struct LP_peerinfo *LP_addpeer(int32_t amclient,struct LP_peerinfo *mypeer,int32
} }
else else
{ {
//printf("LPaddpeer %s\n",ipaddr); printf("LPaddpeer %s\n",ipaddr);
peer = calloc(1,sizeof(*peer)); peer = calloc(1,sizeof(*peer));
peer->pushsock = peer->subsock = pushsock = subsock = -1; peer->pushsock = peer->subsock = pushsock = subsock = -1;
strcpy(peer->ipaddr,ipaddr); 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 ) if ( pushport != 0 && subport != 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 )
{ {
timeout = 1000; nanomsg_transportname(0,pushaddr,peer->ipaddr,pushport);
nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
nanomsg_tcpname(pushaddr,peer->ipaddr,pushport);
if ( nn_connect(pushsock,pushaddr) >= 0 ) 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); printf("connected to push.(%s) %d\n",pushaddr,pushsock);
peer->connected = (uint32_t)time(NULL); peer->connected = (uint32_t)time(NULL);
peer->pushsock = pushsock; 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; timeout = 1;
nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout));
nn_setsockopt(subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); 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 ) if ( nn_connect(subsock,subaddr) >= 0 )
{ {
peer->subsock = subsock; peer->subsock = subsock;
printf("connected to sub.(%s) %d\n",subaddr,peer->subsock); printf("connected to sub.(%s) %d\n",subaddr,peer->subsock);
Client_connections += amclient;
} else nn_close(subsock); } 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 } else peer->numpeers = 1; // will become mypeer
portable_mutex_unlock(&LP_peermutex); portable_mutex_unlock(&LP_peermutex);
if ( mypubsock >= 0 ) 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); } else printf("LP_addpeer: checkip.(%s) vs (%s)\n",checkip,ipaddr);
return(peer); 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; struct LP_peerinfo *peer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0;
if ( (array= cJSON_Parse(retstr)) != 0 ) if ( (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); argipbits = (uint32_t)calc_ipbits(argipaddr);
if ( (peer= LP_peerfind(argipbits,argport)) == 0 ) 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 ) if ( peer != 0 )
{ {
@ -156,19 +158,17 @@ int32_t LP_peersparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubs
return(n); 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; char *retstr; struct LP_peerinfo *peer,*tmp; uint32_t now,flag = 0;
peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); 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 ) 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); //printf("got.(%s)\n",retstr);
now = (uint32_t)time(NULL); now = (uint32_t)time(NULL);
LP_peersparse(amclient,mypeer,mypubsock,destipaddr,destport,retstr,now); LP_peersparse(mypeer,mypubsock,destipaddr,destport,retstr,now);
free(retstr); free(retstr);
if ( amclient == 0 ) if ( IAMLP != 0 )
{ {
HASH_ITER(hh,LP_peerinfos,peer,tmp) 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 ) if ( flag != 0 )
printf(" <- missing peers\n"); 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);
} }

490
iguana/exchanges/LP_prices.c

@ -18,7 +18,9 @@
// marketmaker // 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 struct LP_priceinfo
{ {
char symbol[16]; char symbol[16];
@ -39,6 +41,45 @@ struct LP_cacheinfo
uint32_t timestamp; uint32_t timestamp;
} *LP_cacheinfos; } *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; i<LP_numpriceinfos; i++,pp++)
if ( pp->coinbits == 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) int32_t LP_cachekey(uint8_t *key,char *base,char *rel,bits256 txid,int32_t vout)
{ {
uint64_t basebits,relbits; int32_t offset = 0; 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 *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)]; 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) ) if ( LP_cachekey(key,base,rel,txid,vout) == sizeof(key) )
{ {
portable_mutex_lock(&LP_cachemutex); 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); 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; baseid<LP_numpriceinfos; baseid++)
{
base = LP_priceinfos[baseid].symbol;
for (relid=0; relid<LP_numpriceinfos; relid++)
{
if ( (price= pubp->matrix[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; i<n; i++)
{
item = jitem(asks,i);
base = jstri(item,0);
rel = jstri(item,1);
askprice = jdoublei(item,2);
if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 )
{
char str[65]; printf("%s %s/%s (%d/%d) %.8f\n",bits256_str(str,pubkey),base,rel,basepp->ind,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; i<n; i++)
LP_prices_parse(jitem(array,i));
}
free_json(array);
}
free(retstr);
}
}
double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,int32_t vout) double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,int32_t vout)
{ {
struct LP_cacheinfo *ptr; struct LP_cacheinfo *ptr;
@ -79,7 +247,7 @@ double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,i
(*qp) = ptr->Q; (*qp) = ptr->Q;
if ( ptr->price == 0. && ptr->Q.satoshis != 0 ) 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; ptr->price = (double)ptr->Q.destsatoshis / ptr->Q.satoshis;
} }
//printf("found %s/%s %.8f\n",base,rel,ptr->price); //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.); return(0.);
} }
struct LP_priceinfo *LP_priceinfofind(char *symbol) void LP_priceinfoupdate(char *base,char *rel,double price)
{ {
int32_t i; struct LP_priceinfo *pp; uint64_t coinbits; struct LP_priceinfo *basepp,*relpp;
if ( LP_numpriceinfos > 0 ) if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{ {
coinbits = stringbits(symbol); //dxblend(&basepp->relvals[relpp->ind],price,0.9);
pp = LP_priceinfos; //dxblend(&relpp->relvals[basepp->ind],1. / price,0.9);
for (i=0; i<LP_numpriceinfos; i++,pp++) basepp->relvals[relpp->ind] = price;
if ( pp->coinbits == coinbits ) relpp->relvals[basepp->ind] = 1. / price;
return(pp);
} }
return(0);
} }
struct LP_priceinfo *LP_priceinfoptr(int32_t *indp,char *base,char *rel) 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 ) if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{ {
*indp = relpp->ind; if ( (*askp= basepp->myprices[relpp->ind]) > SMALLVAL )
return(basepp); {
if ( (val= relpp->myprices[basepp->ind]) > SMALLVAL )
{
*bidp = 1. / val;
return((*askp + *bidp) * 0.5);
} }
else else
{ {
*indp = -1; *bidp = 0.;
return(0); return(*askp);
} }
} }
else
void LP_priceinfoupdate(char *base,char *rel,double price)
{ {
struct LP_priceinfo *basepp,*relpp; if ( (val= relpp->myprices[basepp->ind]) > SMALLVAL )
if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{ {
dxblend(&basepp->relvals[relpp->ind],price,0.9); *bidp = 1. / val;
dxblend(&relpp->relvals[basepp->ind],1. / price,0.9); *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; int32_t baseid,relid; double bid,ask; char *base,*rel; cJSON *item,*array;
if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) array = cJSON_CreateArray();
for (baseid=0; baseid<LP_numpriceinfos; baseid++)
{ {
*askp = basepp->myprices[relpp->ind]; base = LP_priceinfos[baseid].symbol;
*bidp = relpp->myprices[basepp->ind]; for (relid=0; relid<LP_numpriceinfos; relid++)
return((*askp + *bidp) * 0.5); {
} else return(0.); rel = LP_priceinfos[relid].symbol;
if ( LP_myprice(&bid,&ask,base,rel) > 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) int32_t LP_mypriceset(char *base,char *rel,double price)
{ {
struct LP_priceinfo *basepp,*relpp; struct LP_priceinfo *basepp,*relpp; struct LP_pubkeyinfo *pubp;
if ( price != 0. && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) 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 basepp->myprices[relpp->ind] = price; // ask
relpp->myprices[basepp->ind] = (1. / price) * LP_profitratio; // bid //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); return(0);
} else return(-1); } else return(-1);
} }
@ -167,7 +359,7 @@ cJSON *LP_priceinfomatrix(int32_t usemyprices)
now = (uint32_t)time(NULL); now = (uint32_t)time(NULL);
HASH_ITER(hh,LP_cacheinfos,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; continue;
LP_priceinfoupdate(ptr->Q.srccoin,ptr->Q.destcoin,ptr->price); 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. ) if ( usemyprices == 0 || (val= pp->myprices[j]) == 0. )
val = pp->relvals[j]; val = pp->relvals[j];
if ( val != 0. ) if ( val > SMALLVAL )
{ {
sum += val; sum += val;
n++; n++;
@ -196,17 +388,22 @@ cJSON *LP_priceinfomatrix(int32_t usemyprices)
{ {
pp = LP_priceinfos; pp = LP_priceinfos;
for (i=0; i<LP_numpriceinfos; i++,pp++) for (i=0; i<LP_numpriceinfos; i++,pp++)
{
if ( pp->diagval > SMALLVAL )
{ {
pp->diagval /= total; pp->diagval /= total;
jaddnum(vectorjson,pp->symbol,pp->diagval); jaddnum(vectorjson,pp->symbol,pp->diagval);
} }
} }
}
return(vectorjson); return(vectorjson);
} }
struct LP_priceinfo *LP_priceinfoadd(char *symbol) struct LP_priceinfo *LP_priceinfoadd(char *symbol)
{ {
struct LP_priceinfo *pp; cJSON *retjson; struct LP_priceinfo *pp; cJSON *retjson;
if ( symbol == 0 )
return(0);
if ( LP_numpriceinfos >= sizeof(LP_priceinfos)/sizeof(*LP_priceinfos) ) if ( LP_numpriceinfos >= sizeof(LP_priceinfos)/sizeof(*LP_priceinfos) )
{ {
printf("cant add any more priceinfos\n"); 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)); safecopy(pp->symbol,symbol,sizeof(pp->symbol));
pp->coinbits = stringbits(symbol); pp->coinbits = stringbits(symbol);
pp->ind = LP_numpriceinfos++; 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; i<LP_numpriceinfos; i++)
{
printf("realloc i.%d of %d relvals.%p\n",i,LP_numpriceinfos,LP_priceinfos[i].relvals);
LP_priceinfos[i].relvals = realloc(LP_priceinfos[i].relvals,vecsize);
memset(LP_priceinfos[i].relvals,0,vecsize);
LP_priceinfos[i].myprices[LP_numpriceinfos] = 0.;
}*/
LP_numpriceinfos++; LP_numpriceinfos++;
if ( (retjson= LP_priceinfomatrix(0)) != 0 ) if ( (retjson= LP_priceinfomatrix(0)) != 0 )
free_json(retjson); free_json(retjson);
@ -236,6 +423,8 @@ struct LP_priceinfo *LP_priceinfoadd(char *symbol)
struct LP_cacheinfo *LP_cacheadd(char *base,char *rel,bits256 txid,int32_t vout,double price,struct LP_quoteinfo *qp) struct LP_cacheinfo *LP_cacheadd(char *base,char *rel,bits256 txid,int32_t vout,double price,struct LP_quoteinfo *qp)
{ {
char str[65]; struct LP_cacheinfo *ptr=0; char str[65]; struct LP_cacheinfo *ptr=0;
if ( base == 0 || rel == 0 )
return(0);
if ( (ptr= LP_cachefind(base,rel,txid,vout)) == 0 ) if ( (ptr= LP_cachefind(base,rel,txid,vout)) == 0 )
{ {
ptr = calloc(1,sizeof(*ptr)); ptr = calloc(1,sizeof(*ptr));
@ -259,99 +448,215 @@ struct LP_cacheinfo *LP_cacheadd(char *base,char *rel,bits256 txid,int32_t vout,
static int _cmp_orderbook(const void *a,const void *b) static int _cmp_orderbook(const void *a,const void *b)
{ {
#define ptr_a ((struct LP_cacheinfo *)a)->price int32_t retval = 0;
#define ptr_b ((struct LP_cacheinfo *)b)->price #define ptr_a (*(struct LP_orderbookentry **)a)->price
#define ptr_b (*(struct LP_orderbookentry **)b)->price
if ( ptr_b > ptr_a ) if ( ptr_b > ptr_a )
return(1); retval = -1;
else if ( ptr_b < ptr_a ) else if ( ptr_b < ptr_a )
return(-1); retval = 1;
else else
{ {
#undef ptr_a #undef ptr_a
#undef ptr_b #undef ptr_b
#define ptr_a ((struct LP_cacheinfo *)a)->Q.satoshis #define ptr_a ((struct LP_orderbookentry *)a)->basesatoshis
#define ptr_b ((struct LP_cacheinfo *)b)->Q.satoshis #define ptr_b ((struct LP_orderbookentry *)b)->basesatoshis
if ( ptr_b > ptr_a ) if ( ptr_b > ptr_a )
return(1);
else if ( ptr_b < ptr_a )
return(-1); 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_a
#undef ptr_b #undef ptr_b
} }
static int _cmp_orderbookrev(const void *a,const void *b) cJSON *LP_orderbookjson(struct LP_orderbookentry *op)
{
cJSON *item = cJSON_CreateObject();
if ( op->price > SMALLVAL )
{ {
return(-_cmp_orderbook(a,b)); 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(); struct LP_orderbookentry *op;
if ( ptr->Q.satoshis != 0 && ptr->Q.destsatoshis != 0 ) if ( (op= calloc(1,sizeof(*op))) != 0 )
{ {
price = (double)ptr->Q.destsatoshis / ptr->Q.satoshis; op->txid = txid;
jaddnum(item,"price",polarity > 0 ? price : 1. / price); op->vout = vout;
jaddnum(item,"volume",polarity > 0 ? dstr(ptr->Q.satoshis) : dstr(ptr->Q.destsatoshis)); op->txid2 = txid2;
jaddbits256(item,"txid",ptr->Q.txid); op->vout2 = vout2;
jaddnum(item,"vout",ptr->Q.vout); op->price = price;
op->basesatoshis = basesatoshis;
op->pubkey = pubkey;
}
return(op);
}
int32_t LP_orderbookfind(struct LP_orderbookentry **array,int32_t num,bits256 txid,int32_t vout)
{
int32_t i;
for (i=0; i<num; i++)
if ( (array[i]->vout == 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(item); }
}
return(num);
} }
char *LP_orderbook(char *base,char *rel) 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); now = (uint32_t)time(NULL);
/*struct LP_cacheinfo *ptr,*tmp;
HASH_ITER(hh,LP_cacheinfos,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; continue;
if ( strcmp(ptr->Q.srccoin,base) == 0 && strcmp(ptr->Q.destcoin,rel) == 0 ) if ( strcmp(ptr->Q.srccoin,base) == 0 && strcmp(ptr->Q.destcoin,rel) == 0 )
{ {
asks = realloc(asks,sizeof(*asks) * (numasks+1)); 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 ) else if ( strcmp(ptr->Q.srccoin,rel) == 0 && strcmp(ptr->Q.destcoin,base) == 0 )
{ {
bids = realloc(bids,sizeof(*bids) * (numbids+1)); 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(); retjson = cJSON_CreateObject();
array = cJSON_CreateArray(); array = cJSON_CreateArray();
if ( numbids > 1 ) if ( numbids > 1 )
qsort(bids,numbids,sizeof(*bids),_cmp_orderbookrev); qsort(bids,numbids,sizeof(*bids),_cmp_orderbook);
if ( numasks > 1 )
{
for (i=0; i<numasks; i++)
printf("%.8f ",asks[i]->price);
printf(" -> ");
qsort(asks,numasks,sizeof(*asks),_cmp_orderbook);
for (i=0; i<numasks; i++)
printf("%.8f ",asks[i]->price);
printf("sorted asks.%d\n",numasks);
}
for (i=0; i<numbids; i++) for (i=0; i<numbids; i++)
jaddi(array,LP_orderbookjson(bids[i],-1)); {
jaddi(array,LP_orderbookjson(bids[i]));
free(bids[i]);
bids[i] = 0;
}
jadd(retjson,"bids",array); jadd(retjson,"bids",array);
jaddnum(retjson,"numbids",numbids);
array = cJSON_CreateArray(); array = cJSON_CreateArray();
if ( numasks > 1 )
qsort(asks,numasks,sizeof(*asks),_cmp_orderbook);
for (i=0; i<numasks; i++) for (i=0; i<numasks; i++)
jaddi(array,LP_orderbookjson(asks[i],1)); {
jaddi(array,LP_orderbookjson(asks[i]));
free(asks[i]);
asks[i] = 0;
}
jadd(retjson,"asks",array); jadd(retjson,"asks",array);
jaddnum(retjson,"numasks",numasks);
jaddstr(retjson,"base",base); jaddstr(retjson,"base",base);
jaddstr(retjson,"rel",rel); jaddstr(retjson,"rel",rel);
jaddnum(retjson,"timestamp",now); jaddnum(retjson,"timestamp",now);
if ( bids != 0 )
free(bids);
if ( asks != 0 )
free(asks);
return(jprint(retjson,1)); return(jprint(retjson,1));
} }
void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32]) char *LP_pricestr(char *base,char *rel,double origprice)
{ {
LP_priceinfoupdate(base,rel,price); cJSON *retjson; double price = 0.;
}
char *LP_pricestr(char *base,char *rel)
{
double price = 0.; cJSON *retjson;
if ( base != 0 && base[0] != 0 && rel != 0 && rel[0] != 0 ) if ( base != 0 && base[0] != 0 && rel != 0 && rel[0] != 0 )
{
price = LP_price(base,rel); price = LP_price(base,rel);
if ( price != 0. ) if ( origprice > SMALLVAL && origprice < price )
price = origprice;
}
if ( price > SMALLVAL )
{ {
retjson = cJSON_CreateObject(); retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success"); jaddstr(retjson,"result","success");
jaddstr(retjson,"method","postprice");
jaddbits256(retjson,"pubkey",LP_mypubkey);
jaddstr(retjson,"base",base); jaddstr(retjson,"base",base);
jaddstr(retjson,"rel",rel); jaddstr(retjson,"rel",rel);
jaddnum(retjson,"price",price); jaddnum(retjson,"price",price);
@ -361,7 +666,24 @@ char *LP_pricestr(char *base,char *rel)
} else return(clonestr("{\"error\":\"cant find baserel pair\"}")); } 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);
}

97
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)); fprintf(fp,",\"trigger\":\"%s\"",bits256_str(str,triggertxid));
if ( bits256_nonz(swap->I.pubAm) != 0 && bits256_nonz(swap->I.pubBn) != 0 ) 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); LP_importaddress(swap->alicecoin.symbol,coinaddr);
fprintf(fp,",\"Apayment\":\"%s\"",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 ) if ( bits256_nonz(privkey) != 0 )
{ {
privAm = privkey; privAm = privkey;
printf("set privAm <- %s\n",bits256_str(str,privAm)); //printf("set privAm <- %s\n",bits256_str(str,privAm));
} }
privkey = jbits256(item,"privBn"); privkey = jbits256(item,"privBn");
if ( bits256_nonz(privkey) != 0 ) if ( bits256_nonz(privkey) != 0 )
{ {
privBn = privkey; privBn = privkey;
printf("set privBn <- %s\n",bits256_str(str,privBn)); //printf("set privBn <- %s\n",bits256_str(str,privBn));
} }
expiration = juint(item,"expiration"); expiration = juint(item,"expiration");
state = jint(item,"state"); state = jint(item,"state");
@ -554,7 +554,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
} else if ( finishedflag == 0 ) } else if ( finishedflag == 0 )
printf("%s not finished\n",fname); 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)); //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; Adestaddr[0] = destaddr[0] = 0;
Adest = Bdest = AAdest = ABdest = 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 ) if ( (alice= LP_coinfind(alicecoin)) != 0 )
{ {
bitcoin_address(Adestaddr,alice->pubtype,pubkey33,33); bitcoin_address(Adestaddr,alice->taddr,alice->pubtype,pubkey33,33);
AAdest = Adestaddr; AAdest = Adestaddr;
} }
if ( (bob= LP_coinfind(bobcoin)) != 0 ) if ( (bob= LP_coinfind(bobcoin)) != 0 )
{ {
bitcoin_address(destaddr,bob->pubtype,pubkey33,33); bitcoin_address(destaddr,bob->taddr,bob->pubtype,pubkey33,33);
Adest = destaddr; Adest = destaddr;
} }
} }
@ -581,12 +581,12 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
{ {
if ( (bob= LP_coinfind(bobcoin)) != 0 ) if ( (bob= LP_coinfind(bobcoin)) != 0 )
{ {
bitcoin_address(destaddr,bob->pubtype,pubkey33,33); bitcoin_address(destaddr,bob->taddr,bob->pubtype,pubkey33,33);
Bdest = destaddr; Bdest = destaddr;
} }
if ( (alice= LP_coinfind(alicecoin)) != 0 ) if ( (alice= LP_coinfind(alicecoin)) != 0 )
{ {
bitcoin_address(Adestaddr,alice->pubtype,pubkey33,33); bitcoin_address(Adestaddr,alice->taddr,alice->pubtype,pubkey33,33);
ABdest = Adestaddr; 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]; char privaddr[64]; uint8_t privpub33[33];
bitcoin_pubkey33(ctx,privpub33,myprivs[0]); 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])); 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++) for (j=0; j<32; j++)
rev.bytes[j] = myprivs[0].bytes[31 - 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]); printf("alicespend.(%s)\n",txbytes[BASILISK_ALICESPEND]);
} }
} }
if ( txbytes[BASILISK_ALICESPEND] != 0 ) 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 if ( bits256_nonz(txids[BASILISK_ALICESPEND]) != 0 ) // tested
{ {
sentflags[BASILISK_ALICESPEND] = 1; sentflags[BASILISK_ALICESPEND] = 1;
@ -655,13 +655,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
if ( redeemlen > 0 ) if ( redeemlen > 0 )
{ {
len = basilisk_swapuserdata(userdata,zero,1,myprivs[0],redeemscript,redeemlen); 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]); printf("privBn.(%s) aliceclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICECLAIM]);
} }
} }
if ( txbytes[BASILISK_ALICECLAIM] != 0 ) 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 if ( bits256_nonz(txids[BASILISK_ALICECLAIM]) != 0 ) // tested
{ {
sentflags[BASILISK_ALICECLAIM] = 1; 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); 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 ( 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]); printf("privBn.(%s) alicereclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICERECLAIM]);
} }
} }
if ( txbytes[BASILISK_ALICERECLAIM] != 0 ) 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 if ( bits256_nonz(txids[BASILISK_ALICERECLAIM]) != 0 ) // tested
{ {
sentflags[BASILISK_ALICERECLAIM] = 1; 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 ( 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]); printf("bobspend.(%s)\n",txbytes[BASILISK_BOBSPEND]);
} }
} }
if ( txbytes[BASILISK_BOBSPEND] != 0 ) 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 if ( bits256_nonz(txids[BASILISK_BOBSPEND]) != 0 ) // tested
{ {
sentflags[BASILISK_BOBSPEND] = 1; sentflags[BASILISK_BOBSPEND] = 1;
@ -731,7 +731,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
if ( redeemlen > 0 ) if ( redeemlen > 0 )
{ {
len = basilisk_swapuserdata(userdata,zero,1,myprivs[1],redeemscript,redeemlen); 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; int32_t z;
for (z=0; z<20; 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 ) 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 if ( bits256_nonz(txids[BASILISK_BOBRECLAIM]) != 0 ) // tested
{ {
sentflags[BASILISK_BOBRECLAIM] = 1; 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)); 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); 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); 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]); printf("pubB1.(%s) bobrefund.(%s)\n",bits256_str(str,pubB1),txbytes[BASILISK_BOBREFUND]);
} }
if ( txbytes[BASILISK_BOBREFUND] != 0 ) 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 if ( bits256_nonz(txids[BASILISK_BOBREFUND]) != 0 ) // tested
{ {
sentflags[BASILISK_BOBREFUND] = 1; sentflags[BASILISK_BOBREFUND] = 1;
@ -867,6 +867,24 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
if ( finishedflag != 0 ) if ( finishedflag != 0 )
jaddstr(item,"status","finished"); jaddstr(item,"status","finished");
else jaddstr(item,"status","pending"); 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,paymentspent), jaddbits256(item,"paymentspent",paymentspent);
bits256_str(str,Apaymentspent), jaddbits256(item,"Apaymentspent",Apaymentspent); bits256_str(str,Apaymentspent), jaddbits256(item,"Apaymentspent",Apaymentspent);
bits256_str(str,depositspent), jaddbits256(item,"depositspent",depositspent); 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 *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(KMDtotals,0,sizeof(KMDtotals));
memset(BTCtotals,0,sizeof(BTCtotals)); memset(BTCtotals,0,sizeof(BTCtotals));
//,statebits; int32_t optionduration; struct basilisk_request R; bits256 privkey; //,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 ) if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid)) != 0 )
{ {
jaddi(array,item); jaddi(array,item);
if ( 1 && (status= jstr(item,"status")) != 0 && strcmp(status,"pending") == 0 ) //if ( (status= jstr(item,"status")) != 0 && strcmp(status,"pending") == 0 )
break; // break;
} }
} }
} }
@ -949,6 +968,36 @@ char *basilisk_swaplist()
jaddi(array,linfo_json(&myinfo->linfos[i])); jaddi(array,linfo_json(&myinfo->linfos[i]));
} }
jadd(retjson,"quotes",array);*/ jadd(retjson,"quotes",array);*/
portable_mutex_unlock(&LP_swaplistmutex);
return(jprint(retjson,1)); 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; i<n; i++)
{
item = jitem(array,i);
//printf("(%s) check r%u/q%u\n",jprint(item,0),juint(item,"requestid"),juint(item,"quoteid"));
if ( juint(item,"requestid") == requestid && juint(item,"quoteid") == quoteid )
{
retstr = jprint(item,0);
break;
}
}
}
free_json(retjson);
}
free(liststr);
}
return(retstr);
}

226
iguana/exchanges/LP_rpc.c

@ -17,45 +17,167 @@
// LP_rpc.c // LP_rpc.c
// marketmaker // marketmaker
// //
char *LP_issue_curl(char *debugstr,char *destip,uint16_t port,char *url)
{
char *retstr = 0; int32_t maxerrs; struct LP_peerinfo *peer = 0;
peer = LP_peerfind((uint32_t)calc_ipbits(destip),port);
maxerrs = LP_MAXPEER_ERRORS;
if ( peer == 0 || (peer->errors < 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 *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); 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); return(LP_issue_curl("getpeers",destip,port,url));
retstr = issue_curl(url);
//printf("GETPEERS.(%s)\n",retstr);
return(retstr);
} }
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 *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]; 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); 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 *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); 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(LP_issue_curl("clientgetutxos",destip,destport,url));
return(issue_curl(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 *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); 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 *issue_LP_notifyutxo(char *destip,uint16_t destport,struct LP_utxoinfo *utxo)
{ {
char url[4096],str[65],str2[65]; char url[4096],str[65],str2[65],str3[65],*retstr; struct _LP_utxoinfo u; uint64_t val,val2;
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 ( (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&timestamp=%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 ) if ( strlen(url) > 1024 )
printf("WARNING long url.(%s)\n",url); printf("WARNING long url.(%s)\n",url);
return(issue_curl(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) 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); retjson = cJSON_Parse(retstr);
free(retstr); free(retstr);
} }
//usleep(1000);
//printf("dpow_gettxout.(%s)\n",retstr); //printf("dpow_gettxout.(%s)\n",retstr);
} } else printf("bitcoin_json cant talk to NULL coin\n");
return(retjson); return(retjson);
} }
@ -87,10 +210,16 @@ cJSON *LP_getinfo(char *symbol)
return(bitcoin_json(coin,"getinfo","[]")); 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) cJSON *LP_gettxout(char *symbol,bits256 txid,int32_t vout)
{ {
char buf[128],str[65]; struct iguana_info *coin = LP_coinfind(symbol); 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)); return(bitcoin_json(coin,"gettxout",buf));
} }
@ -101,6 +230,20 @@ cJSON *LP_gettx(char *symbol,bits256 txid)
return(bitcoin_json(coin,"getrawtransaction",buf)); 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) cJSON *LP_listunspent(char *symbol,char *coinaddr)
{ {
char buf[128]; struct iguana_info *coin = LP_coinfind(symbol); 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); sprintf(buf,"[\"%s\", \"%s\", false]",address,address);
if ( (retstr= bitcoind_passthru(symbol,coin->serverport,coin->userpass,"importaddress",buf)) != 0 ) 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); free(retstr);
} else printf("importaddress.(%s %s)\n",symbol,address); } //else printf("importaddress.(%s %s)\n",symbol,address);
return(1); return(1);
} }
double LP_getestimatedrate(char *symbol) 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 ) if ( coin != 0 )
{ {
sprintf(buf,"[%d]",3); sprintf(buf,"[%d]",3);
@ -168,7 +311,7 @@ double LP_getestimatedrate(char *symbol)
{ {
if ( retstr[0] != '-' ) if ( retstr[0] != '-' )
{ {
rate = atof(retstr) / 1024.; coin->estimatedrate = rate = atof(retstr) / 1024.;
printf("estimated rate.(%s) %s -> %.8f\n",symbol,retstr,rate); printf("estimated rate.(%s) %s -> %.8f\n",symbol,retstr,rate);
} }
free(retstr); free(retstr);
@ -185,6 +328,19 @@ uint64_t LP_txfee(char *symbol)
return(txfee); 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) char *LP_sendrawtransaction(char *symbol,char *signedtx)
{ {
cJSON *array; char *paramstr,*retstr; struct iguana_info *coin = LP_coinfind(symbol); 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); jaddistr(array,signedtx);
paramstr = jprint(array,1); paramstr = jprint(array,1);
retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"sendrawtransaction",paramstr); 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); free(paramstr);
return(retstr); return(retstr);
} }
@ -238,3 +394,31 @@ char *LP_signrawtx(char *symbol,bits256 *signedtxidp,int32_t *completedp,cJSON *
free(paramstr); free(paramstr);
return(signedtx); 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);
}

180
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)) 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; 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); swap->lasttime = (uint32_t)time(NULL);
memset(srchash.bytes,0,sizeof(srchash)); 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) 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; 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); init_hexbytes_noT(scriptstr,script,scriptlen);
basilisktag = (uint32_t)rand(); basilisktag = (uint32_t)rand();
valsobj = cJSON_CreateObject(); valsobj = cJSON_CreateObject();
jaddstr(valsobj,"coin",rawtx->coin->symbol); jaddstr(valsobj,"coin",rawtx->coin->symbol);
jaddstr(valsobj,"spendscript",scriptstr); jaddstr(valsobj,"spendscript",scriptstr);
jaddstr(valsobj,"changeaddr",rawtx->coin->changeaddr); jaddstr(valsobj,"changeaddr",rawtx->coin->smartaddr);
jadd64bits(valsobj,"satoshis",rawtx->I.amount); jadd64bits(valsobj,"satoshis",rawtx->I.amount);
if ( strcmp(rawtx->coin->symbol,"BTC") == 0 && txfee > 0 && txfee < 50000 ) if ( strcmp(rawtx->coin->symbol,"BTC") == 0 && txfee > 0 && txfee < 50000 )
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]; 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(); 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 ) if ( (n= cJSON_GetArraySize(vins)) > 0 )
{ {
for (i=0; i<n; i++) for (i=0; i<n; i++)
@ -1271,3 +1264,172 @@ int32_t bitcoin_coinptrs(bits256 pubkey,struct iguana_info **bobcoinp,struct igu
} }
portable_mutex_unlock(&myinfo->DEX_swapmutex); portable_mutex_unlock(&myinfo->DEX_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; i<n && i<sizeof(prices)/sizeof(*prices); i++)
{
item = jitem(array,i);
LP_quoteparse(&Q[i],item);
if ( (price= jdouble(item,"price")) == 0. )
{
price = LP_query("price",&Q[i],base,myutxo->coin,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<n && i<sizeof(prices)/sizeof(*prices); i++)
{
if ( (price= prices[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<n; i++)
{
item = jitem(array,i);
LP_quoteparse(&Q,item);
safecopy(coinstr,jstr(item,"base"),sizeof(coinstr));
if ( strcmp(coinstr,base) == 0 )
{
if ( LP_iseligible(1,Q.srccoin,Q.txid,Q.vout,Q.satoshis,Q.txid2,Q.vout2) != 0 )
{
if ( LP_arrayfind(retarray,Q.txid,Q.vout) < 0 )
{
jaddi(retarray,jduplicate(item));
added++;
totaladded++;
}
} else printf("ineligible.(%s)\n",jprint(item,0));
}
}
}
free_json(array);
}
free(utxostr);
}
if ( n == totaladded && added == 0 )
{
printf("n.%d totaladded.%d vs added.%d\n",n,totaladded,added);
break;
}
}
return(retarray);
}
void LP_quotesinit(char *base,char *rel)
{
cJSON *array,*item; struct LP_quoteinfo Q; bits256 zero; int32_t i,n,iter;
memset(&zero,0,sizeof(zero));
for (iter=0; iter<2; iter++)
if ( (array= LP_tradecandidates(iter == 0 ? base : rel)) != 0 )
{
//printf("candidates.(%s)\nn.%d\n",jprint(array,0),cJSON_GetArraySize(array));
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
memset(&Q,0,sizeof(Q));
for (i=0; i<n; i++)
{
item = jitem(array,i);
LP_quoteparse(&Q,item);
if ( iter == 0 )
LP_query("price",&Q,base,rel,zero);
else LP_query("price",&Q,rel,base,zero);
}
}
free_json(array);
}
}*/
/*else if ( LP_ismine(utxo) > 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);
}*/

354
iguana/exchanges/LP_swap.c

@ -17,22 +17,12 @@
// LP_swap.c // LP_swap.c
// marketmaker // 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 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 // included from basilisk.c
/* https://bitcointalk.org/index.php?topic=1340621.msg13828271#msg13828271 /* https://bitcointalk.org/index.php?topic=1340621.msg13828271#msg13828271
https://bitcointalk.org/index.php?topic=1364951 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) void basilisk_swap_finished(struct basilisk_swap *swap)
{ {
int32_t i; int32_t i;
if ( swap->utxo != 0 && swap->sentflag == 0 )
LP_availableset(swap->utxo);
swap->I.finished = (uint32_t)time(NULL); swap->I.finished = (uint32_t)time(NULL);
// save to permanent storage // save to permanent storage
basilisk_rawtx_purge(&swap->bobdeposit); 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[i].data), swap->messages[i].data = 0;
free(swap->messages), swap->messages = 0; free(swap->messages), swap->messages = 0;
swap->nummessages = 0; swap->nummessages = 0;
if ( swap->N.pair >= 0 )
nn_close(swap->N.pair), swap->N.pair = -1;
} }
uint32_t basilisk_quoteid(struct basilisk_request *rp) 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)); 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); swap->I.pubAm = bitcoin_pubkey33(swap->ctx,pubkey33,swap->I.privAm);
printf("set privAm.%s %s\n",bits256_str(str,swap->I.privAm),bits256_str(str2,*(bits256 *)swap->I.secretAm256)); printf("set privAm.%s %s\n",bits256_str(str,swap->I.privAm),bits256_str(str2,*(bits256 *)swap->I.secretAm256));
swap->bobdeposit.I.pubkey33[0] = 2;
swap->bobpayment.I.pubkey33[0] = 2;
for (i=0; i<32; i++)
swap->bobpayment.I.pubkey33[i+1] = swap->bobdeposit.I.pubkey33[i+1] = swap->I.pubA0.bytes[i];
printf("SET bobdeposit pubkey33.(02%s)\n",bits256_str(str,swap->I.pubA0));
//basilisk_bobscripts_set(swap,0); //basilisk_bobscripts_set(swap,0);
} }
return(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; void *data; int32_t datalen,retval = -1; uint32_t expiration = (uint32_t)time(NULL) + timeout;
while ( time(NULL) < expiration ) while ( time(NULL) < expiration )
{ {
//printf("start wait\n");
if ( (datalen= nn_recv(pairsock,&data,NN_MSG,0)) >= 0 ) 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); retval = (*verify)(swap,data,datalen);
nn_freemsg(data); nn_freemsg(data);
//printf("retval.%d\n",retval);
return(retval); return(retval);
} else printf("error nn_recv\n"); } // else printf("error nn_recv\n");
} }
printf("waitfor timedout\n"); printf("waitfor timedout\n");
return(retval); 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 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; int32_t datalen,sendlen,retval = -1;
printf("waitsend.%s\n",statename);
if ( LP_waitfor(pairsock,swap,timeout,verify) == 0 ) if ( LP_waitfor(pairsock,swap,timeout,verify) == 0 )
{ {
printf("waited for %s\n",statename);
if ( (datalen= (*datagen)(swap,data,maxlen)) > 0 ) if ( (datalen= (*datagen)(swap,data,maxlen)) > 0 )
{ {
if ( (sendlen= nn_send(pairsock,data,datalen,0)) == datalen ) if ( (sendlen= nn_send(pairsock,data,datalen,0)) == datalen )
{
printf("sent.%d after waitfor.%s\n",sendlen,statename);
retval = 0; retval = 0;
else printf("send %s error\n",statename); } else printf("send %s error\n",statename);
} } else printf("%s datagen no data\n",statename);
} else printf("didnt get valid data\n"); } else printf("didnt get valid data after %d\n",timeout);
return(retval); 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 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; int32_t datalen,sendlen,retval = -1;
//printf("sendwait.%s\n",statename);
if ( (datalen= (*datagen)(swap,data,maxlen)) > 0 ) if ( (datalen= (*datagen)(swap,data,maxlen)) > 0 )
{ {
//printf("generated %d for %s\n",datalen,statename);
if ( (sendlen= nn_send(pairsock,data,datalen,0)) == datalen ) 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 ) if ( LP_waitfor(pairsock,swap,timeout,verify) == 0 )
{
//printf("waited! sendwait.%s sent %d\n",statename,sendlen);
retval = 0; retval = 0;
else printf("didnt get %s\n",statename); } else printf("didnt get %s\n",statename);
} else printf("send pubkeys error\n"); } else printf("send pubkeys error\n");
} } else printf("no datagen for %s\n",statename);
return(retval); return(retval);
} }
@ -456,7 +466,7 @@ void LP_swapsfp_update(struct basilisk_request *rp)
if ( (swapsfp= fopen(fname,"rb+")) == 0 ) if ( (swapsfp= fopen(fname,"rb+")) == 0 )
swapsfp = fopen(fname,"wb+"); swapsfp = fopen(fname,"wb+");
else fseek(swapsfp,0,SEEK_END); else fseek(swapsfp,0,SEEK_END);
printf("LIST fp.%p\n",swapsfp); //printf("LIST fp.%p\n",swapsfp);
} }
if ( swapsfp != 0 ) if ( swapsfp != 0 )
{ {
@ -477,9 +487,90 @@ struct basilisk_rawtx *LP_swapdata_rawtx(struct basilisk_swap *swap,uint8_t *dat
return(0); 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),&quoteid);
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; i<rawtx->I.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; i<datalen; i++)
// printf("%02x",data[i]);
//printf(" <- received\n");
memcpy(rawtx->txbytes,data,datalen);
rawtx->I.datalen = datalen;
}
else if ( datalen != rawtx->I.datalen || memcmp(rawtx->txbytes,data,datalen) != 0 )
{
for (i=0; i<rawtx->I.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) 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 ( LP_swapdata_rawtx(swap,data,maxlen,rawtx) != 0 )
{ {
if ( bits256_nonz(rawtx->I.signedtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 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 & 0xff;
sendbuf[sendlen++] = (rawtx->I.datalen >> 8) & 0xff; sendbuf[sendlen++] = (rawtx->I.datalen >> 8) & 0xff;
sendbuf[sendlen++] = rawtx->I.redeemlen; sendbuf[sendlen++] = rawtx->I.redeemlen;
//int32_t z; for (z=0; z<rawtx->I.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); //printf("datalen.%d redeemlen.%d\n",rawtx->I.datalen,rawtx->I.redeemlen);
memcpy(&sendbuf[sendlen],rawtx->txbytes,rawtx->I.datalen), sendlen += rawtx->I.datalen; memcpy(&sendbuf[sendlen],rawtx->txbytes,rawtx->I.datalen), sendlen += rawtx->I.datalen;
if ( rawtx->I.redeemlen > 0 && rawtx->I.redeemlen < 0x100 ) 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); basilisk_dontforget_update(swap,rawtx);
//printf("sendlen.%d datalen.%d redeemlen.%d\n",sendlen,rawtx->datalen,rawtx->redeemlen); //printf("sendlen.%d datalen.%d redeemlen.%d\n",sendlen,rawtx->datalen,rawtx->redeemlen);
if ( suppress_swapsend == 0 ) 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 else
{ {
printf("suppress swapsend %x\n",msgbits); 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); return(0);
} }
void LP_bobloop(void *_utxo) int32_t LP_swapwait(uint32_t requestid,uint32_t quoteid,int32_t duration,int32_t sleeptime)
{ {
uint8_t *data; char *retstr; int32_t maxlen; uint32_t expiration; struct basilisk_swap *swap; struct LP_utxoinfo *utxo = _utxo; 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; int32_t maxlen,n; uint32_t expiration; struct basilisk_swap *swap = _swap;
fprintf(stderr,"start swap iambob\n"); fprintf(stderr,"start swap iambob\n");
maxlen = 1024*1024 + sizeof(*swap); maxlen = 1024*1024 + sizeof(*swap);
data = malloc(maxlen); data = malloc(maxlen);
expiration = (uint32_t)time(NULL) + 10; expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT;
while ( (swap= utxo->swap) == 0 && time(NULL) < expiration ) if ( swap != 0 )
sleep(1);
if ( (utxo->swap= 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"); 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"); 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"); printf("error waitsend mostprivs\n");
else if ( basilisk_bobscripts_set(swap,1,1) < 0 ) else if ( basilisk_bobscripts_set(swap,1,1) < 0 )
printf("error bobscripts deposit\n"); printf("error bobscripts deposit\n");
else 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); 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"); 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"); 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"); 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 else
{ {
printf("looping on swaplist\n"); if ( basilisk_bobscripts_set(swap,0,1) < 0 )
while ( 1 ) 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); 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));
free(retstr); 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); basilisk_swap_finished(swap);
free(utxo->swap); free(swap);
} else printf("swap timed out\n"); } 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; uint8_t *data; int32_t maxlen,n; uint32_t expiration; struct basilisk_swap *swap = _swap;
fprintf(stderr,"start swap iamalice pair.%d\n",qp->pair);
maxlen = 1024*1024 + sizeof(*swap); maxlen = 1024*1024 + sizeof(*swap);
data = malloc(maxlen); data = malloc(maxlen);
expiration = (uint32_t)time(NULL) + 10; expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT;
swap = LP_swapinit(0,0,qp->privkey,&qp->R,qp);
if ( swap != 0 ) 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"); 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"); 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"); 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"); printf("basilisk_alicetxs error\n");
else else
{ {
LP_swapsfp_update(&swap->I.req); 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"); 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"); 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"); printf("error sending alicepayment\n");
else if ( LP_waitfor(qp->pair,swap,10,LP_verify_bobpayment) < 0 ) else
{
while ( (n= LP_numconfirms(swap,&swap->alicepayment)) < 1 )
{
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"); printf("error waiting for bobpayment\n");
else else
{ {
printf("looping on swaplist\n"); while ( (n= LP_numconfirms(swap,&swap->bobpayment)) < swap->I.bobconfirms )
while ( 1 )
{ {
if ( (retstr= basilisk_swaplist()) != 0 ) 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); 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));
free(retstr); 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); basilisk_swap_finished(swap);
free(swap); free(swap);
} }
nn_close(qp->pair); free(data);
free(qp); nn_close(swap->N.pair);
} }
bits256 instantdex_derivekeypair(void *ctx,bits256 *newprivp,uint8_t pubkey[33],bits256 privkey,bits256 orderhash) 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) 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); strcpy(rawtx->name,name);
rawtx->coin = coin; rawtx->coin = coin;
strcpy(rawtx->I.coinstr,coin->symbol); 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 ) if ( strcmp(coin->symbol,"BTC") == 0 && (quoteid % 10) == 0 )
decode_hex(rawtx->I.rmd160,20,TIERNOLAN_RMD160); decode_hex(rawtx->I.rmd160,20,TIERNOLAN_RMD160);
else decode_hex(rawtx->I.rmd160,20,INSTANTDEX_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 ) if ( pubkey33 != 0 )
{ {
memcpy(rawtx->I.pubkey33,pubkey33,33); memcpy(rawtx->I.pubkey33,pubkey33,33);
bitcoin_address(rawtx->I.destaddr,rawtx->coin->pubtype,rawtx->I.pubkey33,33); bitcoin_address(rawtx->I.destaddr,rawtx->coin->taddr,rawtx->coin->pubtype,rawtx->I.pubkey33,33);
bitcoin_addr2rmd160(&rawtx->I.addrtype,rawtx->I.rmd160,rawtx->I.destaddr); bitcoin_addr2rmd160(rawtx->coin->taddr,&rawtx->I.addrtype,rawtx->I.rmd160,rawtx->I.destaddr);
} }
if ( rawtx->I.vouttype <= 1 && rawtx->I.destaddr[0] != 0 ) 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); } 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]; //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; swap->I.putduration = swap->I.callduration = INSTANTDEX_LOCKTIME;
if ( optionduration < 0 ) if ( optionduration < 0 )
swap->I.putduration -= optionduration; 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.iambob = 0;
swap->I.otherhash = swap->I.req.desthash; swap->I.otherhash = swap->I.req.desthash;
aliceistrusted = 1;
bobistrusted = LP_pubkey_istrusted(swap->I.req.desthash);
} }
else else
{ {
swap->I.iambob = 1; swap->I.iambob = 1;
swap->I.otherhash = swap->I.req.srchash; 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 ) 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 ) if ( strcmp("BTC",swap->bobcoin.symbol) == 0 )
{ {
swap->I.bobconfirms = (1*0 + sqrt(dstr(swap->I.bobsatoshis) * .1)); swap->I.bobconfirms = (1 + sqrt(dstr(swap->I.bobsatoshis) * .1));
swap->I.aliceconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.bobconfirms * 3); swap->I.aliceconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.bobconfirms);
} }
else if ( strcmp("BTC",swap->alicecoin.symbol) == 0 ) else if ( strcmp("BTC",swap->alicecoin.symbol) == 0 )
{ {
swap->I.aliceconfirms = (1*0 + sqrt(dstr(swap->I.alicesatoshis) * .1)); swap->I.aliceconfirms = (1 + sqrt(dstr(swap->I.alicesatoshis) * .1));
swap->I.bobconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.bobconfirms * 3); swap->I.bobconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.aliceconfirms);
} }
else else
{ {
swap->I.bobconfirms = BASILISK_DEFAULT_NUMCONFIRMS; swap->I.bobconfirms = BASILISK_DEFAULT_NUMCONFIRMS;
swap->I.aliceconfirms = BASILISK_DEFAULT_NUMCONFIRMS; swap->I.aliceconfirms = BASILISK_DEFAULT_NUMCONFIRMS;
} }
/*if ( swap->I.bobconfirms == 0 ) swap->I.bobconfirms *= !bobistrusted;
swap->I.bobconfirms = swap->bobcoin->chain->minconfirms; swap->I.aliceconfirms *= !aliceistrusted;
if ( swap->I.aliceconfirms == 0 ) 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);
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);
if ( swap->I.iambob != 0 ) 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("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,swap->I.alicesatoshis/INSTANTDEX_INSURANCEDIV,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; bobpub33 = pubkey33;
} }
else 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("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,swap->I.alicesatoshis/INSTANTDEX_INSURANCEDIV,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; 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("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,swap->I.bobsatoshis + (swap->I.bobsatoshis>>3),1,bobpub33,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; 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.suppress_pubkeys = 1;
swap->aliceclaim.I.locktime = swap->I.started + swap->I.putduration+swap->I.callduration + 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; swap->bobspend.I.suppress_pubkeys = 1;
basilisk_rawtx_setparms("alicereclaim",swap->I.req.quoteid,&swap->alicereclaim,&swap->alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,alicepub33,jumblrflag); basilisk_rawtx_setparms("alicereclaim",swap->I.req.quoteid,&swap->alicereclaim,&swap->alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,alicepub33,jumblrflag);
swap->alicereclaim.I.suppress_pubkeys = 1; 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); return(swap);
} }
@ -857,18 +1021,12 @@ struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256
swap->persistent_privkey = privkey; swap->persistent_privkey = privkey;
memcpy(swap->persistent_pubkey33,pubkey33,33); memcpy(swap->persistent_pubkey33,pubkey33,33);
calc_rmd160_sha256(swap->changermd160,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"); printf("error doing swapinit\n");
free(swap); free(swap);
swap = 0; 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); return(swap);
} }

583
iguana/exchanges/LP_transaction.c

File diff suppressed because it is too large

694
iguana/exchanges/LP_utxos.c

@ -18,35 +18,240 @@
// marketmaker // 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,txid.bytes,sizeof(txid));
memcpy(&key[sizeof(txid)],&vout,sizeof(vout)); 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); 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); portable_mutex_unlock(&LP_utxomutex);
return(utxo); 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; i<n; i++)
if ( ptrs[i] == utxo )
return(n);
ptrs[n++] = utxo;
return(n);
}
int32_t LP_utxocollisions(struct LP_utxoinfo *ptrs[],struct LP_utxoinfo *refutxo)
{
int32_t iambob,n = 0; struct LP_utxoinfo *utxo; struct _LP_utxoinfo u;
portable_mutex_lock(&LP_utxomutex);
for (iambob=0; iambob<=1; iambob++)
{
if ( (utxo= _LP_utxofind(iambob,refutxo->payment.txid,refutxo->payment.vout)) != 0 && utxo != refutxo )
n = LP_utxoaddptrs(ptrs,n,utxo);
if ( (utxo= _LP_utxo2find(iambob,refutxo->payment.txid,refutxo->payment.vout)) != 0 && utxo != refutxo )
n = LP_utxoaddptrs(ptrs,n,utxo);
u = (refutxo->iambob != 0) ? refutxo->deposit : refutxo->fee;
if ( (utxo= _LP_utxofind(iambob,u.txid,u.vout)) != 0 && utxo != refutxo )
n = LP_utxoaddptrs(ptrs,n,utxo);
if ( (utxo= _LP_utxo2find(iambob,u.txid,u.vout)) != 0 && utxo != refutxo )
n = LP_utxoaddptrs(ptrs,n,utxo);
}
portable_mutex_unlock(&LP_utxomutex);
if ( 0 && n > 0 )
printf("LP_utxocollisions n.%d\n",n);
return(n);
}
int32_t _LP_availableset(struct LP_utxoinfo *utxo)
{
int32_t flag = 0;
if ( utxo != 0 )
{
if ( bits256_nonz(utxo->S.otherpubkey) != 0 )
flag = 1, memset(&utxo->S.otherpubkey,0,sizeof(utxo->S.otherpubkey));
if ( utxo->S.swap != 0 )
flag = 1, utxo->S.swap = 0;
if ( utxo->T.swappending != 0 )
flag = 1, utxo->T.swappending = 0;
return(flag);
}
return(0);
}
void _LP_unavailableset(struct LP_utxoinfo *utxo,bits256 otherpubkey)
{
if ( utxo != 0 )
{
utxo->T.swappending = (uint32_t)(time(NULL) + LP_RESERVETIME);
utxo->S.otherpubkey = otherpubkey;
}
}
void LP_unavailableset(struct LP_utxoinfo *utxo,bits256 otherpubkey)
{
struct LP_utxoinfo *ptrs[8]; int32_t i,n; struct _LP_utxoinfo u;
memset(ptrs,0,sizeof(ptrs));
if ( (n= LP_utxocollisions(ptrs,utxo)) > 0 )
{
for (i=0; i<n; i++)
_LP_unavailableset(ptrs[i],otherpubkey);
}
u = (utxo->iambob != 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<n; i++)
count += _LP_availableset(ptrs[i]);
}
count += _LP_availableset(utxo);
if ( count > 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) 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); jaddstr(item,"coin",utxo->coin);
jaddnum(item,"now",time(NULL));
jaddnum(item,"iambob",utxo->iambob);
jaddstr(item,"address",utxo->coinaddr); jaddstr(item,"address",utxo->coinaddr);
jaddbits256(item,"txid",utxo->txid); jaddbits256(item,"txid",utxo->payment.txid);
jaddnum(item,"vout",utxo->vout); jaddnum(item,"vout",utxo->payment.vout);
jaddnum(item,"value",dstr(utxo->satoshis)); jadd64bits(item,"value",utxo->payment.value);
jaddbits256(item,"txid2",utxo->txid2); jadd64bits(item,"satoshis",utxo->S.satoshis);
jaddnum(item,"vout2",utxo->vout2); u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee;
jaddnum(item,"value2",dstr(utxo->satoshis2)); if ( bits256_nonz(u.txid) != 0 )
if ( utxo->swappending != 0 ) {
jaddnum(item,"pending",utxo->swappending); jaddbits256(item,"txid2",u.txid);
if ( bits256_nonz(utxo->otherpubkey) != 0 ) jaddnum(item,"vout2",u.vout);
jaddbits256(item,"desthash",utxo->otherpubkey); jadd64bits(item,"value2",u.value);
if ( utxo->pair >= 0 ) }
jaddnum(item,"socket",utxo->pair); if ( utxo->T.swappending != 0 )
if ( utxo->swap != 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"); jaddstr(item,"swap","in progress");
if ( utxo->T.spentflag != 0 )
jaddnum(item,"spent",utxo->T.spentflag);
return(item); return(item);
} }
@ -54,94 +259,276 @@ cJSON *LP_utxojson(struct LP_utxoinfo *utxo)
{ {
cJSON *item = cJSON_CreateObject(); cJSON *item = cJSON_CreateObject();
item = LP_inventoryjson(item,utxo); item = LP_inventoryjson(item,utxo);
jaddstr(item,"ipaddr",utxo->ipaddr); jaddbits256(item,"pubkey",utxo->pubkey);
jaddnum(item,"port",utxo->port); jaddnum(item,"profit",utxo->S.profitmargin);
jaddnum(item,"profit",utxo->profitmargin);
jaddstr(item,"base",utxo->coin); jaddstr(item,"base",utxo->coin);
jaddstr(item,"script",utxo->spendscript); jaddstr(item,"script",utxo->spendscript);
return(item); 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 )
{ {
int32_t i,firsti; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray(); 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,n; uint64_t val,val2; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray();
i = 0; 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; firsti = -1;
else firsti = (mypeer->numutxos - lastn); else firsti = (lastn - n);
HASH_ITER(hh,LP_utxoinfos,utxo,tmp) //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 ) if ( i++ < firsti )
continue; 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)); 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; struct LP_utxoinfo *utxo;
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 ) if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 || (utxo= LP_utxo2find(iambob,txid,vout)) != 0 )
{
//if ( utxo->T.spentflag != 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); //char str[65]; printf("prevent adding %s/v%d to inventory\n",bits256_str(str,txid),vout);
return(1);
}
}
return(0); return(0);
} }
if ( IAMCLIENT == 0 && strcmp(ipaddr,"127.0.0.1") == 0 )
struct LP_utxoinfo *LP_utxo_bestfit(char *symbol,uint64_t destsatoshis)
{ {
printf("LP node got localhost utxo\n"); struct LP_utxoinfo *utxo,*tmp,*bestutxo = 0;
if ( symbol == 0 || destsatoshis == 0 )
return(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;
}
}
return(bestutxo);
} }
if ( (utxo= LP_utxofind(txid,vout)) != 0 )
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 )
{ {
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 ) argjson = cJSON_CreateObject();
jaddstr(argjson,"method","checktxid");
jaddbits256(argjson,"txid",utxo->payment.txid);
jaddnum(argjson,"vout",utxo->payment.vout);
if ( selector != 0 )
{ {
utxo->errors++; if ( bits256_nonz(utxo->deposit.txid) != 0 )
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); 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);
} }
else if ( profitmargin != 0. )
utxo->profitmargin = profitmargin;
} }
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++)
{
if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 && utxo->T.spentflag == 0 )
{
if ( jobj(argjson,"check") == 0 )
checktxid = txid, checkvout = vout;
else 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_utxofinds(iambob,txid,vout,txid2,vout2)) != 0 )
{
if ( 0 && LP_ismine(utxo) == 0 )
{
char str2[65],str3[65]; printf("iambob.%d %s %s utxoadd.(%.8f %.8f) %s %s\n",iambob,bits256_str(str3,pubkey),symbol,dstr(value),dstr(value2),bits256_str(str,txid),bits256_str(str2,txid2));
printf("duplicate %.8f %.8f %.8f vs utxo.(%.8f %.8f %.8f)\n",dstr(value),dstr(value2),dstr(tmpsatoshis),dstr(utxo->payment.value),dstr(utxo->deposit.value),dstr(utxo->S.satoshis));
}
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee;
if ( bits256_cmp(txid,utxo->payment.txid) != 0 || bits256_cmp(txid2,u.txid) != 0 || vout != utxo->payment.vout || value != utxo->payment.value || tmpsatoshis != utxo->S.satoshis || vout2 != u.vout || value2 != u.value || strcmp(symbol,utxo->coin) != 0 || strcmp(spendscript,utxo->spendscript) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || bits256_cmp(pubkey,utxo->pubkey) != 0 )
{
utxo->T.errors++;
char str[65],str2[65],str3[65],str4[65],str5[65],str6[65];
if ( 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 > SMALLVAL )
utxo->S.profitmargin = profitmargin;
if ( utxo != 0 )
return(utxo);
}
utxo = calloc(1,sizeof(*utxo)); utxo = calloc(1,sizeof(*utxo));
utxo->pair = -1; utxo->S.profitmargin = profitmargin;
utxo->profitmargin = profitmargin; utxo->pubkey = pubkey;
strcpy(utxo->ipaddr,ipaddr); safecopy(utxo->gui,gui,sizeof(utxo->gui));
utxo->port = port; safecopy(utxo->coin,symbol,sizeof(utxo->coin));
safecopy(utxo->coin,coin,sizeof(utxo->coin));
safecopy(utxo->coinaddr,coinaddr,sizeof(utxo->coinaddr)); safecopy(utxo->coinaddr,coinaddr,sizeof(utxo->coinaddr));
safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript)); safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript));
utxo->txid = txid; utxo->payment.txid = txid;
utxo->vout = vout; utxo->payment.vout = vout;
utxo->satoshis = satoshis; utxo->payment.value = value;
utxo->txid2 = deposittxid; utxo->S.satoshis = tmpsatoshis;
utxo->vout2 = depositvout; if ( (utxo->iambob= iambob) != 0 )
utxo->satoshis2 = depositsatoshis; {
memcpy(utxo->key,txid.bytes,sizeof(txid)); utxo->deposit.txid = txid2;
memcpy(&utxo->key[sizeof(txid)],&vout,sizeof(vout)); utxo->deposit.vout = vout2;
utxo->deposit.value = value2;
}
else
{
utxo->fee.txid = txid2;
utxo->fee.vout = vout2;
utxo->fee.value = value2;
}
LP_utxosetkey(utxo->key,txid,vout);
LP_utxosetkey(utxo->key2,txid2,vout2);
portable_mutex_lock(&LP_utxomutex); portable_mutex_lock(&LP_utxomutex);
HASH_ADD_KEYPTR(hh,LP_utxoinfos,utxo->key,sizeof(utxo->key),utxo); HASH_ADD_KEYPTR(hh,LP_utxoinfos[iambob],utxo->key,sizeof(utxo->key),utxo);
if ( mypeer != 0 ) if ( _LP_utxo2find(iambob,txid2,vout2) == 0 )
mypeer->numutxos++; HASH_ADD_KEYPTR(hh2,LP_utxoinfos2[iambob],utxo->key2,sizeof(utxo->key2),utxo);
portable_mutex_unlock(&LP_utxomutex); portable_mutex_unlock(&LP_utxomutex);
if ( iambob != 0 )
{
if ( mypubsock >= 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); 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; struct LP_utxoinfo *utxo;
if ( amclient != 0 ) if ( jobj(argjson,"iambob") == 0 || iambob != jint(argjson,"iambob") )
{ {
printf("LP_utxosparse not for clientside\n"); printf("LP_utxoaddjson: iambob.%d != arg.%d obj.%p (%s)\n",iambob,jint(argjson,"iambob"),jobj(argjson,"iambob"),jprint(argjson,0));
return(-1); 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 ( (array= cJSON_Parse(retstr)) != 0 )
{ {
if ( (n= cJSON_GetArraySize(array)) > 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; subport = argport + 2;
argipbits = (uint32_t)calc_ipbits(argipaddr); argipbits = (uint32_t)calc_ipbits(argipaddr);
if ( (peer= LP_peerfind(argipbits,argport)) == 0 ) 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(0,-1,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos"));
}
if ( jobj(item,"txid") != 0 ) if ( jobj(item,"txid") != 0 )
{ {
txid = jbits256(item,"txid"); 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")); //printf("parse.(%s)\n",jprint(item,0));
if ( utxo != 0 ) if ( (utxo= LP_utxoaddjson(1,-1,item)) != 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 ) if ( (destpeer= LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport)) != 0 )
{ {
destpeer->numutxos = n; 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); free_json(array);
@ -182,29 +568,27 @@ int32_t LP_utxosparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubs
return(n); 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; char *retstr; struct LP_peerinfo *peer; uint32_t now; int32_t retval = -1;
if ( amclient != 0 )
{
printf("LP_utxosquery not for clientside\n");
return;
}
peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport);
if ( mypeer == 0 ) //(peer != 0 && peer->errors > 0) ||
return;
if ( coin == 0 ) if ( coin == 0 )
coin = ""; 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); 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); free(retstr);
i = 0; /*i = 0;
if ( lastn >= mypeer->numutxos ) if ( lastn >= mypeer->numutxos )
firsti = -1; firsti = -1;
else firsti = (mypeer->numutxos - lastn); else firsti = (mypeer->numutxos - lastn);
/*HASH_ITER(hh,LP_utxoinfos,utxo,tmp) HASH_ITER(hh,LP_utxoinfos,utxo,tmp)
{ {
if ( i++ < firsti ) if ( i++ < firsti )
continue; continue;
@ -218,22 +602,25 @@ void LP_utxosquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock
} }
if ( flag != 0 ) if ( flag != 0 )
printf(" <- missing utxos\n");*/ 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 ) if ( LP_mypeer != 0 )
myipaddr = LP_mypeer->ipaddr; myipaddr = LP_mypeer->ipaddr;
else myipaddr = "127.0.0.1"; 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)); 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) int32_t LP_maxvalue(uint64_t *values,int32_t n)
@ -265,54 +652,40 @@ int32_t LP_nearestvalue(uint64_t *values,int32_t n,uint64_t targetval)
return(mini); 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 *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;
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);
if ( coin == 0 ) if ( coin == 0 )
{ {
printf("cant add privkey for %s, coin not active\n",symbol); printf("coin not active\n");
return(0); return(0);
} }
if ( passphrase != 0 ) //printf("privkey init.(%s) %s\n",coin->symbol,coin->smartaddr);
conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); if ( coin->inactive == 0 && (array= LP_listunspent(coin->symbol,coin->smartaddr)) != 0 )
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 )
{ {
if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{ {
for (iambob=0; iambob<=1; iambob++)
{
if ( iambob == 0 )
values = calloc(n,sizeof(*values)); values = calloc(n,sizeof(*values));
else memset(values,0,n * sizeof(*values));
//if ( iambob == 0 && IAMLP != 0 )
// continue;
used = 0;
for (i=0; i<n; i++) for (i=0; i<n; i++)
{ {
item = jitem(array,i); item = jitem(array,i);
satoshis = SATOSHIDEN * jdouble(item,"amount"); satoshis = SATOSHIDEN * jdouble(item,"amount");
if ( LP_inventory_prevent(iambob,jbits256(item,"txid"),juint(item,"vout")) == 0 )
values[i] = satoshis; values[i] = satoshis;
else used++;
//printf("%.8f ",dstr(satoshis)); //printf("%.8f ",dstr(satoshis));
} }
//printf("array.%d\n",n); //printf("array.%d\n",n);
used = 0; while ( used < n-1 )
while ( used < n )
{ {
//printf("used.%d of n.%d\n",used,n);
if ( (i= LP_maxvalue(values,n)) >= 0 ) if ( (i= LP_maxvalue(values,n)) >= 0 )
{ {
item = jitem(array,i); item = jitem(array,i);
@ -321,10 +694,12 @@ uint64_t LP_privkey_init(struct LP_peerinfo *mypeer,int32_t mypubsock,char *symb
script = jstr(item,"scriptPubKey"); script = jstr(item,"scriptPubKey");
depositval = values[i]; depositval = values[i];
values[i] = 0, used++; values[i] = 0, used++;
if ( amclient != 0 ) if ( iambob == 0 )
targetval = (depositval / 776) + 50000; targetval = (depositval / 776) + 100000;
else targetval = (depositval / 9) * 8; else targetval = (depositval / 9) * 8 + 100000;
//printf("i.%d %.8f target %.8f\n",i,dstr(depositval),dstr(targetval)); //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 ) if ( (i= LP_nearestvalue(values,n,targetval)) >= 0 )
{ {
item = jitem(array,i); item = jitem(array,i);
@ -334,33 +709,88 @@ uint64_t LP_privkey_init(struct LP_peerinfo *mypeer,int32_t mypubsock,char *symb
{ {
value = values[i]; value = values[i];
values[i] = 0, used++; values[i] = 0, used++;
if ( amclient == 0 ) portable_mutex_lock(&LP_UTXOmutex);
if ( iambob != 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 ) 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 )
utxo->mypub = curve25519(privkey,curve25519_basepoint9()); {
}
} }
else else
{ {
if ( (utxo= LP_addutxo(amclient,mypeer,mypubsock,symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coinaddr,"127.0.0.1",0,0)) != 0 ) if ( (utxo= LP_utxoadd(0,mypubsock,coin->symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coin->smartaddr,mypub,0.,LP_gui)) != 0 )
utxo->mypub = curve25519(privkey,curve25519_basepoint9()); {
}
} }
portable_mutex_unlock(&LP_UTXOmutex);
total += value; total += value;
} }
} }
} else break; } else break;
} }
if ( iambob == 1 )
free(values); free(values);
} }
}
free_json(array); free_json(array);
} }
//printf("privkey.%s %.8f\n",symbol,dstr(total));
return(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; static uint32_t counter;
for (i=0; i<sizeof(activecoins)/sizeof(*activecoins); i++) bits256 privkey,userpub,userpass; char tmpstr[128]; cJSON *retjson; uint8_t tmptype,rmd160[20];
LP_privkey_init(mypeer,pubsock,activecoins[i],passphrase,"",amclient); if ( passphrase != 0 && passphrase[0] != 0 )
conv_NXTpassword(privkey.bytes,pubkeyp->bytes,(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; i<LP_numcoins; i++)
{
//printf("i.%d of %d\n",i,LP_numcoins);
if ( (coin= LP_coinfind(LP_coins[i].symbol)) != 0 )
{
if ( bits256_nonz(privkey) == 0 || coin->smartaddr[0] == 0 )
privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,coin,passphrase,"");
if ( coin->inactive == 0 && initonly == 0 )
LP_privkey_init(pubsock,coin,privkey,pubkey,pubkey33);
}
}
} }

2
iguana/exchanges/autotrade

@ -1,2 +1,2 @@
source userpass 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}"

2
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) 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 *addrtypep,uint8_t rmd160[20],char *coinaddr)

24
iguana/exchanges/client

@ -1,2 +1,24 @@
source randval 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\"}" &

22
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\"}" &

2
iguana/exchanges/getprice → iguana/exchanges/disable

@ -1,2 +1,2 @@
source userpass 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\"}"

2
iguana/exchanges/enable

@ -0,0 +1,2 @@
source userpass
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"BTC\"}"

2
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\"}"

2
iguana/exchanges/getcoins

@ -0,0 +1,2 @@
source userpass
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"getcoins\"}"

2
iguana/exchanges/getprices

@ -0,0 +1,2 @@
source userpass
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"getprices\",\"coin\":\"REVS\"}"

2
iguana/exchanges/getutxos

@ -0,0 +1,2 @@
source userpass
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"getutxos\",\"coin\":\"REVS\"}"

2
iguana/exchanges/help

@ -0,0 +1,2 @@
source userpass
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"help\"}"

2
iguana/exchanges/inv

@ -1,2 +1,2 @@
source userpass 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\"}"

2
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\"}"

7
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

89
iguana/exchanges/mm.c

@ -24,11 +24,12 @@
#include <stdint.h> #include <stdint.h>
#include "OS_portable.h" #include "OS_portable.h"
#define MAX(a,b) ((a) > (b) ? (a) : (b)) #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" #include "stats.c"
void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32]); 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/nn.h"
#include "../../crypto777/nanosrc/bus.h" #include "../../crypto777/nanosrc/bus.h"
#include "../../crypto777/nanosrc/pubsub.h" #include "../../crypto777/nanosrc/pubsub.h"
@ -70,7 +71,7 @@ char *DEX_swapstatus()
char url[512],postdata[1024]; char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL); sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"getswaplist\"}"); 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) char *DEX_amlp(char *blocktrail)
@ -78,7 +79,7 @@ char *DEX_amlp(char *blocktrail)
char url[512],postdata[1024]; char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL); sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"amlp\",\"blocktrail\":\"%s\"}",blocktrail); 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) char *DEX_openorders(char *exchange)
@ -86,7 +87,7 @@ char *DEX_openorders(char *exchange)
char url[512],postdata[1024]; char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL); sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"openorders\",\"exchange\":\"%s\"}",exchange); 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) char *DEX_tradehistory(char *exchange)
@ -94,7 +95,7 @@ char *DEX_tradehistory(char *exchange)
char url[512],postdata[1024]; char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL); sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"tradehistory\",\"exchange\":\"%s\"}",exchange); 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) char *DEX_orderstatus(char *exchange,char *orderid)
@ -102,7 +103,7 @@ char *DEX_orderstatus(char *exchange,char *orderid)
char url[512],postdata[1024]; char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL); sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"orderstatus\",\"exchange\":\"%s\",\"orderid\":\"%s\"}",exchange,orderid); 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) char *DEX_cancelorder(char *exchange,char *orderid)
@ -110,7 +111,7 @@ char *DEX_cancelorder(char *exchange,char *orderid)
char url[512],postdata[1024]; char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL); sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"cancelorder\",\"exchange\":\"%s\",\"orderid\":\"%s\"}",exchange,orderid); 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) 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 ) if ( strcmp(exchange,"DEX") == 0 )
{ {
sprintf(postdata,"{\"agent\":\"dex\",\"method\":\"getbalance\",\"address\":\"%s\",\"symbol\":\"%s\"}",coinaddr,base); 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 else
{ {
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"balance\",\"exchange\":\"%s\",\"base\":\"%s\"}",exchange,base); 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]; char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL); sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"apikeypair\",\"exchange\":\"%s\",\"apikey\":\"%s\",\"apisecret\":\"%s\"}",exchange,apikey,apisecret); 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) 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]; char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL); sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"setuserid\",\"exchange\":\"%s\",\"userid\":\"%s\",\"tradepassword\":\"%s\"}",exchange,userid,tradepassword); 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) 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(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); 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); //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) 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]; char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL); sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"withdraw\",\"exchange\":\"%s\",\"destaddr\":\"%s\",\"amount\":%.8f}",exchange,destaddr,amount); 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) 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]; char url[512],postdata[1024];
sprintf(url,"%s/coin=KMD&agent=bitcoinrpc&method=walletpassphrase?",IGUANA_URL); sprintf(url,"%s/coin=KMD&agent=bitcoinrpc&method=walletpassphrase?",IGUANA_URL);
sprintf(postdata,"[\"%s\", %d]",passphrase,timeout); 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) /*char *iguana_listunspent(char *coin,char *coinaddr)
@ -194,7 +195,7 @@ char *DEX_listunspent(char *coin,char *coinaddr)
char url[512],postdata[1024]; char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL); sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"dex\",\"method\":\"listunspent\",\"address\":\"%s\",\"symbol\":\"%s\",\"timeout\":60000}",coinaddr,coin); 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) bits256 iguana_wif2privkey(char *wifstr)
@ -203,7 +204,7 @@ bits256 iguana_wif2privkey(char *wifstr)
memset(privkey.bytes,0,sizeof(privkey)); memset(privkey.bytes,0,sizeof(privkey));
sprintf(url,"%s/?",IGUANA_URL); sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"SuperNET\",\"method\":\"wif2priv\",\"wif\":\"%s\"}",wifstr); 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 ) if ( (retjson= cJSON_Parse(retstr)) != 0 )
{ {
@ -219,28 +220,6 @@ bits256 iguana_wif2privkey(char *wifstr)
return(privkey); 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) double bittrex_balance(char *base,char *coinaddr)
{ {
char *retstr; cJSON *retjson; double balance = 0.; 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(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"%s\",\"vals\":%s}",base,jprint(vals,1)); sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"%s\",\"vals\":%s}",base,jprint(vals,1));
//printf("(%s)\n",postdata); //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); //printf("(%s) -> (%s)\n",postdata,retstr);
free(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]))); jaddnum(vals,"minvol",MAX(1,(int32_t)(vol * 0.01 * PAXPRICES[i])));
sprintf(url,"%s/?",IGUANA_URL); sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"%s\",\"vals\":%s}","KMD",jprint(vals,1)); 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); //printf("(%s) -> (%s)\n",postdata,retstr);
free(retstr); free(retstr);
@ -811,15 +790,15 @@ void LP_main(void *ptr)
if ( (passphrase= jstr(argjson,"passphrase")) != 0 ) if ( (passphrase= jstr(argjson,"passphrase")) != 0 )
{ {
profitmargin = jdouble(argjson,"profitmargin"); 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[]) int main(int argc, const char * argv[])
{ {
char *base,*rel,*name,*exchange,*apikey,*apisecret,*blocktrail,*retstr,*baseaddr,*reladdr,*passphrase; 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.; double profitmargin,maxexposure,incrratio,start_rel,start_base,minask,maxbid,incr;
cJSON *retjson,*loginjson,*matchjson; int32_t i; cJSON *retjson,*loginjson; int32_t i;
if ( argc > 1 && (retjson= cJSON_Parse(argv[1])) != 0 ) if ( argc > 1 && (retjson= cJSON_Parse(argv[1])) != 0 )
{ {
if ( (passphrase= jstr(retjson,"passphrase")) == 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)); printf("error launching LP_main (%s)\n",jprint(retjson,0));
exit(-1); exit(-1);
} else printf("(%s) launched.(%s)\n",argv[1],passphrase); } 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.; 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 ) while ( 1 )
sleep(1); sleep(1);
profitmargin = jdouble(retjson,"profitmargin"); profitmargin = jdouble(retjson,"profitmargin");

2
iguana/exchanges/myprices

@ -0,0 +1,2 @@
source userpass
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"myprices\"}"

2
iguana/exchanges/nxtae.c

@ -14,7 +14,7 @@
******************************************************************************/ ******************************************************************************/
#define DEFAULT_NXT_DEADLINE 720 #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_MSTYPE 5
#define NXT_ASSETTYPE 2 #define NXT_ASSETTYPE 2
#define NXT_GENESISTIME 1385294400 #define NXT_GENESISTIME 1385294400

2
iguana/exchanges/orderbook

@ -1,2 +1,2 @@
source userpass 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\"}"

2
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\"}"

3
iguana/exchanges/registerall

@ -0,0 +1,3 @@
source userpass
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"registerall\",\"numnodes\":10}"

19
iguana/exchanges/run

@ -1,2 +1,19 @@
source randval 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}
]}" &

17
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}
]}" &

12
iguana/exchanges/stats.c

@ -302,11 +302,15 @@ cJSON *SuperNET_urlconv(char *value,int32_t bufsize,char *urlstr)
return(json); 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) 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; static void *ctx;
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; 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); //printf("rpcparse.(%s)\n",urlstr);
if ( ctx == 0 )
ctx = bitcoin_ctx();
for (i=0; i<sizeof(urlmethod)-1&&urlstr[i]!=0&&urlstr[i]!=' '; i++) for (i=0; i<sizeof(urlmethod)-1&&urlstr[i]!=0&&urlstr[i]!=' '; i++)
urlmethod[i] = urlstr[i]; urlmethod[i] = urlstr[i];
urlmethod[i++] = 0; urlmethod[i++] = 0;
@ -489,7 +493,7 @@ char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *po
if ( userpass != 0 && jstr(argjson,"userpass") == 0 ) if ( userpass != 0 && jstr(argjson,"userpass") == 0 )
jaddstr(argjson,"userpass",userpass); jaddstr(argjson,"userpass",userpass);
//printf("after urlconv.(%s) argjson.(%s)\n",jprint(json,0),jprint(argjson,0)); //printf("after urlconv.(%s) argjson.(%s)\n",jprint(json,0),jprint(argjson,0));
if ( (retstr= stats_JSON(argjson,remoteaddr,port)) != 0 ) if ( (retstr= stats_JSON(ctx,myipaddr,-1,profitmargin,argjson,remoteaddr,port)) != 0 )
{ {
if ( (retitem= cJSON_Parse(retstr)) != 0 ) if ( (retitem= cJSON_Parse(retstr)) != 0 )
jaddi(retarray,retitem); jaddi(retarray,retitem);
@ -512,7 +516,7 @@ char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *po
//printf("ARGJSON.(%s)\n",jprint(arg,0)); //printf("ARGJSON.(%s)\n",jprint(arg,0));
if ( userpass != 0 && jstr(arg,"userpass") == 0 ) if ( userpass != 0 && jstr(arg,"userpass") == 0 )
jaddstr(arg,"userpass",userpass); jaddstr(arg,"userpass",userpass);
retstr = stats_JSON(arg,remoteaddr,port); retstr = stats_JSON(ctx,myipaddr,-1,profitmargin,arg,remoteaddr,port);
} }
free_json(argjson); free_json(argjson);
free_json(json); free_json(json);

2
iguana/exchanges/status

@ -0,0 +1,2 @@
source userpass
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"swapstatus\"}"

2
iguana/exchanges/swapstatus

@ -0,0 +1,2 @@
source userpass
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"swapstatus\",\"requestid\":2291973695,\"quoteid\":3387529385}"

2
iguana/exchanges/utxos

@ -0,0 +1,2 @@
source userpass
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"getutxos\",\"coin\":\"REVS\"}"

2
iguana/iguana_notary.c

@ -437,7 +437,7 @@ STRING_ARG(iguana,addnotary,ipaddr)
char NOTARY_CURRENCIES[][16] = { "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", char NOTARY_CURRENCIES[][16] = { "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD",
"CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", "CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK",
"REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "SHARK", "BOTS", "MGW", "MVP", "WLC", "KV", "CEAL", "MESH", "LTC" }; "REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "SHARK", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "LTC" };
ZERO_ARGS(dpow,notarychains) ZERO_ARGS(dpow,notarychains)
{ {

3
iguana/m_notary

@ -35,7 +35,8 @@ coins/jumblr_7776
coins/crypto_7776 coins/crypto_7776
coins/pangea_7776 coins/pangea_7776
coins/mgw_7776 coins/mgw_7776
coins/mvp_7776 #coins/mvp_7776
coins/coqui_7776
coins/wlc_7776 coins/wlc_7776
coins/kv_7776 coins/kv_7776
coins/ceal_7776 coins/ceal_7776

2
iguana/tests/dexlistunspent

@ -1,2 +1,2 @@
#!/bin/bash #!/bin/bash
curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"dex\",\"method\":\"listunspent\",\"address\":\"RYZx1e7kVNTuQ6RTrvTkYeZAz5uJobC3pg\",\"symbol\":\"KMD\"}" curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"dex\",\"method\":\"listunspent\",\"address\":\"RNmvQtThVZAbc1tFEFmKAnJZrc9XqciNog\",\"symbol\":\"KMD\"}"

2
includes/cJSON.h

@ -211,7 +211,7 @@ extern "C"
char *get_cJSON_fieldname(cJSON *obj); char *get_cJSON_fieldname(cJSON *obj);
void ensure_jsonitem(cJSON *json,char *field,char *value); void ensure_jsonitem(cJSON *json,char *field,char *value);
int32_t in_jsonarray(cJSON *array,char *value); int32_t in_jsonarray(cJSON *array,char *value);
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);
uint64_t calc_nxt64bits(const char *str); uint64_t calc_nxt64bits(const char *str);
int32_t expand_nxt64bits(char *str,uint64_t nxt64bits); int32_t expand_nxt64bits(char *str,uint64_t nxt64bits);
char *nxt64str(uint64_t nxt64bits); char *nxt64str(uint64_t nxt64bits);

Loading…
Cancel
Save