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. 92
      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. 213
      iguana/exchanges/LP_coins.c
  17. 753
      iguana/exchanges/LP_commands.c
  18. 349
      iguana/exchanges/LP_forwarding.c
  19. 121
      iguana/exchanges/LP_include.h
  20. 594
      iguana/exchanges/LP_nativeDEX.c
  21. 396
      iguana/exchanges/LP_network.c
  22. 690
      iguana/exchanges/LP_ordermatch.c
  23. 57
      iguana/exchanges/LP_peers.c
  24. 506
      iguana/exchanges/LP_prices.c
  25. 97
      iguana/exchanges/LP_remember.c
  26. 230
      iguana/exchanges/LP_rpc.c
  27. 180
      iguana/exchanges/LP_statemachine.c
  28. 356
      iguana/exchanges/LP_swap.c
  29. 585
      iguana/exchanges/LP_transaction.c
  30. 766
      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/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++;
}
// MVP -> USD myrequest.0 pendingid.0 noquoteflag.1 havequoteflag.0 maxi.-1 0.00000000
struct iguana_info *coin; char coinaddr[64]; double retvals[4],refprice=0.,profitmargin,aveprice,destvolume;
destvolume = dstr(maxamount);
//printf("destvolume <- %.8f\n",dstr(destvolume));

92
basilisk/jumblr.c

@ -642,16 +642,18 @@ void jumblr_utxoupdate(struct supernet_info *myinfo,char *dest,struct iguana_inf
void jumblr_iteration(struct supernet_info *myinfo,struct iguana_info *coin,int32_t selector,int32_t modval)
{
//static uint32_t lasttime;
char BTCaddr[64],KMDaddr[64],*zaddr,*retstr; bits256 privkey; uint64_t amount=0,total=0; double fee; struct jumblr_item *ptr,*tmp; uint8_t r;
char BTCaddr[64],KMDaddr[64],*zaddr,*retstr; int32_t iter,counter,chosen_one,n; bits256 privkey; uint64_t amount=0,total=0; double fee; struct jumblr_item *ptr,*tmp; uint8_t r,s;
if ( myinfo->IAMNOTARY != 0 )
return;
fee = JUMBLR_INCR * JUMBLR_FEE;
OS_randombytes(&r,sizeof(r));
//r = 0;
// randomize size chosen and order of chunks
if ( strcmp(coin->symbol,"KMD") == 0 && coin->FULLNODE < 0 )
{
s = (selector + (r>>1)) % 3;
//printf("JUMBLR selector.%d modval.%d r.%d\n",selector,modval,r&7);
switch ( selector )
switch ( s )
{
case 0: // public -> z, need to importprivkey
jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,JUMBLR_DEPOSITPREFIX);
@ -661,12 +663,14 @@ void jumblr_iteration(struct supernet_info *myinfo,struct iguana_info *coin,int3
{
if ( (zaddr= jumblr_zgetnewaddress(myinfo,coin)) != 0 )
{
amount = 0;
if ( total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE) )
amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE);
else if ( total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE) )
if ( (r & 2) != 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE) )
amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE);
else amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE);
if ( (retstr= jumblr_sendt_to_z(myinfo,coin,KMDaddr,zaddr,dstr(amount))) != 0 )
if ( (r & 4) != 0 )
amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE);
if ( amount > 0 && (retstr= jumblr_sendt_to_z(myinfo,coin,KMDaddr,zaddr,dstr(amount))) != 0 )
{
printf("sendt_to_z.(%s)\n",retstr);
free(retstr);
@ -678,24 +682,44 @@ void jumblr_iteration(struct supernet_info *myinfo,struct iguana_info *coin,int3
break;
case 1: // z -> z
jumblr_opidsupdate(myinfo,coin);
HASH_ITER(hh,myinfo->jumblrs,ptr,tmp)
chosen_one = -1;
for (iter=counter=0; iter<2; iter++)
{
if ( jumblr_addresstype(myinfo,coin,ptr->src) == 't' && jumblr_addresstype(myinfo,coin,ptr->dest) == 'z' )
counter = n = 0;
HASH_ITER(hh,myinfo->jumblrs,ptr,tmp)
{
if ( (r & 1) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN )
if ( jumblr_addresstype(myinfo,coin,ptr->src) == 't' && jumblr_addresstype(myinfo,coin,ptr->dest) == 'z' )
{
if ( (zaddr= jumblr_zgetnewaddress(myinfo,coin)) != 0 )
if ( (r & 1) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN )
{
if ( (retstr= jumblr_sendz_to_z(myinfo,coin,ptr->dest,zaddr,dstr(total))) != 0 )
if ( iter == 1 && counter == chosen_one )
{
printf("sendz_to_z.(%s)\n",retstr);
free(retstr);
if ( (zaddr= jumblr_zgetnewaddress(myinfo,coin)) != 0 )
{
if ( (retstr= jumblr_sendz_to_z(myinfo,coin,ptr->dest,zaddr,dstr(total))) != 0 )
{
printf("n.%d counter.%d chosen_one.%d sendz_to_z.(%s)\n",n,counter,chosen_one,retstr);
free(retstr);
}
ptr->spent = (uint32_t)time(NULL);
free(zaddr);
break;
}
}
ptr->spent = (uint32_t)time(NULL);
free(zaddr);
break;
counter++;
}
}
n++;
}
if ( counter == 0 )
break;
if ( iter == 0 )
{
OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one));
if ( chosen_one < 0 )
chosen_one = -chosen_one;
chosen_one %= counter;
printf("jumblr z->z chosen_one.%d of %d, from %d\n",chosen_one,counter,n);
}
}
break;
@ -703,21 +727,41 @@ void jumblr_iteration(struct supernet_info *myinfo,struct iguana_info *coin,int3
if ( myinfo->runsilent == 0 )
{
jumblr_opidsupdate(myinfo,coin);
HASH_ITER(hh,myinfo->jumblrs,ptr,tmp)
chosen_one = -1;
for (iter=0; iter<2; iter++)
{
if ( jumblr_addresstype(myinfo,coin,ptr->src) == 'z' && jumblr_addresstype(myinfo,coin,ptr->dest) == 'z' )
counter = n = 0;
HASH_ITER(hh,myinfo->jumblrs,ptr,tmp)
{
if ( (r & 1) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN )
if ( jumblr_addresstype(myinfo,coin,ptr->src) == 'z' && jumblr_addresstype(myinfo,coin,ptr->dest) == 'z' )
{
privkey = jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,"");
if ( (retstr= jumblr_sendz_to_t(myinfo,coin,ptr->dest,KMDaddr,dstr(total))) != 0 )
if ( (r & 1) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN )
{
printf("sendz_to_t.(%s)\n",retstr);
free(retstr);
if ( iter == 1 && n == chosen_one )
{
privkey = jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,"");
if ( (retstr= jumblr_sendz_to_t(myinfo,coin,ptr->dest,KMDaddr,dstr(total))) != 0 )
{
printf("sendz_to_t.(%s)\n",retstr);
free(retstr);
}
ptr->spent = (uint32_t)time(NULL);
break;
}
counter++;
}
ptr->spent = (uint32_t)time(NULL);
break;
}
n++;
}
if ( counter == 0 )
break;
if ( iter == 0 )
{
OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one));
if ( chosen_one < 0 )
chosen_one = -chosen_one;
chosen_one %= counter;
printf("jumblr z->t chosen_one.%d of %d, from %d\n",chosen_one,counter,n);
}
}
}

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 OS_thread_create pthread_create
#define issue_curl(cmdstr) bitcoind_RPC(0,"curl",cmdstr,0,0,0)
#define issue_curl(cmdstr) bitcoind_RPC(0,"curl",cmdstr,0,0,0,0)
#define issue_curlt(cmdstr,timeout) bitcoind_RPC(0,"curl",cmdstr,0,0,0,timeout)
struct allocitem { uint32_t allocsize,type; } PACKED;
struct queueitem { struct queueitem *next,*prev; uint32_t allocsize,type; } PACKED;

7
crypto777/bitcoind_RPC.c

@ -115,7 +115,7 @@ char *Jay_NXTrequest(char *command,char *params)
return(retstr);
}
char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params)
char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params,int32_t timeout)
{
static int didinit,count,count2; static double elapsedsum,elapsedsum2; extern int32_t USE_JAY;
struct curl_slist *headers = NULL; struct return_string s; CURLcode res; CURL *curl_handle;
@ -153,7 +153,8 @@ try_again:
curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback
curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash
curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback
//curl_easy_setopt(curl_handle,CURLOPT_TIMEOUT, 60L); // causes problems with iguana timeouts
if ( timeout > 0 )
curl_easy_setopt(curl_handle,CURLOPT_TIMEOUT, timeout); // causes problems with iguana timeouts
if ( strncmp(url,"https",5) == 0 )
{
curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0);
@ -201,7 +202,7 @@ try_again:
if ( res != CURLE_OK )
{
numretries++;
if ( specialcase != 0 )
if ( specialcase != 0 || timeout != 0 )
{
printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res);
free(s.ptr);

2
crypto777/nanosrc/aio/worker_posix.c

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

46
crypto777/nanosrc/core/global.c

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

4
crypto777/nanosrc/utils/efd_pipe.c

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

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

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)
{
@ -839,7 +839,7 @@ char *dpow_issuemethod(char *userpass,char *method,char *params,uint16_t port)
sprintf(url,(char *)"http://127.0.0.1:%u",port);
sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params);
//printf("postdata.(%s) USERPASS.(%s)\n",postdata,KMDUSERPASS);
retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,userpass,method,params);
retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,userpass,method,params,0);
}
return(retstr2);
}

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
char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port)
char *stats_JSON(char *myipaddr,int32_t mypubsock,double profitmargin,cJSON *argjson,char *remoteaddr,uint16_t port)
{
char *method,*agent,*retstr,*source,*dest; struct tai T; uint32_t endtimestamp; struct DEXstats_disp prices[365]; int32_t leftdatenum,seconds,numdates;
if ( (method= jstr(argjson,"method")) == 0 )

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)
{
return(bitcoind_RPC(0,coinstr,serverport,userpass,method,params));
return(bitcoind_RPC(0,coinstr,serverport,userpass,method,params,0));
}
int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr)
int32_t bitcoin_addr2rmd160(uint8_t taddr,uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr)
{
bits256 hash; uint8_t *buf,_buf[25]; int32_t len;
bits256 hash; uint8_t *buf,_buf[26]; int32_t len,offset;
offset = 1 + (taddr != 0);
memset(rmd160,0,20);
*addrtypep = 0;
buf = _buf;
if ( (len= bitcoin_base58decode(buf,coinaddr)) >= 4 )
{
// validate with trailing hash, then remove hash
hash = bits256_doublesha256(0,buf,21);
*addrtypep = *buf;
memcpy(rmd160,buf+1,20);
if ( (buf[21]&0xff) == hash.bytes[31] && (buf[22]&0xff) == hash.bytes[30] &&(buf[23]&0xff) == hash.bytes[29] && (buf[24]&0xff) == hash.bytes[28] )
hash = bits256_doublesha256(0,buf,20+offset);
*addrtypep = (taddr == 0) ? *buf : buf[1];
memcpy(rmd160,buf+offset,20);
if ( (buf[20+offset]&0xff) == hash.bytes[31] && (buf[21+offset]&0xff) == hash.bytes[30] &&(buf[22+offset]&0xff) == hash.bytes[29] && (buf[23+offset]&0xff) == hash.bytes[28] )
{
//printf("coinaddr.(%s) valid checksum addrtype.%02x\n",coinaddr,*addrtypep);
return(20);
@ -2054,61 +2055,94 @@ int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr
}
for (i=0; i<len; 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);
}
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 )
calc_rmd160_sha256(data+1,pubkey_or_rmd160,len);
else memcpy(data+1,pubkey_or_rmd160,20);
calc_rmd160_sha256(data+offset,pubkey_or_rmd160,len);
else memcpy(data+offset,pubkey_or_rmd160,20);
//btc_convrmd160(checkaddr,addrtype,data+1);
data[0] = addrtype;
hash = bits256_doublesha256(0,data,21);
if ( taddr != 0 )
{
data[0] = taddr;
data[1] = addrtype;
} else data[0] = addrtype;
hash = bits256_doublesha256(0,data,20+offset);
for (i=0; i<4; i++)
data[21+i] = hash.bytes[31-i];
if ( (coinaddr= bitcoin_base58encode(coinaddr,data,25)) != 0 )
data[20+offset+i] = hash.bytes[31-i];
if ( (coinaddr= bitcoin_base58encode(coinaddr,data,24+offset)) != 0 )
{
//uint8_t checktype,rmd160[20];
//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));
}
} else printf("null coinaddr taddr.%02x\n",taddr);
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];
if ( coinaddr == 0 || coinaddr[0] == 0 )
return(-1);
else if ( bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr) < 0 )
else if ( bitcoin_addr2rmd160(taddr,&addrtype,rmd160,coinaddr) < 0 )
return(-1);
else if ( addrtype != pubtype && addrtype != p2shtype )
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(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; bits256 hash;
data[0] = addrtype;
uint8_t i,offset; bits256 hash;
offset = 1 + (taddr != 0);
if ( taddr != 0 )
{
data[0] = taddr;
data[1] = addrtype;
} else data[0] = addrtype;
//for (i=0; i<data_len+1; i++)
// printf("%02x",data[i]);
//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++)
// printf("%02x",hash.bytes[i]);
//printf(" checkhash\n");
for (i=0; i<4; i++)
data[data_len+i+1] = hash.bytes[31-i];
return(data_len + 5);
data[data_len+i+offset] = hash.bytes[31-i];
return(data_len + 4 + offset);
}
int32_t bitcoin_wif2priv(uint8_t *addrtypep,bits256 *privkeyp,char *wifstr)
@ -2146,7 +2180,7 @@ int32_t bitcoin_priv2wif(char *wifstr,bits256 privkey,uint8_t addrtype)
uint8_t data[128]; int32_t len = 32;
memcpy(data+1,privkey.bytes,sizeof(privkey));
data[1 + len++] = 1;
len = base58encode_checkbuf(addrtype,data,len);
len = base58encode_checkbuf(0,addrtype,data,len);
if ( bitcoin_base58encode(wifstr,data,len) == 0 )
return(-1);
if ( 1 )
@ -2165,7 +2199,7 @@ int32_t bitcoin_priv2wiflong(char *wifstr,bits256 privkey,uint8_t addrtype)
{
uint8_t data[128]; int32_t len = 32;
memcpy(data+1,privkey.bytes,sizeof(privkey));
len = base58encode_checkbuf(addrtype,data,len);
len = base58encode_checkbuf(0,addrtype,data,len);
if ( bitcoin_base58encode(wifstr,data,len) == 0 )
return(-1);
if ( 1 )
@ -2180,10 +2214,10 @@ int32_t bitcoin_priv2wiflong(char *wifstr,bits256 privkey,uint8_t addrtype)
return((int32_t)strlen(wifstr));
}
bits256 LP_privkey(char *coinaddr)
bits256 LP_privkey(char *coinaddr,uint8_t taddr)
{
bits256 privkey; uint8_t addrtype,rmd160[20];
bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr);
bitcoin_addr2rmd160(taddr,&addrtype,rmd160,coinaddr);
privkey = LP_privkeyfind(rmd160);
return(privkey);
}
@ -2216,7 +2250,7 @@ uint8_t iguana_addrtype(uint8_t pubtype,uint8_t p2shtype,uint8_t script_type)
}
}
int32_t iguana_scriptgen(uint8_t pubtype,uint8_t p2shtype,int32_t *Mp,int32_t *nump,char *coinaddr,uint8_t *script,char *asmstr,uint8_t rmd160[20],uint8_t type,const struct vin_info *vp,int32_t txi)
int32_t iguana_scriptgen(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,int32_t *Mp,int32_t *nump,char *coinaddr,uint8_t *script,char *asmstr,uint8_t rmd160[20],uint8_t type,const struct vin_info *vp,int32_t txi)
{
uint8_t addrtype; char rmd160str[41],pubkeystr[256]; int32_t plen,i,m,n,flag = 0,scriptlen = 0;
m = n = 0;
@ -2226,7 +2260,7 @@ int32_t iguana_scriptgen(uint8_t pubtype,uint8_t p2shtype,int32_t *Mp,int32_t *n
if ( type == IGUANA_SCRIPT_76A988AC || type == IGUANA_SCRIPT_AC || type == IGUANA_SCRIPT_76AC || type == IGUANA_SCRIPT_P2SH )
{
init_hexbytes_noT(rmd160str,rmd160,20);
bitcoin_address(coinaddr,addrtype,rmd160,20);
bitcoin_address(coinaddr,taddr,addrtype,rmd160,20);
}
switch ( type )
{
@ -2265,7 +2299,7 @@ int32_t iguana_scriptgen(uint8_t pubtype,uint8_t p2shtype,int32_t *Mp,int32_t *n
case IGUANA_SCRIPT_OPRETURN:
if ( asmstr != 0 )
strcpy(asmstr,"OP_RETURN ");
bitcoin_address(coinaddr,addrtype,(uint8_t *)&vp->spendscript[0],vp->spendlen);
bitcoin_address(coinaddr,taddr,addrtype,(uint8_t *)&vp->spendscript[0],vp->spendlen);
flag++;
break;
case IGUANA_SCRIPT_3of3: m = 3, n = 3; break;
@ -2278,13 +2312,13 @@ int32_t iguana_scriptgen(uint8_t pubtype,uint8_t p2shtype,int32_t *Mp,int32_t *n
case IGUANA_SCRIPT_DATA:
if ( asmstr != 0 )
strcpy(asmstr,"DATA ONLY");
bitcoin_address(coinaddr,addrtype,(uint8_t *)&vp->spendscript[0],vp->spendlen);
bitcoin_address(coinaddr,taddr,addrtype,(uint8_t *)&vp->spendscript[0],vp->spendlen);
flag++;
break;
case IGUANA_SCRIPT_STRANGE:
if ( asmstr != 0 )
strcpy(asmstr,"STRANGE SCRIPT ");
bitcoin_address(coinaddr,addrtype,(uint8_t *)&vp->spendscript[0],vp->spendlen);
bitcoin_address(coinaddr,taddr,addrtype,(uint8_t *)&vp->spendscript[0],vp->spendlen);
flag++;
break;
default: break;//printf("unexpected script type.%d\n",type); break;
@ -2292,7 +2326,7 @@ int32_t iguana_scriptgen(uint8_t pubtype,uint8_t p2shtype,int32_t *Mp,int32_t *n
if ( n > 0 )
{
scriptlen = bitcoin_MofNspendscript(rmd160,script,0,vp);
bitcoin_address(coinaddr,p2shtype,script,scriptlen);
bitcoin_address(coinaddr,taddr,p2shtype,script,scriptlen);
if ( asmstr != 0 )
{
sprintf(asmstr,"%d ",m);
@ -2319,7 +2353,7 @@ int32_t iguana_scriptgen(uint8_t pubtype,uint8_t p2shtype,int32_t *Mp,int32_t *n
return(scriptlen);
}
int32_t bitcoin_scriptget(uint8_t pubtype,uint8_t p2shtype,int32_t *hashtypep,uint32_t *sigsizep,uint32_t *pubkeysizep,uint8_t **userdatap,uint32_t *userdatalenp,struct vin_info *vp,uint8_t *scriptsig,int32_t len,int32_t spendtype)
int32_t bitcoin_scriptget(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,int32_t *hashtypep,uint32_t *sigsizep,uint32_t *pubkeysizep,uint8_t **userdatap,uint32_t *userdatalenp,struct vin_info *vp,uint8_t *scriptsig,int32_t len,int32_t spendtype)
{
int32_t j,n,siglen,plen; uint8_t *p2shscript;
j = n = 0;
@ -2393,12 +2427,12 @@ int32_t bitcoin_scriptget(uint8_t pubtype,uint8_t p2shtype,int32_t *hashtypep,ui
decode_hex(vp->rmd160,20,"010966776006953d5567439e5e39f86a0d273bee");//3564a74f9ddb4372301c49154605573d7d1a88fe");
vp->type = IGUANA_SCRIPT_76A988AC;
}*/
vp->spendlen = iguana_scriptgen(pubtype,p2shtype,&vp->M,&vp->N,vp->coinaddr,vp->spendscript,0,vp->rmd160,vp->type,(const struct vin_info *)vp,vp->vin.prev_vout);
vp->spendlen = iguana_scriptgen(taddr,pubtype,p2shtype,&vp->M,&vp->N,vp->coinaddr,vp->spendscript,0,vp->rmd160,vp->type,(const struct vin_info *)vp,vp->vin.prev_vout);
//printf("type.%d asmstr.(%s) spendlen.%d\n",vp->type,asmstr,vp->spendlen);
return(vp->spendlen);
}
int32_t _iguana_calcrmd160(uint8_t pubtype,uint8_t p2shtype,struct vin_info *vp)
int32_t _iguana_calcrmd160(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,struct vin_info *vp)
{
static uint8_t zero_rmd160[20];
char hexstr[8192]; uint8_t *script,type; int32_t i,n,m,plen;
@ -2473,7 +2507,7 @@ int32_t _iguana_calcrmd160(uint8_t pubtype,uint8_t p2shtype,struct vin_info *vp)
}
memcpy(vp->signers[i].pubkey,script,plen);
calc_rmd160_sha256(vp->signers[i].rmd160,vp->signers[i].pubkey,plen);
bitcoin_address(vp->signers[i].coinaddr,pubtype,vp->signers[i].pubkey,plen);
bitcoin_address(vp->signers[i].coinaddr,taddr,pubtype,vp->signers[i].pubkey,plen);
}
if ( (int32_t)((long)script - (long)vp->spendscript) == vp->spendlen-2 )
{
@ -2526,7 +2560,7 @@ int32_t _iguana_calcrmd160(uint8_t pubtype,uint8_t p2shtype,struct vin_info *vp)
return(type);
}
int32_t iguana_calcrmd160(uint8_t pubtype,uint8_t p2shtype,char *asmstr,struct vin_info *vp,uint8_t *pk_script,int32_t pk_scriptlen,bits256 debugtxid,int32_t vout,uint32_t sequence)
int32_t iguana_calcrmd160(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,char *asmstr,struct vin_info *vp,uint8_t *pk_script,int32_t pk_scriptlen,bits256 debugtxid,int32_t vout,uint32_t sequence)
{
int32_t scriptlen; uint8_t script[IGUANA_MAXSCRIPTSIZE];
memset(vp,0,sizeof(*vp));
@ -2534,9 +2568,9 @@ int32_t iguana_calcrmd160(uint8_t pubtype,uint8_t p2shtype,char *asmstr,struct v
vp->spendlen = pk_scriptlen;
vp->vin.sequence = sequence;
memcpy(vp->spendscript,pk_script,pk_scriptlen);
if ( (vp->type= _iguana_calcrmd160(pubtype,p2shtype,vp)) >= 0 )
if ( (vp->type= _iguana_calcrmd160(taddr,pubtype,p2shtype,vp)) >= 0 )
{
scriptlen = iguana_scriptgen(pubtype,p2shtype,&vp->M,&vp->N,vp->coinaddr,script,asmstr,vp->rmd160,vp->type,(const struct vin_info *)vp,vout);
scriptlen = iguana_scriptgen(taddr,pubtype,p2shtype,&vp->M,&vp->N,vp->coinaddr,script,asmstr,vp->rmd160,vp->type,(const struct vin_info *)vp,vout);
if ( vp->M == 0 && vp->N == 0 )
{
vp->M = vp->N = 1;
@ -2578,11 +2612,11 @@ cJSON *bitcoin_txscript(char *asmstr,char **vardata,int32_t numvars)
return(scriptjson);
}
cJSON *iguana_scriptpubkeys(uint8_t pubtype,uint8_t p2shtype,uint8_t *script,int32_t scriptlen,bits256 txid,int16_t vout,uint32_t sequenceid)
cJSON *iguana_scriptpubkeys(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t *script,int32_t scriptlen,bits256 txid,int16_t vout,uint32_t sequenceid)
{
int32_t type,i,n,plen; struct vin_info V; cJSON *pubkeys; char pubkeystr[256];
pubkeys = cJSON_CreateArray();
if ( (type= iguana_calcrmd160(pubtype,p2shtype,0,&V,script,scriptlen,txid,vout,sequenceid)) >= 0 )
if ( (type= iguana_calcrmd160(taddr,pubtype,p2shtype,0,&V,script,scriptlen,txid,vout,sequenceid)) >= 0 )
{
if ( (n= V.N) == 0 )
n = 1;
@ -2634,7 +2668,7 @@ cJSON *iguana_pubkeysjson(uint8_t *pubkeyptrs[],int32_t numpubkeys)
return(pubkeysjson);
}
cJSON *bitcoin_txinput(uint8_t pubtype,uint8_t p2shtype,cJSON *txobj,bits256 txid,int32_t vout,uint32_t sequenceid,uint8_t *spendscript,int32_t spendlen,uint8_t *redeemscript,int32_t p2shlen,uint8_t *pubkeys[],int32_t numpubkeys,uint8_t *sig,int32_t siglen)
cJSON *bitcoin_txinput(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,cJSON *txobj,bits256 txid,int32_t vout,uint32_t sequenceid,uint8_t *spendscript,int32_t spendlen,uint8_t *redeemscript,int32_t p2shlen,uint8_t *pubkeys[],int32_t numpubkeys,uint8_t *sig,int32_t siglen)
{
cJSON *item,*vins; char p2shscriptstr[IGUANA_MAXSCRIPTSIZE*2+1]; uint8_t *script,len=0;
vins = jduplicate(jobj(txobj,"vin"));
@ -2654,7 +2688,7 @@ cJSON *bitcoin_txinput(uint8_t pubtype,uint8_t p2shtype,cJSON *txobj,bits256 txi
script = redeemscript, len = p2shlen;
} else script = 0;
if ( script != 0 && numpubkeys == 0 )
jadd(item,"pubkeys",iguana_scriptpubkeys(pubtype,p2shtype,script,len,txid,vout,sequenceid));
jadd(item,"pubkeys",iguana_scriptpubkeys(taddr,pubtype,p2shtype,script,len,txid,vout,sequenceid));
else if ( pubkeys != 0 && numpubkeys > 0 )
jadd(item,"pubkeys",iguana_pubkeysjson(pubkeys,numpubkeys));
jaddbits256(item,"txid",txid);
@ -2698,12 +2732,12 @@ cJSON *bitcoin_txoutput(cJSON *txobj,uint8_t *paymentscript,int32_t len,uint64_t
return(txobj);
}
int32_t bitcoin_txaddspend(uint8_t pubtype,uint8_t p2shtype,cJSON *txobj,char *destaddress,uint64_t satoshis)
int32_t bitcoin_txaddspend(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,cJSON *txobj,char *destaddress,uint64_t satoshis)
{
uint8_t outputscript[128],addrtype,rmd160[20]; int32_t scriptlen;
if ( bitcoin_validaddress(pubtype,p2shtype,destaddress) == 0 && satoshis != 0 )
if ( bitcoin_validaddress(taddr,pubtype,p2shtype,destaddress) == 0 && satoshis != 0 )
{
bitcoin_addr2rmd160(&addrtype,rmd160,destaddress);
bitcoin_addr2rmd160(taddr,&addrtype,rmd160,destaddress);
scriptlen = bitcoin_standardspend(outputscript,0,rmd160);
bitcoin_txoutput(txobj,outputscript,scriptlen,satoshis);
return(0);
@ -3130,7 +3164,7 @@ int32_t iguana_parsevoutobj(uint8_t *serialized,int32_t maxsize,struct iguana_ms
return(len);
}
cJSON *iguana_voutjson(uint8_t pubtype,uint8_t p2shtype,struct iguana_msgvout *vout,int32_t txi,bits256 txid)
cJSON *iguana_voutjson(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,struct iguana_msgvout *vout,int32_t txi,bits256 txid)
{
// 035f1321ed17d387e4433b2fa229c53616057964af065f98bfcae2233c5108055e OP_CHECKSIG
char scriptstr[IGUANA_MAXSCRIPTSIZE+1],asmstr[2*IGUANA_MAXSCRIPTSIZE+1]; int32_t i,m,n,scriptlen,asmtype; struct vin_info *vp;
@ -3143,10 +3177,10 @@ cJSON *iguana_voutjson(uint8_t pubtype,uint8_t p2shtype,struct iguana_msgvout *v
if ( vout->pk_script != 0 && vout->pk_scriptlen*2+1 < sizeof(scriptstr) )
{
memset(vp,0,sizeof(*vp));
if ( (asmtype= iguana_calcrmd160(pubtype,p2shtype,asmstr,vp,vout->pk_script,vout->pk_scriptlen,txid,txi,0xffffffff)) >= 0 )
if ( (asmtype= iguana_calcrmd160(taddr,pubtype,p2shtype,asmstr,vp,vout->pk_script,vout->pk_scriptlen,txid,txi,0xffffffff)) >= 0 )
{
skey = cJSON_CreateObject();
scriptlen = iguana_scriptgen(pubtype,p2shtype,&m,&n,vp->coinaddr,space,asmstr,vp->rmd160,asmtype,vp,txi);
scriptlen = iguana_scriptgen(taddr,pubtype,p2shtype,&m,&n,vp->coinaddr,space,asmstr,vp->rmd160,asmtype,vp,txi);
if ( asmstr[0] != 0 )
jaddstr(skey,"asm",asmstr);
addrs = cJSON_CreateArray();
@ -3223,9 +3257,9 @@ int32_t iguana_vinarray_check(cJSON *vinarray,bits256 txid,int32_t vout)
return(-1);
}
int32_t iguana_rwmsgtx(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,int32_t rwflag,cJSON *json,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,bits256 *txidp,char *vpnstr,uint8_t *extraspace,int32_t extralen,cJSON *vins,int32_t suppress_pubkeys);
int32_t iguana_rwmsgtx(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,int32_t rwflag,cJSON *json,uint8_t *serialized,int32_t maxsize,struct iguana_msgtx *msg,bits256 *txidp,char *vpnstr,uint8_t *extraspace,int32_t extralen,cJSON *vins,int32_t suppress_pubkeys);
bits256 bitcoin_sigtxid(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,uint8_t *serialized,int32_t maxlen,struct iguana_msgtx *msgtx,int32_t vini,uint8_t *spendscript,int32_t spendlen,int32_t hashtype,char *vpnstr,int32_t suppress_pubkeys)
bits256 bitcoin_sigtxid(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,uint8_t *serialized,int32_t maxlen,struct iguana_msgtx *msgtx,int32_t vini,uint8_t *spendscript,int32_t spendlen,int32_t hashtype,char *vpnstr,int32_t suppress_pubkeys)
{
int32_t i,len; bits256 sigtxid,txid,revsigtxid; struct iguana_msgtx dest;
dest = *msgtx;
@ -3259,7 +3293,7 @@ bits256 bitcoin_sigtxid(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t h
dest.vins[i].userdata = 0;
dest.vins[i].userdatalen = 0;
}
len = iguana_rwmsgtx(pubtype,p2shtype,isPoS,height,1,0,serialized,maxlen,&dest,&txid,vpnstr,0,0,0,suppress_pubkeys);
len = iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,1,0,serialized,maxlen,&dest,&txid,vpnstr,0,0,0,suppress_pubkeys);
//for (i=0; i<len; i++)
// printf("%02x",serialized[i]);
//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);
}
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;
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);
}
if ( voutarray != 0 )
jaddi(voutarray,iguana_voutjson(pubtype,p2shtype,&msg->vouts[i],i,*txidp));
jaddi(voutarray,iguana_voutjson(taddr,pubtype,p2shtype,&msg->vouts[i],i,*txidp));
}
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->lock_time),&msg->lock_time);
//printf("lock_time.%08x len.%d\n",msg->lock_time,len);
@ -3398,7 +3432,7 @@ int32_t iguana_rwmsgtx(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t he
if ( vins != 0 && jitem(vins,i) != 0 )
{
iguana_vinobjset(&msg->vins[i],jitem(vins,i),spendscript,sizeof(spendscript));
sigtxid = bitcoin_sigtxid(pubtype,p2shtype,isPoS,height,sigser,maxsize*2,msg,i,msg->vins[i].spendscript,msg->vins[i].spendlen,SIGHASH_ALL,vpnstr,suppress_pubkeys);
sigtxid = bitcoin_sigtxid(taddr,pubtype,p2shtype,isPoS,height,sigser,maxsize*2,msg,i,msg->vins[i].spendscript,msg->vins[i].spendlen,SIGHASH_ALL,vpnstr,suppress_pubkeys);
//printf("after vini.%d vinscript.%p spendscript.%p spendlen.%d (%s)\n",i,msg->vins[i].vinscript,msg->vins[i].spendscript,msg->vins[i].spendlen,jprint(jitem(vins,i),0));
if ( iguana_vinarray_check(vinarray,msg->vins[i].prev_hash,msg->vins[i].prev_vout) < 0 )
jaddi(vinarray,iguana_vinjson(&msg->vins[i],sigtxid));
@ -3495,13 +3529,13 @@ bits256 iguana_parsetxobj(uint8_t isPoS,int32_t *txstartp,uint8_t *serialized,in
return(txid);
}
char *iguana_rawtxbytes(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,cJSON *json,struct iguana_msgtx *msgtx,int32_t suppress_pubkeys)
char *iguana_rawtxbytes(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,cJSON *json,struct iguana_msgtx *msgtx,int32_t suppress_pubkeys)
{
int32_t n; char *txbytes = 0,vpnstr[64]; uint8_t *serialized;
serialized = malloc(IGUANA_MAXPACKETSIZE);
vpnstr[0] = 0;
//char str[65]; printf("%d of %d: %s\n",i,msg.txn_count,bits256_str(str,tx.txid));
if ( (n= iguana_rwmsgtx(pubtype,p2shtype,isPoS,height,1,json,serialized,IGUANA_MAXPACKETSIZE,msgtx,&msgtx->txid,vpnstr,0,0,0,suppress_pubkeys)) > 0 )
if ( (n= iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,1,json,serialized,IGUANA_MAXPACKETSIZE,msgtx,&msgtx->txid,vpnstr,0,0,0,suppress_pubkeys)) > 0 )
{
txbytes = malloc(n*2+1);
init_hexbytes_noT(txbytes,serialized,n);
@ -3529,7 +3563,7 @@ char *bitcoin_json2hex(uint8_t isPoS,bits256 *txidp,cJSON *txjson,struct vin_inf
return(txbytes);
}
cJSON *bitcoin_data2json(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys)
cJSON *bitcoin_data2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys)
{
int32_t n; char vpnstr[64]; struct iguana_msgtx M; cJSON *txobj;
if ( serialized == 0 )
@ -3540,7 +3574,7 @@ cJSON *bitcoin_data2json(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t
memset(msgtx,0,sizeof(M));
vpnstr[0] = 0;
memset(txidp,0,sizeof(*txidp));
if ( (n= iguana_rwmsgtx(pubtype,p2shtype,isPoS,height,0,txobj,serialized,len,msgtx,txidp,vpnstr,extraspace,extralen,vins,suppress_pubkeys)) <= 0 )
if ( (n= iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,0,txobj,serialized,len,msgtx,txidp,vpnstr,extraspace,extralen,vins,suppress_pubkeys)) <= 0 )
{
printf("errortxobj.(%s)\n",jprint(txobj,0));
free_json(txobj);
@ -3558,7 +3592,7 @@ cJSON *bitcoin_data2json(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t
return(txobj);
}
cJSON *bitcoin_hex2json(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,char *txbytes,uint8_t *extraspace,int32_t extralen,uint8_t *origserialized,cJSON *vins,int32_t suppress_pubkeys)
cJSON *bitcoin_hex2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,char *txbytes,uint8_t *extraspace,int32_t extralen,uint8_t *origserialized,cJSON *vins,int32_t suppress_pubkeys)
{
int32_t len; uint8_t *serialized; cJSON *txobj;
if ( txbytes == 0 )
@ -3567,7 +3601,7 @@ cJSON *bitcoin_hex2json(uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t h
if ( (serialized= origserialized) == 0 )
serialized = calloc(1,len+4096);
decode_hex(serialized,len,txbytes);
txobj = bitcoin_data2json(pubtype,p2shtype,isPoS,height,txidp,msgtx,extraspace,extralen,serialized,len,vins,suppress_pubkeys);
txobj = bitcoin_data2json(taddr,pubtype,p2shtype,isPoS,height,txidp,msgtx,extraspace,extralen,serialized,len,vins,suppress_pubkeys);
if ( serialized != origserialized )
free(serialized);
return(txobj);

213
iguana/exchanges/LP_coins.c

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

753
iguana/exchanges/LP_commands.c

@ -18,526 +18,74 @@
// marketmaker
//
struct basilisk_request *LP_requestinit(struct basilisk_request *rp,bits256 srchash,bits256 desthash,char *src,uint64_t srcsatoshis,char *dest,uint64_t destsatoshis,uint32_t timestamp,uint32_t quotetime,int32_t DEXselector)
{
struct basilisk_request R;
memset(rp,0,sizeof(*rp));
rp->srchash = srchash;
rp->srcamount = srcsatoshis;
rp->timestamp = timestamp;
rp->DEXselector = DEXselector;
safecopy(rp->src,src,sizeof(rp->src));
safecopy(rp->dest,dest,sizeof(rp->dest));
R = *rp;
rp->requestid = basilisk_requestid(rp);
rp->quotetime = quotetime;
rp->desthash = desthash;
rp->destamount = destsatoshis;
rp->quoteid = basilisk_quoteid(rp);
return(rp);
}
cJSON *LP_quotejson(struct LP_quoteinfo *qp)
{
double price; cJSON *retjson = cJSON_CreateObject();
jaddstr(retjson,"base",qp->srccoin);
jaddstr(retjson,"rel",qp->destcoin);
if ( qp->coinaddr[0] != 0 )
jaddstr(retjson,"address",qp->coinaddr);
if ( qp->timestamp != 0 )
jaddnum(retjson,"timestamp",qp->timestamp);
if ( bits256_nonz(qp->txid) != 0 )
{
jaddbits256(retjson,"txid",qp->txid);
jaddnum(retjson,"vout",qp->vout);
}
if ( bits256_nonz(qp->srchash) != 0 )
jaddbits256(retjson,"srchash",qp->srchash);
if ( qp->txfee != 0 )
jadd64bits(retjson,"txfee",qp->txfee);
if ( qp->quotetime != 0 )
jaddnum(retjson,"quotetime",qp->quotetime);
if ( qp->satoshis != 0 )
{
jadd64bits(retjson,"satoshis",qp->satoshis);
price = (double)(qp->destsatoshis+qp->desttxfee) / qp->satoshis;
jaddnum(retjson,"price",price);
}
if ( bits256_nonz(qp->desthash) != 0 )
jaddbits256(retjson,"desthash",qp->desthash);
if ( bits256_nonz(qp->txid2) != 0 )
{
jaddbits256(retjson,"txid2",qp->txid2);
jaddnum(retjson,"vout2",qp->vout2);
if ( qp->satoshis2 != 0 )
jadd64bits(retjson,"satoshis2",qp->satoshis2);
}
if ( bits256_nonz(qp->desttxid) != 0 )
{
if ( qp->destaddr[0] != 0 )
jaddstr(retjson,"destaddr",qp->destaddr);
jaddbits256(retjson,"desttxid",qp->desttxid);
jaddnum(retjson,"destvout",qp->destvout);
}
if ( bits256_nonz(qp->feetxid) != 0 )
{
jaddbits256(retjson,"feetxid",qp->feetxid);
jaddnum(retjson,"feevout",qp->feevout);
}
if ( qp->destsatoshis != 0 )
jadd64bits(retjson,"destsatoshis",qp->destsatoshis);
if ( qp->desttxfee != 0 )
jadd64bits(retjson,"desttxfee",qp->desttxfee);
if ( qp->change != 0 )
jaddnum(retjson,"change",dstr(qp->change));
return(retjson);
}
int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson)
char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port
{
safecopy(qp->srccoin,jstr(argjson,"base"),sizeof(qp->srccoin));
safecopy(qp->coinaddr,jstr(argjson,"address"),sizeof(qp->coinaddr));
safecopy(qp->destcoin,jstr(argjson,"rel"),sizeof(qp->destcoin));
safecopy(qp->destaddr,jstr(argjson,"destaddr"),sizeof(qp->destaddr));
qp->timestamp = juint(argjson,"timestamp");
qp->quotetime = juint(argjson,"quotetime");
qp->txid = jbits256(argjson,"txid");
qp->txid2 = jbits256(argjson,"txid2");
qp->vout = jint(argjson,"vout");
qp->vout2 = jint(argjson,"vout2");
qp->feevout = jint(argjson,"feevout");
qp->srchash = jbits256(argjson,"srchash");
qp->desttxid = jbits256(argjson,"desttxid");
qp->feetxid = jbits256(argjson,"feetxid");
qp->destvout = jint(argjson,"destvout");
qp->desthash = jbits256(argjson,"desthash");
if ( (qp->satoshis= j64bits(argjson,"satoshis")) == 0 )
qp->satoshis = j64bits(argjson,"value");
if ( (qp->satoshis2= j64bits(argjson,"satoshis2")) == 0 )
qp->satoshis2 = j64bits(argjson,"value2");
qp->destsatoshis = j64bits(argjson,"destsatoshis");
qp->change = SATOSHIDEN * jdouble(argjson,"change");
qp->txfee = j64bits(argjson,"txfee");
qp->desttxfee = j64bits(argjson,"desttxfee");
return(0);
}
int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char *destcoin,double price)
{
memset(qp,0,sizeof(*qp));
qp->timestamp = (uint32_t)time(NULL);
safecopy(qp->destcoin,destcoin,sizeof(qp->destcoin));
if ( (qp->txfee= LP_getestimatedrate(utxo->coin)*LP_AVETXSIZE) < 10000 )
qp->txfee = 10000;
if ( qp->txfee >= utxo->satoshis || qp->txfee >= utxo->satoshis2 )
return(-1);
qp->txid = utxo->txid;
qp->vout = utxo->vout;
qp->txid2 = utxo->txid2;
qp->vout2 = utxo->vout2;
qp->satoshis2 = utxo->satoshis2 - qp->txfee;
qp->satoshis = utxo->satoshis - qp->txfee;
qp->destsatoshis = qp->satoshis * price;
if ( (qp->desttxfee= LP_getestimatedrate(qp->destcoin) * LP_AVETXSIZE) < 10000 )
qp->desttxfee = 10000;
if ( qp->desttxfee >= qp->destsatoshis )
return(-2);
qp->destsatoshis -= qp->desttxfee;
safecopy(qp->srccoin,utxo->coin,sizeof(qp->srccoin));
safecopy(qp->coinaddr,utxo->coinaddr,sizeof(qp->coinaddr));
qp->srchash = LP_pubkey(LP_privkey(utxo->coinaddr));
return(0);
}
int32_t LP_quoteinfoset(struct LP_quoteinfo *qp,uint32_t timestamp,uint32_t quotetime,uint64_t value,uint64_t txfee,uint64_t destsatoshis,uint64_t desttxfee,bits256 desttxid,int32_t destvout,bits256 desthash,char *destaddr)
{
if ( txfee != qp->txfee )
{
if ( txfee >= value )
return(-1);
qp->txfee = txfee;
qp->satoshis = value - txfee;
}
qp->timestamp = timestamp;
qp->quotetime = quotetime;
qp->destsatoshis = destsatoshis;
qp->desttxfee = desttxfee;
qp->desttxid = desttxid;
qp->destvout = destvout;
qp->desthash = desthash;
safecopy(qp->destaddr,destaddr,sizeof(qp->destaddr));
return(0);
}
char *LP_quotereceived(cJSON *argjson)
{
struct LP_cacheinfo *ptr; double price; struct LP_quoteinfo Q;
LP_quoteparse(&Q,argjson);
price = (double)(Q.destsatoshis + Q.desttxfee) / (Q.satoshis + Q.txfee);
if ( (ptr= LP_cacheadd(Q.srccoin,Q.destcoin,Q.txid,Q.vout,price,&Q)) != 0 )
{
ptr->Q = Q;
return(clonestr("{\"result\":\"updated\"}"));
} else return(clonestr("{\"error\":\"nullptr\"}"));
}
double LP_query(char *method,struct LP_quoteinfo *qp,char *ipaddr,uint16_t port,char *base,char *rel,bits256 mypub)
{
cJSON *reqjson; struct LP_peerinfo *peer; int32_t i,flag = 0,pushsock = -1; double price = 0.;
if ( ipaddr != 0 && port >= 1000 )
{
if ( (peer= LP_peerfind((uint32_t)calc_ipbits(ipaddr),port)) == 0 )
peer = LP_addpeer(1,0,-1,ipaddr,port,port+1,port+2,0,0,0);
if ( peer != 0 )
{
if ( (pushsock= peer->pushsock) >= 0 )
{
qp->desthash = mypub;
strcpy(qp->srccoin,base);
strcpy(qp->destcoin,rel);
if ( strcmp(method,"request") == 0 )
qp->quotetime = (uint32_t)time(NULL);
reqjson = LP_quotejson(qp);
if ( bits256_nonz(qp->desthash) != 0 )
flag = 1;
jaddstr(reqjson,"method",method);
LP_send(pushsock,jprint(reqjson,1),1);
for (i=0; i<30; i++)
{
if ( (price= LP_pricecache(qp,base,rel,qp->txid,qp->vout)) != 0. )
{
if ( flag == 0 || bits256_nonz(qp->desthash) != 0 )
{
//printf("break out of loop.%d price %.8f\n",i,price);
break;
}
}
usleep(100000);
}
} else printf("no pushsock for peer.%s:%u\n",ipaddr,port);
} else printf("cant find/create peer.%s:%u\n",ipaddr,port);
}
return(price);
}
int32_t LP_sizematch(uint64_t mysatoshis,uint64_t othersatoshis)
{
if ( mysatoshis >= othersatoshis )
return(0);
else return(-1);
}
cJSON *LP_tradecandidates(struct LP_utxoinfo *myutxo,char *base)
{
struct LP_peerinfo *peer,*tmp; struct LP_quoteinfo Q; char *utxostr,coinstr[16]; cJSON *array,*icopy,*retarray=0,*item; int32_t i,n; double price; int64_t estimatedbase;
if ( (price= LP_price(base,myutxo->coin)) == .0 )
{
printf("no LP_price (%s -> %s)\n",base,myutxo->coin);
return(0);
}
estimatedbase = myutxo->satoshis / price;
printf("%s -> %s price %.8f mysatoshis %llu estimated base %llu\n",base,myutxo->coin,price,(long long)myutxo->satoshis,(long long)estimatedbase);
if ( estimatedbase <= 0 )
return(0);
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
if ( (utxostr= issue_LP_clientgetutxos(peer->ipaddr,peer->port,base,100)) != 0 )
{
//printf("%s:%u %s\n",peer->ipaddr,peer->port,utxostr);
if ( (array= cJSON_Parse(utxostr)) != 0 )
{
if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{
retarray = cJSON_CreateArray();
for (i=0; 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 )
char *method,*ipaddr,*userpass,*base,*rel,*coin,*retstr = 0; uint16_t argport=0,pushport,subport; int32_t otherpeers,othernumutxos,flag = 0; struct LP_peerinfo *peer; cJSON *retjson; struct iguana_info *ptr;
//printf("stats_JSON(%s)\n",jprint(argjson,0));
if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 )
{
printf("candidates.(%s)\n",jprint(array,0));
if ( (n= cJSON_GetArraySize(array)) > 0 )
if ( strcmp(ipaddr,"127.0.0.1") != 0 && argport >= 1000 )
{
memset(prices,0,sizeof(prices));
memset(Q,0,sizeof(Q));
for (i=0; 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. )
flag = 1;
if ( (pushport= juint(argjson,"push")) == 0 )
pushport = argport + 1;
if ( (subport= juint(argjson,"sub")) == 0 )
subport = argport + 2;
if ( (peer= LP_peerfind((uint32_t)calc_ipbits(ipaddr),argport)) != 0 )
{
bestmetric = 0.;
besti = -1;
for (i=0; i<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 )
if ( 0 && (otherpeers= jint(argjson,"numpeers")) > peer->numpeers )
peer->numpeers = otherpeers;
if ( 0 && (othernumutxos= jint(argjson,"numutxos")) > peer->numutxos )
{
i = besti;
bestprice = prices[i];
item = jitem(array,i);
bestitem = LP_quotejson(&Q[i]);
printf("bestprice %f vs maxprice %f\n",bestprice,maxprice);
if ( maxprice == 0. || bestprice <= maxprice )
{
Q[i].desttxid = myutxo->txid;
Q[i].destvout = myutxo->vout;
Q[i].feetxid = myutxo->txid2;
Q[i].feevout = myutxo->vout2;
strcpy(Q[i].destaddr,myutxo->coinaddr);
price = LP_query("request",&Q[i],jstr(item,"ipaddr"),jint(item,"port"),base,myutxo->coin,myutxo->mypub);
if ( jobj(bestitem,"price") != 0 )
jdelete(bestitem,"price");
jaddnum(bestitem,"price",prices[i]);
if ( price <= maxprice )
{
Q[i].desttxid = myutxo->txid;
Q[i].destvout = myutxo->vout;
Q[i].feetxid = myutxo->txid2;
Q[i].feevout = myutxo->vout2;
strcpy(Q[i].destaddr,myutxo->coinaddr);
price = LP_query("connect",&Q[i],jstr(item,"ipaddr"),jint(item,"port"),base,myutxo->coin,myutxo->mypub);
LP_requestinit(&R,Q[i].srchash,Q[i].desthash,base,Q[i].satoshis,Q[i].destcoin,Q[i].destsatoshis,Q[i].timestamp,Q[i].quotetime,DEXselector);
jaddstr(bestitem,"status","connected");
jaddnum(bestitem,"requestid",R.requestid);
jaddnum(bestitem,"quoteid",R.quoteid);
printf("Alice r.%u q.%u\n",R.requestid,R.quoteid);
} else jaddstr(bestitem,"status","too expensive");
}
printf("change.(%s) numutxos.%d -> %d mynumutxos.%d\n",peer->ipaddr,peer->numutxos,othernumutxos,LP_mypeer != 0 ? LP_mypeer->numutxos:0);
peer->numutxos = othernumutxos;
}
}
free_json(array);
//printf("peer.(%s) found (%d %d) (%d %d) (%s)\n",peer->ipaddr,peer->numpeers,peer->numutxos,otherpeers,othernumutxos,jprint(argjson,0));
} else LP_addpeer(LP_mypeer,LP_mypubsock,ipaddr,argport,pushport,subport,jdouble(argjson,"profit"),jint(argjson,"numpeers"),jint(argjson,"numutxos"));
}
}
if ( bestitem == 0 )
return(cJSON_Parse("{\"error\":\"no match found\"}"));
return(bestitem);
}
int32_t LP_priceping(int32_t pubsock,struct LP_utxoinfo *utxo,char *rel,double profitmargin)
{
double price; uint32_t now; cJSON *retjson; struct LP_quoteinfo Q; char *retstr;
if ( (now= (uint32_t)time(NULL)) > utxo->swappending )
utxo->swappending = 0;
if ( now > utxo->published+60 && utxo->swappending == 0 && utxo->pair < 0 && utxo->swap == 0 && (price= LP_price(utxo->coin,rel)) != 0. )
if ( (method= jstr(argjson,"method")) == 0 )
{
price *= (1. + profitmargin);
if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 )
return(-1);
Q.timestamp = (uint32_t)time(NULL);
retjson = LP_quotejson(&Q);
jaddstr(retjson,"method","quote");
retstr = jprint(retjson,1);
LP_send(pubsock,retstr,1);
utxo->published = now;
if ( flag == 0 || jobj(argjson,"result") != 0 )
printf("stats_JSON no method: (%s) (%s:%u)\n",jprint(argjson,0),ipaddr,argport);
return(0);
}
return(-1);
}
int32_t LP_command(struct LP_peerinfo *mypeer,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin)
{
char *method,*base,*rel,*retstr,pairstr[512]; cJSON *retjson; double price; bits256 privkey,txid; struct LP_utxoinfo *utxo; int32_t retval = -1,DEXselector = 0; uint64_t destvalue; struct basilisk_request R; struct LP_quoteinfo Q;
if ( IAMCLIENT == 0 && (method= jstr(argjson,"method")) != 0 )
if ( strcmp(method,"hello") == 0 )
{
txid = jbits256(argjson,"txid");
if ( (utxo= LP_utxofind(txid,jint(argjson,"vout"))) != 0 && strcmp(utxo->ipaddr,mypeer->ipaddr) == 0 && utxo->port == mypeer->port && (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 && strcmp(base,utxo->coin) == 0 )
{
//printf("LP_command.(%s)\n",jprint(argjson,0));
if ( time(NULL) > utxo->swappending )
utxo->swappending = 0;
if ( strcmp(method,"price") == 0 || strcmp(method,"request") == 0 )
{
retval = 1;
if ( utxo->swappending == 0 )
{
if ( strcmp(method,"request") == 0 && utxo->pair >= 0 )
nn_close(utxo->pair), utxo->pair = -1;
if ( (price= LP_price(base,rel)) != 0. )
{
price *= (1. + profitmargin);
if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 )
return(-1);
if ( strcmp(method,"price") == 0 )
Q.timestamp = (uint32_t)time(NULL);
retjson = LP_quotejson(&Q);
if ( strcmp(method,"request") == 0 )
{
retval |= 2;
utxo->swappending = (uint32_t)(time(NULL) + LP_RESERVETIME);
utxo->otherpubkey = jbits256(argjson,"desthash");
jaddnum(retjson,"quotetime",juint(argjson,"quotetime"));
jaddnum(retjson,"pending",utxo->swappending);
jaddbits256(retjson,"desthash",utxo->otherpubkey);
jaddstr(retjson,"method","reserved");
}
else jaddstr(retjson,"method","quote");
retstr = jprint(retjson,1);
LP_send(pubsock,retstr,1);
utxo->published = (uint32_t)time(NULL);
} else printf("null price\n");
} else printf("swappending.%u pair.%d\n",utxo->swappending,utxo->pair);
}
else if ( strcmp(method,"connect") == 0 )
{
retval = 4;
if ( utxo->pair < 0 )
{
if ( (price= LP_price(base,rel)) != 0. )
{
price *= (1. + profitmargin);
if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 )
return(-1);
if ( LP_quoteparse(&Q,argjson) < 0 )
return(-2);
//printf("connect with.(%s)\n",jprint(argjson,0));
privkey = LP_privkey(utxo->coinaddr);
if ( bits256_nonz(utxo->mypub) == 0 )
utxo->mypub = LP_pubkey(privkey);
if ( bits256_nonz(privkey) != 0 && Q.quotetime >= Q.timestamp-3 && Q.quotetime < utxo->swappending && bits256_cmp(utxo->mypub,Q.srchash) == 0 && (destvalue= LP_txvalue(rel,Q.desttxid,Q.destvout)) >= price*Q.satoshis+Q.desttxfee && destvalue >= Q.destsatoshis+Q.desttxfee )
{
Q.change = destvalue - (Q.destsatoshis+Q.desttxfee);
nanomsg_tcpname(pairstr,mypeer->ipaddr,10000+(rand() % 10000));
if ( (utxo->pair= nn_socket(AF_SP,NN_PAIR)) < 0 )
printf("error creating utxo->pair\n");
else if ( nn_bind(utxo->pair,pairstr) >= 0 )
{
//char str[65]; printf("destsatoshis %.8f %s t%u\n",dstr(Q.destsatoshis),bits256_str(str,Q.desthash),Q.quotetime);
LP_requestinit(&R,Q.srchash,Q.desthash,base,Q.satoshis,rel,Q.destsatoshis,Q.timestamp,Q.quotetime,DEXselector);
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_bobloop,(void *)utxo) == 0 )
{
retjson = LP_quotejson(&Q);
jaddstr(retjson,"method","connected");
jaddstr(retjson,"pair",pairstr);
jaddnum(retjson,"requestid",R.requestid);
jaddnum(retjson,"quoteid",R.quoteid);
retstr = jprint(retjson,1);
LP_send(pubsock,retstr,1);
utxo->swap = LP_swapinit(1,0,privkey,&R,&Q);
}
else
{
printf("error launching swaploop\n");
free(utxo->swap);
utxo->swap = 0;
nn_close(utxo->pair);
utxo->pair = -1;
}
}
else
{
printf("printf error nn_connect to %s\n",pairstr);
nn_close(utxo->pair);
utxo->pair = -1;
}
} else printf("dest %.8f < required %.8f (%d %d %d %d %d %d) %.8f %.8f\n",dstr(Q.satoshis),dstr(price*(utxo->satoshis-Q.txfee)),bits256_nonz(privkey) != 0 ,Q.timestamp == utxo->swappending-LP_RESERVETIME ,Q.quotetime >= Q.timestamp ,Q.quotetime < utxo->swappending ,bits256_cmp(utxo->mypub,Q.srchash) == 0 , LP_txvalue(rel,Q.desttxid,Q.destvout) >= price*Q.satoshis+Q.desttxfee,dstr(LP_txvalue(rel,Q.desttxid,Q.destvout)),dstr(price*Q.satoshis+Q.desttxfee));
} else printf("no price for %s/%s\n",base,rel);
} else printf("utxo->pair.%d when connect came in (%s)\n",utxo->pair,jprint(argjson,0));
}
}
}
return(retval);
}
char *LP_connected(cJSON *argjson)
{
cJSON *retjson; int32_t pairsock = -1; char *pairstr; struct LP_quoteinfo *qp; int32_t DEXselector = 0;
retjson = cJSON_CreateObject();
if ( IAMCLIENT == 0 )
jaddstr(retjson,"result","update stats");
else
{
if ( (pairstr= jstr(argjson,"pair")) == 0 || (pairsock= nn_socket(AF_SP,NN_PAIR)) < 0 )
jaddstr(retjson,"error","couldnt create pairsock");
else if ( nn_connect(pairsock,pairstr) >= 0 )
{
qp = calloc(1,sizeof(*qp));
LP_quoteparse(qp,argjson);
qp->pair = pairsock;
qp->privkey = LP_privkey(qp->destaddr);
LP_requestinit(&qp->R,qp->srchash,qp->desthash,qp->srccoin,qp->satoshis,qp->destcoin,qp->destsatoshis,qp->timestamp,qp->quotetime,DEXselector);
printf("alice pairstr.(%s)\n",pairstr);
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_aliceloop,(void *)qp) == 0 )
{
jaddstr(retjson,"result","success");
jadd(retjson,"trade",LP_quotejson(qp));
} else jaddstr(retjson,"error","couldnt aliceloop");
}
//printf("got hello from %s:%u\n",ipaddr!=0?ipaddr:"",argport);
return(0);
}
return(jprint(retjson,1));
}
// addcoin api
char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port
{
char *method,*ipaddr,*userpass,*base,*rel,*coin,*retstr = 0; uint16_t argport,pushport,subport; int32_t amclient,otherpeers,othernumutxos; struct LP_peerinfo *peer; cJSON *retjson;
if ( (method= jstr(argjson,"method")) == 0 )
return(clonestr("{\"error\":\"need method in request\"}"));
else if ( strcmp(method,"nn_tests") == 0 )
return(clonestr("{\"result\":\"success\"}"));
else if ( strcmp(method,"help") == 0 )
return(clonestr("{\"result\":\" \
available localhost RPC commands:\n \
setprice(base, rel, price)\n\
myprice(base, rel)\n\
enable(coin)\n\
disable(coin)\n\
inventory(coin)\n\
autotrade(base, rel, price, volume, timeout)\n\
swapstatus()\n\
swapstatus(requestid, quoteid)\n\
public API:\n \
getcoins()\n\
getpeers()\n\
getutxos()\n\
getutxos(coin, lastn)\n\
orderbook(base, rel)\n\
getprices(base, rel)\n\
trust(pubkey, trust)\n\
register(pubkey,pushaddr)\n\
registerall(numnodes)\n\
lookup(pubkey)\n\
forward(pubkey,method2,<argjson>)\n\
forward(pubkey,method2=publish,<argjson>)\n\
forwardhex(pubkey,hex)\n\
\"}"));
base = jstr(argjson,"base");
rel = jstr(argjson,"rel");
if ( USERPASS[0] != 0 && strcmp(remoteaddr,"127.0.0.1") == 0 && port != 0 )
{
if ( USERPASS_COUNTER == 0 )
@ -545,24 +93,31 @@ char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port
USERPASS_COUNTER = 1;
retjson = cJSON_CreateObject();
jaddstr(retjson,"userpass",USERPASS);
jaddstr(retjson,"BTC",BTCADDR);
jaddstr(retjson,"KMD",KMDADDR);
jaddbits256(retjson,"mypubkey",LP_mypubkey);
jadd(retjson,"coins",LP_coinsjson());
return(jprint(retjson,1));
}
if ( (userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,USERPASS) != 0 )
return(clonestr("{\"error\":\"authentication error\"}"));
if ( (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 )
if ( base != 0 && rel != 0 )
{
double price;
if ( LP_isdisabled(base,rel) != 0 )
return(clonestr("{\"error\":\"at least one of coins disabled\"}"));
price = jdouble(argjson,"price");
if ( strcmp(method,"setprice") == 0 )
{
if ( LP_mypriceset(base,rel,jdouble(argjson,"price")) < 0 )
return(clonestr("{\"error\":\"couldnt set price\"}"));
else return(clonestr("{\"result\":\"success\"}"));
if ( price > SMALLVAL )
{
if ( LP_mypriceset(base,rel,price) < 0 )
return(clonestr("{\"error\":\"couldnt set price\"}"));
else return(LP_pricepings(ctx,myipaddr,LP_mypubsock,profitmargin,base,rel,price * LP_profitratio));
} else return(clonestr("{\"error\":\"no price\"}"));
}
else if ( strcmp(method,"myprice") == 0 )
{
double bid,ask;
if ( LP_myprice(&bid,&ask,base,rel) != 0. )
if ( LP_myprice(&bid,&ask,base,rel) > SMALLVAL )
{
retjson = cJSON_CreateObject();
jaddstr(retjson,"base",base);
@ -572,78 +127,142 @@ char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port
return(jprint(retjson,1));
} else return(clonestr("{\"error\":\"no price set\"}"));
}
else if ( strcmp(method,"autotrade") == 0 )
{
if ( price > SMALLVAL )
{
printf("price set (%s/%s) <- %.8f\n",rel,base,1./price);
LP_mypriceset(rel,base,1./price);
return(LP_autotrade(ctx,myipaddr,pubsock,profitmargin,base,rel,price,jdouble(argjson,"volume"),jint(argjson,"timeout")));
} else return(clonestr("{\"error\":\"no price set\"}"));
}
}
else if ( (coin= jstr(argjson,"coin")) != 0 )
{
if ( strcmp(method,"inventory") == 0 )
if ( strcmp(method,"enable") == 0 )
{
LP_privkey_init(0,-1,coin,0,USERPASS_WIFSTR,1);
return(LP_inventory(coin));
if ( (ptr= LP_coinsearch(coin)) != 0 )
ptr->inactive = 0;
return(jprint(LP_coinsjson(),1));
}
else if ( IAMCLIENT != 0 && (strcmp(method,"candidates") == 0 || strcmp(method,"autotrade") == 0) )
else if ( strcmp(method,"disable") == 0 )
{
bits256 txid; int32_t vout; struct LP_utxoinfo *utxo;
txid = jbits256(argjson,"txid");
if ( bits256_nonz(txid) == 0 )
return(clonestr("{\"error\":\"invalid or missing txid\"}"));
if ( jobj(argjson,"vout") == 0 )
return(clonestr("{\"error\":\"missing vout\"}"));
vout = jint(argjson,"vout");
if ( (utxo= LP_utxofind(txid,vout)) == 0 )
return(clonestr("{\"error\":\"txid/vout not found\"}"));
if ( strcmp(method,"candidates") == 0 )
return(jprint(LP_tradecandidates(utxo,coin),1));
else return(jprint(LP_autotrade(utxo,coin,jdouble(argjson,"maxprice")),1));
if ( (ptr= LP_coinsearch(coin)) != 0 )
ptr->inactive = (uint32_t)time(NULL);
return(jprint(LP_coinsjson(),1));
}
}
}
amclient = (LP_mypeer == 0);
if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 )
{
if ( strcmp(ipaddr,"127.0.0.1") != 0 && port >= 1000 )
{
if ( (pushport= juint(argjson,"push")) == 0 )
pushport = argport + 1;
if ( (subport= juint(argjson,"sub")) == 0 )
subport = argport + 2;
if ( (peer= LP_peerfind((uint32_t)calc_ipbits(ipaddr),argport)) != 0 )
if ( LP_isdisabled(coin,0) != 0 )
return(clonestr("{\"error\":\"coin is disabled\"}"));
if ( strcmp(method,"inventory") == 0 )
{
if ( 0 && (otherpeers= jint(argjson,"numpeers")) > peer->numpeers )
peer->numpeers = otherpeers;
if ( 0 && (othernumutxos= jint(argjson,"numutxos")) > peer->numutxos )
struct iguana_info *ptr; bits256 privkey,pubkey; uint8_t pubkey33[33];
if ( (ptr= LP_coinfind(coin)) != 0 )
{
printf("change.(%s) numutxos.%d -> %d mynumutxos.%d\n",peer->ipaddr,peer->numutxos,othernumutxos,LP_mypeer != 0 ? LP_mypeer->numutxos:0);
peer->numutxos = othernumutxos;
privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,ptr,"",USERPASS_WIFSTR);
//LP_utxopurge(0);
LP_privkey_init(-1,ptr,privkey,pubkey,pubkey33);
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"coin",coin);
jaddnum(retjson,"timestamp",time(NULL));
jadd(retjson,"alice",LP_inventory(coin,0));
jadd(retjson,"bob",LP_inventory(coin,1));
return(jprint(retjson,1));
}
//printf("peer.(%s) found (%d %d) (%d %d) (%s)\n",peer->ipaddr,peer->numpeers,peer->numutxos,otherpeers,othernumutxos,jprint(argjson,0));
} else LP_addpeer(amclient,LP_mypeer,LP_mypubsock,ipaddr,argport,pushport,subport,jdouble(argjson,"profit"),jint(argjson,"numpeers"),jint(argjson,"numutxos"));
}
}
else if ( strcmp(method,"swapstatus") == 0 )
{
uint32_t requestid,quoteid;
if ( (requestid= juint(argjson,"requestid")) != 0 && (quoteid= juint(argjson,"quoteid")) != 0 )
return(basilisk_swapentry(requestid,quoteid));
else return(basilisk_swaplist());
}
else if ( strcmp(method,"myprices") == 0 )
return(LP_myprices());
else if ( strcmp(method,"trust") == 0 )
return(LP_pubkey_trustset(jbits256(argjson,"pubkey"),jint(argjson,"trust")));
}
//printf("CMD.(%s)\n",jprint(argjson,0));
if ( strcmp(method,"quote") == 0 || strcmp(method,"reserved") == 0 )
if ( LP_isdisabled(base,rel) != 0 )
retstr = clonestr("{\"error\":\"at least one of coins disabled\"}");
else if ( LP_isdisabled(jstr(argjson,"coin"),0) != 0 )
retstr = clonestr("{\"error\":\"coin is disabled\"}");
else if ( strcmp(method,"reserved") == 0 )
retstr = LP_quotereceived(argjson);
else if ( strcmp(method,"connected") == 0 )
retstr = LP_connected(argjson);
else if ( strcmp(method,"getprice") == 0 )
retstr = LP_pricestr(jstr(argjson,"base"),jstr(argjson,"rel"));
retstr = LP_connectedalice(argjson);
else if ( strcmp(method,"checktxid") == 0 )
retstr = LP_spentcheck(argjson);
else if ( strcmp(method,"getcoins") == 0 )
return(jprint(LP_coinsjson(),1));
else if ( strcmp(method,"postprice") == 0 )
retstr = LP_postedprice(argjson);
else if ( strcmp(method,"broadcast") == 0 )
retstr = LP_broadcasted(argjson);
else if ( strcmp(method,"getprices") == 0 )
return(LP_prices());
else if ( strcmp(method,"orderbook") == 0 )
retstr = LP_orderbook(jstr(argjson,"base"),jstr(argjson,"rel"));
return(LP_orderbook(base,rel));
else if ( strcmp(method,"registerall") == 0 )
return(LP_registerall(jint(argjson,"numnodes")));
else if ( strcmp(method,"forward") == 0 )
{
cJSON *reqjson;
if ( (reqjson= LP_dereference(argjson,"forward")) != 0 )
{
//printf("FORWARDED.(%s)\n",jprint(argjson,0));
if ( LP_forward(ctx,myipaddr,pubsock,profitmargin,jbits256(argjson,"pubkey"),jprint(reqjson,1),1) > 0 )
retstr = clonestr("{\"result\":\"success\"}");
else retstr = clonestr("{\"error\":\"error forwarding\"}");
} else retstr = clonestr("{\"error\":\"cant recurse forwards\"}");
}
else if ( strcmp(method,"keepalive") == 0 )
{
printf("got keepalive lag.%d switch.%u\n",(int32_t)time(NULL) - LP_deadman_switch,LP_deadman_switch);
LP_deadman_switch = (uint32_t)time(NULL);
return(clonestr("{\"result\":\"success\"}"));
}
else if ( strcmp(method,"getpeers") == 0 )
retstr = LP_peers();
else if ( IAMCLIENT == 0 && strcmp(method,"getutxos") == 0 && (coin= jstr(argjson,"coin")) != 0 )
retstr = LP_utxos(LP_mypeer,coin,jint(argjson,"lastn"));
else if ( IAMCLIENT == 0 && strcmp(method,"notify") == 0 )
retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}");
else if ( IAMCLIENT == 0 && strcmp(method,"notifyutxo") == 0 )
return(LP_peers());
else if ( strcmp(method,"getutxos") == 0 )
return(LP_utxos(1,LP_mypeer,jstr(argjson,"coin"),jint(argjson,"lastn")));
else if ( strcmp(method,"notified") == 0 )
{
printf("utxonotify.(%s)\n",jprint(argjson,0));
LP_addutxo(amclient,LP_mypeer,LP_mypubsock,jstr(argjson,"coin"),jbits256(argjson,"txid"),jint(argjson,"vout"),SATOSHIDEN * jdouble(argjson,"value"),jbits256(argjson,"txid2"),jint(argjson,"vout2"),SATOSHIDEN * jdouble(argjson,"value2"),jstr(argjson,"script"),jstr(argjson,"address"),jstr(argjson,"ipaddr"),juint(argjson,"port"),jdouble(argjson,"profit"));
retstr = clonestr("{\"result\":\"success\",\"notifyutxo\":\"received\"}");
if ( LP_utxoaddjson(1,LP_mypubsock,argjson) != 0 )
return(clonestr("{\"result\":\"success\",\"notifyutxo\":\"received\"}"));
else return(clonestr("{\"error\":\"couldnt add utxo\"}"));
}
else if ( IAMLP != 0 )
{
if ( strcmp(method,"register") == 0 )
{
retstr = LP_register(jbits256(argjson,"client"),jstr(argjson,"pushaddr"),juint(argjson,"pushport"));
//printf("got (%s) from register\n",retstr!=0?retstr:"");
return(retstr);
}
else if ( strcmp(method,"lookup") == 0 )
return(LP_lookup(jbits256(argjson,"client")));
else if ( strcmp(method,"forwardhex") == 0 )
retstr = LP_forwardhex(ctx,pubsock,jbits256(argjson,"pubkey"),jstr(argjson,"hex"));
else if ( strcmp(method,"psock") == 0 )
{
if ( myipaddr == 0 || myipaddr[0] == 0 || strcmp(myipaddr,"127.0.0.1") == 0 )
{
if ( LP_mypeer != 0 )
myipaddr = LP_mypeer->ipaddr;
else printf("LP_psock dont have actual ipaddr?\n");
}
return(LP_psock(myipaddr,jint(argjson,"ispaired")));
}
else if ( strcmp(method,"notify") == 0 )
retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}");
}
if ( retstr != 0 )
return(retstr);
retjson = cJSON_CreateObject();
jaddstr(retjson,"error","unrecognized command");
{
free(retstr);
return(0);
}
printf("ERROR.(%s)\n",jprint(argjson,0));
return(clonestr(jprint(retjson,1)));
return(0);
}

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\"}"));
}

121
iguana/exchanges/LP_include.h

@ -21,6 +21,29 @@
#ifndef LP_INCLUDE_H
#define LP_INCLUDE_H
#define LP_COMMAND_SENDSOCK NN_PUSH
#define LP_COMMAND_RECVSOCK NN_PULL
#define LP_MAXPUBKEY_ERRORS 3
#define PSOCK_KEEPALIVE 3600
#define MAINLOOP_PERSEC 10
#define MAX_PSOCK_PORT 60000
#define MIN_PSOCK_PORT 10000
#define LP_HTTP_TIMEOUT 2 // 1 is too small due to edge cases of time(NULL)
#define LP_MAXPEER_ERRORS 3
#define LP_MINPEER_GOOD 20
#define LP_PEERGOOD_ERRORDECAY 0.9
#define LP_SWAPSTEP_TIMEOUT 3
#define LP_AUTOTRADE_TIMEOUT 3
#define LP_MIN_TXFEE 10000
#define LP_MINVOL 3
#define LP_MINCLIENTVOL 6
#define LP_DEXFEE(destsatoshis) ((destsatoshis) / INSTANTDEX_INSURANCEDIV)
#define LP_DEPOSITSATOSHIS(satoshis) ((satoshis) + (satoshis >> 3))
#define INSTANTDEX_DECKSIZE 1000
#define INSTANTDEX_LOCKTIME (3600*2 + 300*2)
#define INSTANTDEX_INSURANCEDIV 777
@ -31,19 +54,19 @@
#define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu"
#define INSTANTDEX_BTCD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf"
#define BASILISK_DISABLEWAITTX
#define BASILISK_DISABLESENDTX
//#define BASILISK_DISABLEWAITTX
//#define BASILISK_DISABLESENDTX
#define LP_PROPAGATION_SLACK 10 // txid ordering is not enforced, so getting extra recent txid
#define LP_PROPAGATION_SLACK 100 // txid ordering is not enforced, so getting extra recent txid
#define LP_RESERVETIME 60
#define LP_AVETXSIZE 200
#define LP_CACHEDURATION 60
#define BASILISK_DEFAULT_NUMCONFIRMS 5
#define BASILISK_DEFAULT_NUMCONFIRMS 1
#define DEX_SLEEP 3
#define BASILISK_KEYSIZE ((int32_t)(2*sizeof(bits256)+sizeof(uint32_t)*2))
extern char GLOBAL_DBDIR[],USERPASS[],USERPASS_WIFSTR[];
extern int32_t IAMCLIENT,USERPASS_COUNTER;
extern int32_t IAMLP,USERPASS_COUNTER;
struct iguana_msgvin { bits256 prev_hash; uint8_t *vinscript,*userdata,*spendscript,*redeemscript; uint32_t prev_vout,sequence; uint16_t scriptlen,p2shlen,userdatalen,spendlen; };
@ -136,41 +159,34 @@ struct basilisk_swapinfo
struct iguana_info
{
uint64_t txfee; double estimatedrate;
int32_t longestchain;
uint8_t pubtype,p2shtype,isPoS,wiftype;
char symbol[16],changeaddr[64],userpass[1024],serverport[128];
uint64_t txfee; double estimatedrate,profitmargin;
int32_t longestchain; uint32_t counter,inactive;
uint8_t pubtype,p2shtype,isPoS,wiftype,taddr;
char symbol[16],smartaddr[64],userpass[1024],serverport[128];
};
struct basilisk_swap
{
void *ctx; struct iguana_info bobcoin,alicecoin;
void (*balancingtrade)(struct basilisk_swap *swap,int32_t iambob);
int32_t subsock,pushsock,connected,aliceunconf,depositunconf,paymentunconf; uint32_t lasttime,aborted;
FILE *fp;
bits256 persistent_privkey,persistent_pubkey;
struct basilisk_swapinfo I;
struct basilisk_rawtx bobdeposit,bobpayment,alicepayment,myfee,otherfee,aliceclaim,alicespend,bobreclaim,bobspend,bobrefund,alicereclaim;
bits256 privkeys[INSTANTDEX_DECKSIZE];
struct basilisk_swapmessage *messages; int32_t nummessages;
char Bdeposit[64],Bpayment[64];
uint64_t otherdeck[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2];
uint8_t persistent_pubkey33[33],changermd160[20],pad[15],verifybuf[65536];
};
struct _LP_utxoinfo { bits256 txid; uint64_t value; int32_t vout; };
struct LP_utxostats { uint32_t lasttime,errors,swappending,spentflag,lastspentcheck,bestflag; };
struct LP_utxobob { struct _LP_utxoinfo utxo,deposit; };
struct LP_utxoalice { struct _LP_utxoinfo utxo,fee; };
struct LP_utxoswap { bits256 otherpubkey; void *swap; uint64_t satoshis; double profitmargin; };
struct LP_utxoinfo
{
UT_hash_handle hh;
bits256 txid,txid2,feetxid,otherpubkey,mypub;
void *swap;
uint64_t satoshis,satoshis2;
UT_hash_handle hh,hh2;
bits256 pubkey;
struct _LP_utxoinfo payment,deposit,fee;
struct LP_utxostats T;
struct LP_utxoswap S;
//struct LP_utxonetwork N;
int32_t iambob,iamlp;
uint8_t key[sizeof(bits256) + sizeof(int32_t)];
int32_t vout,vout2,pair;
uint32_t lasttime,errors,swappending,published;
double profitmargin;
char ipaddr[64],coinaddr[64],spendscript[256],coin[16];
uint16_t port;
uint8_t key2[sizeof(bits256) + sizeof(int32_t)];
char coin[16],coinaddr[64],spendscript[256],gui[16];
};
struct LP_peerinfo
@ -178,7 +194,7 @@ struct LP_peerinfo
UT_hash_handle hh;
uint64_t ip_port;
double profitmargin;
uint32_t ipbits,errortime,errors,numpeers,numutxos,lasttime,connected;
uint32_t ipbits,errortime,errors,numpeers,numutxos,lasttime,connected,lastutxos,lastpeers,diduquery,good;
int32_t pushsock,subsock;
uint16_t port;
char ipaddr[64];
@ -188,16 +204,49 @@ struct LP_quoteinfo
{
struct basilisk_request R;
bits256 srchash,desthash,txid,txid2,desttxid,feetxid,privkey;
uint64_t satoshis,satoshis2,txfee,destsatoshis,desttxfee,change;
uint64_t satoshis,txfee,destsatoshis,desttxfee;
uint32_t timestamp,quotetime; int32_t vout,vout2,destvout,feevout,pair;
char srccoin[16],coinaddr[64],destcoin[16],destaddr[64];
};
struct LP_endpoint { int32_t pair; char ipaddr[64]; uint16_t port; };
struct basilisk_swap
{
void *ctx; struct iguana_info bobcoin,alicecoin; struct LP_utxoinfo *utxo;
struct LP_endpoint N;
void (*balancingtrade)(struct basilisk_swap *swap,int32_t iambob);
int32_t subsock,pushsock,connected,aliceunconf,depositunconf,paymentunconf; uint32_t lasttime,aborted;
FILE *fp;
bits256 persistent_privkey,persistent_pubkey;
struct basilisk_swapinfo I;
struct basilisk_rawtx bobdeposit,bobpayment,alicepayment,myfee,otherfee,aliceclaim,alicespend,bobreclaim,bobspend,bobrefund,alicereclaim;
bits256 privkeys[INSTANTDEX_DECKSIZE];
struct basilisk_swapmessage *messages; int32_t nummessages,sentflag;
char Bdeposit[64],Bpayment[64];
uint64_t otherdeck[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2];
uint8_t persistent_pubkey33[33],changermd160[20],pad[15],verifybuf[65536];
};
void basilisk_dontforget_update(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx);
uint32_t basilisk_requestid(struct basilisk_request *rp);
uint32_t basilisk_quoteid(struct basilisk_request *rp);
struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp);
char *bitcoind_passthru(char *coinstr,char *serverport,char *userpass,char *method,char *params);
uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx,uint32_t nextbits,int32_t suppress_swapsend);
//double LP_query(char *method,struct LP_quoteinfo *qp,char *base,char *rel,bits256 mypub);
int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys);
void LP_quotesinit(char *base,char *rel);
int32_t LP_forward(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,bits256 pubkey,char *jsonstr,int32_t freeflag);
int32_t LP_ismine(struct LP_utxoinfo *utxo);
int32_t LP_isavailable(struct LP_utxoinfo *utxo);
struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port);
char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin);
void LP_availableset(struct LP_utxoinfo *utxo);
int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2,bits256 pubkey);
int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsock,int32_t pullsock,double profitmargin);
uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired);
#endif

594
iguana/exchanges/LP_nativeDEX.c

@ -17,33 +17,32 @@
// LP_nativeDEX.c
// marketmaker
//
// jl777: fix price calcs based on specific txfees
#include <stdio.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"
struct LP_utxoinfo *LP_utxoinfos;
struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2];
struct LP_peerinfo *LP_peerinfos,*LP_mypeer;
struct LP_forwardinfo *LP_forwardinfos;
char *activecoins[] = { "BTC", "KMD", "REVS", "JUMBLR" };//"LTC", "USD", };
char *activecoins[] = { "BTC", "KMD" };
char GLOBAL_DBDIR[] = { "DB" };
char USERPASS[65],USERPASS_WIFSTR[64],BTCADDR[64],KMDADDR[64],USERHOME[512] = { "/root" };
char USERPASS[65],USERPASS_WIFSTR[64],LP_myipaddr[64],LP_publicaddr[64],USERHOME[512] = { "/root" };
char LP_gui[16] = { "cli" };
char *default_LPnodes[] = { "5.9.253.196", "5.9.253.197", "5.9.253.198", "5.9.253.199", "5.9.253.200", "5.9.253.201", "5.9.253.202", "5.9.253.203", "5.9.253.204" }; //"5.9.253.195",
char *default_LPnodes[] = { "5.9.253.195", "5.9.253.196", "5.9.253.197", "5.9.253.198", "5.9.253.199", "5.9.253.200", "5.9.253.201", "5.9.253.202", "5.9.253.203", };//"5.9.253.204" }; //
portable_mutex_t LP_peermutex,LP_utxomutex,LP_commandmutex,LP_cachemutex;
uint32_t LP_deadman_switch;
uint16_t LP_fixed_pairport,LP_publicport;
int32_t LP_mypubsock = -1;
int32_t Client_connections;
int32_t USERPASS_COUNTER,IAMCLIENT = 0;
int32_t USERPASS_COUNTER,IAMLP = 0;
double LP_profitratio = 1.;
bits256 LP_mypubkey;
// stubs
int32_t basilisk_istrustedbob(struct basilisk_swap *swap)
{
// for BTC and if trusted LP
return(0);
}
void tradebot_swap_balancingtrade(struct basilisk_swap *swap,int32_t iambob)
{
@ -54,6 +53,7 @@ void tradebot_pendingadd(cJSON *tradejson,char *base,double basevolume,char *rel
{
// add to trades
}
char *LP_getdatadir()
{
return(USERHOME);
@ -74,229 +74,451 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_
#include "LP_swap.c"
#include "LP_peers.c"
#include "LP_utxos.c"
#include "LP_forwarding.c"
#include "LP_ordermatch.c"
#include "LP_commands.c"
void LP_mainloop(struct LP_peerinfo *mypeer,uint16_t mypubport,int32_t pubsock,int32_t pullsock,uint16_t myport,int32_t amclient,char *passphrase,double profitmargin)
char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin)
{
//static uint16_t tmpport;
char *retstr; uint8_t r; int32_t i,n,j,len,recvsize,counter=0,nonz,lastn; struct LP_peerinfo *peer,*tmp; struct LP_utxoinfo *utxo,*utmp; void *ptr; cJSON *argjson;
if ( amclient == 0 )
char *retstr=0;
if ( jobj(argjson,"result") != 0 || jobj(argjson,"error") != 0 )
return(0);
if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,data,datalen,profitmargin) <= 0 )
{
for (i=0; i<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 )
continue;
LP_peersquery(amclient,mypeer,pubsock,default_LPnodes[i],myport,mypeer->ipaddr,myport,profitmargin);
//printf("%s PULL.[%d]-> (%s)\n",myipaddr != 0 ? myipaddr : "127.0.0.1",datalen,retstr);
if ( pubsock >= 0 ) //strncmp("{\"error\":",retstr,strlen("{\"error\":")) != 0 &&
LP_send(pubsock,retstr,(int32_t)strlen(retstr)+1,0);
}
}
else
return(retstr);
}
char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock,double profitmargin,void *ptr,int32_t recvlen,int32_t recvsock)
{
int32_t len,datalen=0; char *msg,*retstr=0,*jsonstr=0; cJSON *argjson,*reqjson;
if ( (datalen= is_hexstr((char *)ptr,0)) > 0 )
{
OS_randombytes((void *)&r,sizeof(r));
for (j=0; j<sizeof(default_LPnodes)/sizeof(*default_LPnodes); j++)
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 )
{
}
}
else if ( jstr(argjson,"method") != 0 && strcmp(jstr(argjson,"method"),"publish") == 0 )
{
printf("got publish\n");
if ( jobj(argjson,"method2") != 0 )
jdelete(argjson,"method2");
jaddstr(argjson,"method2","broadcast");
if ( pubsock >= 0 && (reqjson= LP_dereference(argjson,"publish")) != 0 )
{
msg = jprint(reqjson,1);
LP_send(pubsock,msg,(int32_t)strlen(msg)+1,1);
}
}
else if ( (retstr= LP_command_process(ctx,myipaddr,pubsock,argjson,&((uint8_t *)ptr)[len],recvlen - len,profitmargin)) != 0 )
{
i = (r + j) % (sizeof(default_LPnodes)/sizeof(*default_LPnodes));
LP_peersquery(amclient,mypeer,pubsock,default_LPnodes[i],myport,"127.0.0.1",myport,profitmargin);
}
portable_mutex_unlock(&LP_commandmutex);
if ( LP_COMMAND_RECVSOCK == NN_REP )
{
if ( retstr != 0 )
{
if ( strcmp("PULL",typestr) == 0 )
{
printf("%d got REQ.(%s) -> (%s)\n",recvsock,jprint(argjson,0),retstr);
LP_send(recvsock,retstr,(int32_t)strlen(retstr)+1,0);
}
}
else if ( strcmp("PULL",typestr) == 0 )
{
printf("%d got REQ.(%s) -> null\n",recvsock,jprint(argjson,0));
LP_send(recvsock,"{\"result\":null}",(int32_t)strlen("{\"result\":null}")+1,0);
}
}
free_json(argjson);
} else printf("error parsing(%s)\n",jsonstr);
if ( (void *)jsonstr != ptr )
free(jsonstr);
if ( ptr != 0 )
nn_freemsg(ptr), ptr = 0;
return(retstr);
}
int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsock,int32_t pullsock,double profitmargin)
{
void *ptr; int32_t recvlen=-1,nonz = 0;
*retstrp = 0;
if ( pullsock >= 0 )
{
while ( (recvlen= nn_recv(pullsock,&ptr,NN_MSG,0)) > 0 )
{
nonz++;
*retstrp = LP_process_message(ctx,"PULL",myipaddr,pubsock,profitmargin,ptr,recvlen,pullsock);
}
}
//if ( amclient != 0 )
// tmpport = myport + 10;
//else tmpport = myport;
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)stats_rpcloop,(void *)&myport) != 0 )
return(nonz);
}
int32_t LP_subsock_check(void *ctx,char *myipaddr,int32_t pubsock,int32_t sock,double profitmargin)
{
int32_t recvlen,nonz = 0; void *ptr; char *retstr;
if ( sock >= 0 )
{
printf("error launching stats rpcloop for port.%u\n",myport);
exit(-1);
while ( (recvlen= nn_recv(sock,&ptr,NN_MSG,0)) > 0 )
{
nonz++;
if ( (retstr= LP_process_message(ctx,"SUB",myipaddr,pubsock,profitmargin,ptr,recvlen,sock)) != 0 )
free(retstr);
}
}
return(nonz);
}
void LP_utxo_spentcheck(int32_t pubsock,struct LP_utxoinfo *utxo,double profitmargin)
{
struct _LP_utxoinfo u; char str[65],destaddr[64]; uint32_t now = (uint32_t)time(NULL);
//printf("%s lag.%d\n",bits256_str(str,utxo->txid),now-utxo->lastspentcheck);
if ( utxo->T.spentflag == 0 && now > utxo->T.lastspentcheck+60 )
{
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee;
utxo->T.lastspentcheck = now;
if ( LP_txvalue(destaddr,utxo->coin,utxo->payment.txid,utxo->payment.vout) == 0 )
{
printf("txid.%s %s/v%d %.8f has been spent\n",utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout,dstr(utxo->payment.value));
LP_spentnotify(utxo,0);
}
else if ( LP_txvalue(destaddr,utxo->coin,u.txid,u.vout) == 0 )
{
printf("txid2.%s %s/v%d %.8f has been spent\n",utxo->coin,bits256_str(str,u.txid),u.vout,dstr(u.value));
LP_spentnotify(utxo,1);
}
}
}
void LP_myutxo_updates(void *ctx,int32_t pubsock,char *passphrase,double profitmargin)
{
//LP_utxopurge(0); not good to disrupt existing pointers
LP_privkey_updates(ctx,pubsock,passphrase,0);
}
int32_t LP_peer_utxosquery(struct LP_peerinfo *mypeer,uint16_t myport,int32_t pubsock,struct LP_peerinfo *peer,uint32_t now,double profitmargin,int32_t interval)
{
int32_t lastn,n = -1;
if ( peer->lastutxos < now-interval )
{
//lastn = peer->numutxos - mypeer->numutxos + LP_PROPAGATION_SLACK;
//if ( lastn < LP_PROPAGATION_SLACK * 2 )
lastn = LP_PROPAGATION_SLACK * 2;
if ( mypeer == 0 || strcmp(peer->ipaddr,mypeer->ipaddr) != 0 )
{
peer->lastutxos = now;
//printf("query utxos from %s\n",peer->ipaddr);
n = LP_utxosquery(mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,profitmargin);
}
} //else printf("LP_peer_utxosquery skip.(%s) %u\n",peer->ipaddr,peer->lastutxos);
return(n);
}
int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int32_t pubsock,char *pushaddr,uint16_t pushport,int32_t pullsock,uint16_t myport,char *passphrase,double profitmargin)
{
static uint32_t counter,lastforward,numpeers;
struct LP_utxoinfo *utxo,*utmp; char *retstr,*origipaddr; struct LP_peerinfo *peer,*tmp; uint32_t now; int32_t nonz = 0,n=0,lastn=-1;
now = (uint32_t)time(NULL);
if ( (origipaddr= myipaddr) == 0 )
origipaddr = "127.0.0.1";
if ( mypeer == 0 )
myipaddr = "127.0.0.1";
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d peers\n",counter,LP_canbind);
numpeers = LP_numpeers();
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
if ( peer->errors >= LP_MAXPEER_ERRORS )
{
if ( (rand() % 10000) == 0 )
peer->errors--;
else continue;
}
if ( now > peer->lastpeers+60 && peer->numpeers > 0 && (peer->numpeers != numpeers || (rand() % 10000) == 0) )
{
if ( IAMLP != 0 )
printf("numpeers.%d updatepeer.%s lag.%d\n",numpeers,peer->ipaddr,now-peer->lastpeers);
peer->lastpeers = now;
if ( IAMLP != 0 && peer->numpeers != numpeers )
printf("%s num.%d vs %d\n",peer->ipaddr,peer->numpeers,numpeers);
if ( strcmp(peer->ipaddr,myipaddr) != 0 )
LP_peersquery(mypeer,pubsock,peer->ipaddr,peer->port,myipaddr,myport,profitmargin);
}
if ( peer->diduquery == 0 )
{
if ( lastn != n || n < 20 )
{
lastn = n;
n = LP_peer_utxosquery(mypeer,myport,pubsock,peer,now,profitmargin,60);
}
LP_peer_pricesquery(peer->ipaddr,peer->port);
peer->diduquery = now;
}
nonz += LP_subsock_check(ctx,origipaddr,pubsock,peer->subsock,profitmargin);
}
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d forwarding\n",counter,LP_canbind);
if ( (counter % 600) == 20 )
{
LP_myutxo_updates(ctx,pubsock,passphrase,profitmargin);
if ( lastforward < now-3600 )
{
if ( (retstr= LP_registerall(0)) != 0 )
free(retstr);
//LP_forwarding_register(LP_mypubkey,pushaddr,pushport,10);
lastforward = now;
}
}
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d utxos\n",counter,LP_canbind);
if ( (counter % 600) == 60 )
{
HASH_ITER(hh,LP_utxoinfos[0],utxo,utmp)
{
LP_utxo_spentcheck(pubsock,utxo,profitmargin);
}
HASH_ITER(hh,LP_utxoinfos[1],utxo,utmp)
{
//char str[65];
LP_utxo_spentcheck(pubsock,utxo,profitmargin);
if ( utxo->T.lasttime == 0 )
LP_utxo_clientpublish(utxo);
//else if ( strcmp(utxo->coin,"HUSH") == 0 )
// printf("lasttime set %s\n",bits256_str(str,utxo->payment.txid));
}
}
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d swapentry\n",counter,LP_canbind);
if ( (counter % 6000) == 5999 )
{
if ( (retstr= basilisk_swapentry(0,0)) != 0 )
{
//printf("SWAPS.(%s)\n",retstr);
free(retstr);
}
}
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d pullsock check\n",counter,LP_canbind);
nonz += LP_pullsock_check(ctx,&retstr,myipaddr,pubsock,pullsock,profitmargin);
if ( retstr != 0 )
free(retstr);
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d hellos\n",counter,LP_canbind);
if ( IAMLP != 0 && (counter % 600) == 42 )
LP_hellos();
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d\n",counter,LP_canbind);
if ( LP_canbind == 0 && (counter % (PSOCK_KEEPALIVE*MAINLOOP_PERSEC/2)) == 13 )
{
char keepalive[128];
sprintf(keepalive,"{\"method\":\"keepalive\"}");
//printf("send keepalive to %s pullsock.%d\n",pushaddr,pullsock);
if ( LP_send(pullsock,keepalive,(int32_t)strlen(keepalive)+1,0) < 0 )
{
//LP_deadman_switch = 0;
}
}
counter++;
return(nonz);
}
void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins,char *passphrase)
{
int32_t i,n; cJSON *item;
for (i=0; i<sizeof(activecoins)/sizeof(*activecoins); i++)
{
fprintf(stderr,"%s ",activecoins[i]);
LP_coinfind(activecoins[i]);
LP_priceinfoadd(activecoins[i]);
}
LP_privkey_updates(mypeer,pubsock,passphrase,amclient);
HASH_ITER(hh,LP_peerinfos,peer,tmp)
if ( (n= cJSON_GetArraySize(coins)) > 0 )
{
if ( strcmp(peer->ipaddr,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1") != 0 )
LP_utxosquery(0,mypeer,pubsock,peer->ipaddr,peer->port,"",100,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,profitmargin);
for (i=0; i<n; i++)
{
item = jitem(coins,i);
fprintf(stderr,"%s ",jstr(item,"coin"));
LP_coincreate(item);
LP_priceinfoadd(jstr(item,"coin"));
}
}
if ( amclient != 0 )
fprintf(stderr,"privkey updates\n");
LP_privkey_updates(ctx,pubsock,passphrase,1);
}
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 )
{
while ( 1 )
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 )
{
nonz = n = 0;
if ( (++counter % 3600) == 0 )
LP_privkey_updates(mypeer,pubsock,passphrase,amclient);
HASH_ITER(hh,LP_peerinfos,peer,tmp)
for (i=0; i<sizeof(default_LPnodes)/sizeof(*default_LPnodes); i++)
{
n++;
while ( peer->subsock >= 0 && (recvsize= nn_recv(peer->subsock,&ptr,NN_MSG,0)) >= 0 )
{
nonz++;
if ( (argjson= cJSON_Parse((char *)ptr)) != 0 )
{
portable_mutex_lock(&LP_commandmutex);
if ( (retstr= stats_JSON(argjson,"127.0.0.1",0)) != 0 )
{
//printf("%s RECV.[%d] %s\n",peer->ipaddr,recvsize,(char *)ptr);
free(retstr);
}
portable_mutex_unlock(&LP_commandmutex);
//printf("subloop.(%s)\n",jprint(argjson,0));
free_json(argjson);
} else printf("error parsing.(%s)\n",(char *)ptr);
if ( ptr != 0 )
nn_freemsg(ptr), ptr = 0;
}
if ( (rand() % 100) > 25 )
continue;
LP_peersquery(mypeer,pubsock,default_LPnodes[i],myport,mypeer->ipaddr,myport,profitmargin);
}
if ( nonz == 0 )
usleep(100000);
}
} else LP_peersquery(mypeer,pubsock,seednode,myport,mypeer->ipaddr,myport,profitmargin);
}
else
{
while ( 1 )
if ( myipaddr == 0 )
{
nonz = 0;
if ( (++counter % 2000) == 0 )
LP_privkey_updates(mypeer,pubsock,passphrase,amclient);
if ( (counter % 500) == 0 )
{
HASH_ITER(hh,LP_utxoinfos,utxo,utmp)
{
if ( strcmp(utxo->ipaddr,mypeer->ipaddr) == 0 && utxo->port == mypeer->port )
{
if ( strcmp(utxo->coin,"KMD") == 0 )
LP_priceping(pubsock,utxo,"BTC",profitmargin);
else LP_priceping(pubsock,utxo,"KMD",profitmargin);
}
}
}
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
if ( peer->numpeers != mypeer->numpeers || (rand() % 10000) == 0 )
{
if ( peer->numpeers != mypeer->numpeers )
printf("%s num.%d vs %d\n",peer->ipaddr,peer->numpeers,mypeer->numpeers);
if ( strcmp(peer->ipaddr,mypeer->ipaddr) != 0 )
LP_peersquery(amclient,mypeer,pubsock,peer->ipaddr,peer->port,mypeer->ipaddr,myport,profitmargin);
}
if ( peer->numutxos != mypeer->numutxos )
{
lastn = peer->numutxos - mypeer->numutxos + LP_PROPAGATION_SLACK;
if ( lastn < LP_PROPAGATION_SLACK * 2 )
lastn = LP_PROPAGATION_SLACK * 2;
printf("%s numutxos.%d vs %d lastn.%d\n",peer->ipaddr,peer->numutxos,mypeer->numutxos,lastn);
if ( strcmp(peer->ipaddr,mypeer->ipaddr) != 0 )
LP_utxosquery(0,mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,mypeer->ipaddr,myport,profitmargin);
}
while ( peer->subsock >= 0 && (recvsize= nn_recv(peer->subsock,&ptr,NN_MSG,0)) >= 0 )
{
nonz++;
if ( (argjson= cJSON_Parse((char *)ptr)) != 0 )
{
portable_mutex_lock(&LP_commandmutex);
if ( (retstr= stats_JSON(argjson,"127.0.0.1",0)) != 0 )
{
//printf("%s RECV.[%d] %s\n",peer->ipaddr,recvsize,(char *)ptr);
free(retstr);
}
portable_mutex_unlock(&LP_commandmutex);
free_json(argjson);
} else printf("error parsing.(%s)\n",(char *)ptr);
if ( ptr != 0 )
nn_freemsg(ptr), ptr = 0;
}
}
while ( pullsock >= 0 && (recvsize= nn_recv(pullsock,&ptr,NN_MSG,0)) >= 0 )
printf("couldnt get myipaddr\n");
exit(-1);
}
if ( seednode == 0 || seednode[0] == 0 )
{
OS_randombytes((void *)&r,sizeof(r));
for (j=0; j<sizeof(default_LPnodes)/sizeof(*default_LPnodes); j++)
{
nonz++;
if ( (argjson= cJSON_Parse((char *)ptr)) != 0 )
{
len = (int32_t)strlen((char *)ptr) + 1;
portable_mutex_lock(&LP_commandmutex);
if ( LP_command(mypeer,pubsock,argjson,&((uint8_t *)ptr)[len],recvsize - len,profitmargin) == 0 )
{
if ( (retstr= stats_JSON(argjson,"127.0.0.1",0)) != 0 )
{
//printf("%s RECV.[%d] %s\n",peer->ipaddr,recvsize,(char *)ptr);
free(retstr);
}
}
portable_mutex_unlock(&LP_commandmutex);
free_json(argjson);
}
if ( ptr != 0 )
nn_freemsg(ptr), ptr = 0;
i = (r + j) % (sizeof(default_LPnodes)/sizeof(*default_LPnodes));
LP_peersquery(mypeer,pubsock,default_LPnodes[i],myport,"127.0.0.1",myport,profitmargin);
}
if ( nonz == 0 )
usleep(50000);
}
} else LP_peersquery(mypeer,pubsock,seednode,myport,"127.0.0.1",myport,profitmargin);
}
}
void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profitmargin,char *passphrase,int32_t amclient,char *userhome)
void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profitmargin,char *passphrase,int32_t amclient,char *userhome,cJSON *argjson)
{
char *myipaddr=0; long filesize,n; int32_t timeout,maxsize,pullsock=-1,pubsock=-1; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128];
IAMCLIENT = amclient;
char *myipaddr=0; long filesize,n; int32_t timeout,pullsock=-1,pubsock=-1; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128],bindaddr[128]; void *ctx = bitcoin_ctx();
IAMLP = !amclient;
#ifndef __linux__
if ( IAMLP != 0 )
{
printf("must run a unix node for LP node\n");
exit(-1);
}
#endif
LP_profitratio += profitmargin;
OS_randombytes((void *)&n,sizeof(n));
if ( jobj(argjson,"gui") != 0 )
safecopy(LP_gui,jstr(argjson,"gui"),sizeof(LP_gui));
if ( jobj(argjson,"canbind") == 0 )
{
#ifndef __linux__
LP_canbind = 1;
#else
LP_canbind = IAMLP;
#endif
} else LP_canbind = jint(argjson,"canbind");
if ( LP_canbind > 1000 && LP_canbind < 65536 )
LP_fixed_pairport = LP_canbind;
if ( LP_canbind != 0 )
LP_canbind = 1;
srand((int32_t)n);
if ( userhome != 0 && userhome[0] != 0 )
{
safecopy(USERHOME,userhome,sizeof(USERHOME));
#ifdef __APPLE__
strcat(USERHOME,"/Library/Application Support");
#endif
}
portable_mutex_init(&LP_peermutex);
portable_mutex_init(&LP_utxomutex);
portable_mutex_init(&LP_UTXOmutex);
portable_mutex_init(&LP_commandmutex);
portable_mutex_init(&LP_swaplistmutex);
portable_mutex_init(&LP_cachemutex);
if ( amclient == 0 )
portable_mutex_init(&LP_networkmutex);
portable_mutex_init(&LP_forwardmutex);
portable_mutex_init(&LP_psockmutex);
portable_mutex_init(&LP_pubkeymutex);
if ( profitmargin == 0. || profitmargin == 0.01 )
{
if ( profitmargin == 0. || profitmargin == 0.01 )
profitmargin = 0.01 + (double)(rand() % 100)/100000;
printf("default profit margin %f\n",profitmargin);
}
if ( system("curl -s4 checkip.amazonaws.com > /tmp/myipaddr") == 0 )
{
if ( (myipaddr= OS_filestr(&filesize,"/tmp/myipaddr")) != 0 && myipaddr[0] != 0 )
{
profitmargin = 0.01 + (double)(rand() % 100)/100000;
printf("default profit margin %f\n",profitmargin);
}
if ( system("curl -s4 checkip.amazonaws.com > /tmp/myipaddr") == 0 )
n = strlen(myipaddr);
if ( myipaddr[n-1] == '\n' )
myipaddr[--n] = 0;
strcpy(LP_myipaddr,myipaddr);
} else printf("error getting myipaddr\n");
} else printf("error issuing curl\n");
if ( IAMLP != 0 )
{
pubsock = -1;
nanomsg_transportname(0,subaddr,myipaddr,mypubport);
nanomsg_transportname(1,bindaddr,myipaddr,mypubport);
if ( (pubsock= nn_socket(AF_SP,NN_PUB)) >= 0 )
{
if ( (myipaddr= OS_filestr(&filesize,"/tmp/myipaddr")) != 0 && myipaddr[0] != 0 )
if ( nn_bind(pubsock,bindaddr) >= 0 )
{
n = strlen(myipaddr);
if ( myipaddr[n-1] == '\n' )
myipaddr[--n] = 0;
pullsock = pubsock = -1;
nanomsg_tcpname(pushaddr,myipaddr,mypullport);
nanomsg_tcpname(subaddr,myipaddr,mypubport);
printf(">>>>>>>>> myipaddr.%s (%s %s)\n",myipaddr,pushaddr,subaddr);
if ( (pullsock= nn_socket(AF_SP,NN_PULL)) >= 0 && (pubsock= nn_socket(AF_SP,NN_PUB)) >= 0 )
{
if ( nn_bind(pullsock,pushaddr) >= 0 && nn_bind(pubsock,subaddr) >= 0 )
{
timeout = 10;
nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
timeout = 1;
nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout));
timeout = 1;
maxsize = 1024 * 1024;
nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVBUF,&maxsize,sizeof(maxsize));
}
else
{
printf("error binding to (%s).%d (%s).%d\n",pushaddr,pullsock,subaddr,pubsock);
if ( pullsock >= 0 )
nn_close(pullsock), pullsock = -1;
if ( pubsock >= 0 )
nn_close(pubsock), pubsock = -1;
}
} else printf("error getting sockets %d %d\n",pullsock,pubsock);
LP_mypubsock = pubsock;
LP_mypeer = mypeer = LP_addpeer(amclient,mypeer,pubsock,myipaddr,myport,0,0,profitmargin,0,0);
//printf("my ipaddr.(%s) peers.(%s)\n",ipaddr,retstr!=0?retstr:"");
} else printf("error getting myipaddr\n");
} else printf("error issuing curl\n");
if ( myipaddr == 0 || mypeer == 0 )
timeout = 10;
nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
}
else
{
printf("error binding to (%s).%d\n",subaddr,pubsock);
if ( pubsock >= 0 )
nn_close(pubsock), pubsock = -1;
}
} else printf("error getting pubsock %d\n",pubsock);
printf(">>>>>>>>> myipaddr.%s (%s) pullsock.%d\n",myipaddr,subaddr,pubsock);
LP_mypubsock = pubsock;
}
LP_initpeers(pubsock,mypeer,myipaddr,myport,jstr(argjson,"seednode"),profitmargin);
pullsock = LP_initpublicaddr(ctx,&mypullport,pushaddr,myipaddr,mypullport,0);
strcpy(LP_publicaddr,pushaddr);
LP_publicport = mypullport;
LP_deadman_switch = (uint32_t)time(NULL);
printf("my command address is (%s) pullsock.%d pullport.%u\n",pushaddr,pullsock,mypullport);
LP_initcoins(ctx,pubsock,jobj(argjson,"coins"),passphrase);
if ( IAMLP != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_psockloop,(void *)&myipaddr) != 0 )
{
printf("error launching LP_psockloop for (%s)\n",myipaddr);
exit(-1);
}
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)stats_rpcloop,(void *)&myport) != 0 )
{
printf("error launching stats rpcloop for port.%u\n",myport);
exit(-1);
}
while ( 1 )
{
//fprintf(stderr,".");
if ( LP_mainloop_iter(ctx,myipaddr,mypeer,pubsock,pushaddr,mypullport,pullsock,myport,passphrase,profitmargin) == 0 )
usleep(1000000 / MAINLOOP_PERSEC);
if ( LP_canbind == 0 )
{
printf("couldnt get myipaddr or null mypeer.%p\n",mypeer);
exit(-1);
//printf("check deadman %u vs %u\n",LP_deadman_switch,(uint32_t)time(NULL));
if ( LP_deadman_switch < time(NULL)-PSOCK_KEEPALIVE )
{
printf("DEAD man's switch %u activated at %u lag.%d, register forwarding again\n",LP_deadman_switch,(uint32_t)time(NULL),(uint32_t)(time(NULL) - LP_deadman_switch));
if ( pullsock >= 0 )
nn_close(pullsock);
pullsock = LP_initpublicaddr(ctx,&mypullport,pushaddr,myipaddr,mypullport,0);
LP_deadman_switch = (uint32_t)time(NULL);
strcpy(LP_publicaddr,pushaddr);
LP_publicport = mypullport;
LP_forwarding_register(LP_mypubkey,pushaddr,mypullport,MAX_PSOCK_PORT);
}
}
printf("utxos.(%s)\n",LP_utxos(mypeer,"",10000));
}
LP_mainloop(mypeer,mypubport,pubsock,pullsock,myport,amclient,passphrase,profitmargin);
}

396
iguana/exchanges/LP_network.c

@ -18,39 +18,52 @@
// marketmaker
//
char *nanomsg_tcpname(char *str,char *ipaddr,uint16_t port)
struct psock
{
sprintf(str,"tcp://%s:%u",ipaddr,port);
uint32_t lasttime,lastping,errors;
int32_t publicsock,sendsock,ispaired;
uint16_t publicport,sendport;
char sendaddr[128],publicaddr[128];
} *PSOCKS;
uint16_t Numpsocks,Psockport = MIN_PSOCK_PORT;
char *nanomsg_transportname(int32_t bindflag,char *str,char *ipaddr,uint16_t port)
{
sprintf(str,"tcp://%s:%u",bindflag == 0 ? ipaddr : "*",port);
return(str);
}
int32_t LP_send(int32_t sock,char *msg,int32_t freeflag)
int32_t LP_send(int32_t sock,void *msg,int32_t sendlen,int32_t freeflag)
{
int32_t sentbytes,len,i; struct nn_pollfd pfd;
int32_t sentbytes,i; struct nn_pollfd pfd;
if ( sock < 0 )
{
printf("LP_send.(%s) to illegal socket\n",msg);
printf("LP_send.(%s) to illegal socket\n",(char *)msg);
if ( freeflag != 0 )
free(msg);
return(-1);
}
for (i=0; i<100; i++)
//len = (int32_t)strlen(msg) + 1;
for (i=0; i<1000; i++) // 1000 * (1 ms + 1000 us) = 2 seconds
{
pfd.fd = sock;
pfd.events = NN_POLLOUT;
if ( nn_poll(&pfd,1,100) > 0 )
//portable_mutex_lock(&LP_networkmutex);
if ( nn_poll(&pfd,1,1) > 0 )
{
len = (int32_t)strlen(msg) + 1;
if ( (sentbytes= nn_send(sock,msg,len,0)) != len )
printf("LP_send sent %d instead of %d\n",sentbytes,len);
else printf("SENT.(%s)\n",msg);
if ( (sentbytes= nn_send(sock,msg,sendlen,0)) != sendlen )
printf("LP_send sent %d instead of %d\n",sentbytes,sendlen);
//else printf("SENT.(%s)\n",msg);
if ( freeflag != 0 )
free(msg);
//portable_mutex_unlock(&LP_networkmutex);
return(sentbytes);
}
//portable_mutex_unlock(&LP_networkmutex);
usleep(1000);
}
printf("error LP_send\n");
printf("error LP_send sock.%d, i.%d timeout.(%s) %s\n",sock,i,(char *)msg,nn_strerror(nn_errno()));
if ( freeflag != 0 )
free(msg);
return(-1);
@ -75,8 +88,365 @@ uint32_t LP_swapsend(int32_t pairsock,struct basilisk_swap *swap,uint32_t msgbit
{
}
}
printf("sent %d bytes\n",sentbytes);
//printf("sent %d bytes\n",sentbytes);
//else printf("send.[%d] %x offset.%d datalen.%d [%llx]\n",sentbytes,msgbits,offset,datalen,*(long long *)data);
free(buf);
return(nextbits);
}
void LP_psockloop(void *_ptr)
{
static struct nn_pollfd *pfds;
int32_t i,n,nonz,iter,retval,size=0,sentbytes,sendsock = -1; uint32_t now; struct psock *ptr=0; void *buf=0; char keepalive[512];//,*myipaddr = _ptr;
while ( 1 )
{
now = (uint32_t)time(NULL);
if ( buf != 0 && ptr != 0 && sendsock >= 0 )
{
if ( size > 0 )
{
if ( (sentbytes= LP_send(sendsock,buf,size,0)) > 0 )
{
//printf("PSOCKS (%d %d %d) (%s) -> %d/%d bytes %s\n",ptr->publicsock,ptr->sendsock,sendsock,(char *)buf,size,sentbytes,ptr->sendaddr);
}
else
{
ptr->errors++;
printf("send error.%d to %s\n",ptr->errors,ptr->sendaddr);
}
if ( buf != 0 )
{
if ( buf != keepalive )
nn_freemsg(buf);
buf = 0;
size = 0;
ptr = 0;
sendsock = -1;
}
}
}
else if ( Numpsocks > 0 )
{
if ( pfds == 0 )
pfds = calloc(MAX_PSOCK_PORT,sizeof(*pfds));
portable_mutex_lock(&LP_psockmutex);
memset(pfds,0,sizeof(*pfds) * ((Numpsocks*2 <= MAX_PSOCK_PORT) ? Numpsocks*2 : MAX_PSOCK_PORT));
for (iter=0; iter<2; iter++)
{
for (i=n=0; 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));
}

57
iguana/exchanges/LP_peers.c

@ -42,21 +42,22 @@ char *LP_peers()
struct LP_peerinfo *peer,*tmp; cJSON *peersjson = cJSON_CreateArray();
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
jaddi(peersjson,LP_peerjson(peer));
//if ( peer->errors < LP_MAXPEER_ERRORS )
jaddi(peersjson,LP_peerjson(peer));
}
return(jprint(peersjson,1));
}
struct LP_peerinfo *LP_addpeer(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *ipaddr,uint16_t port,uint16_t pushport,uint16_t subport,double profitmargin,int32_t numpeers,int32_t numutxos)
struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char *ipaddr,uint16_t port,uint16_t pushport,uint16_t subport,double profitmargin,int32_t numpeers,int32_t numutxos)
{
uint32_t ipbits; int32_t pushsock,subsock,timeout,enabled; char checkip[64],pushaddr[64],subaddr[64]; struct LP_peerinfo *peer = 0;
uint32_t ipbits; int32_t maxsize,pushsock,subsock,timeout; char checkip[64],pushaddr[64],subaddr[64]; struct LP_peerinfo *peer = 0;
ipbits = (uint32_t)calc_ipbits(ipaddr);
expand_ipbits(checkip,ipbits);
if ( strcmp(checkip,ipaddr) == 0 )
{
if ( (peer= LP_peerfind(ipbits,port)) != 0 )
{
if ( peer->profitmargin == 0. )
if ( profitmargin != 0. )
peer->profitmargin = profitmargin;
if ( numpeers > peer->numpeers )
peer->numpeers = numpeers;
@ -65,34 +66,32 @@ struct LP_peerinfo *LP_addpeer(int32_t amclient,struct LP_peerinfo *mypeer,int32
}
else
{
//printf("LPaddpeer %s\n",ipaddr);
printf("LPaddpeer %s\n",ipaddr);
peer = calloc(1,sizeof(*peer));
peer->pushsock = peer->subsock = pushsock = subsock = -1;
strcpy(peer->ipaddr,ipaddr);
if ( amclient == 0 )
enabled = 1;
else enabled = 1;//(rand() % (1 << Client_connections)) == 0;
if ( pushport != 0 && subport != 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 )
{
timeout = 1000;
nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
nanomsg_tcpname(pushaddr,peer->ipaddr,pushport);
nanomsg_transportname(0,pushaddr,peer->ipaddr,pushport);
if ( nn_connect(pushsock,pushaddr) >= 0 )
{
timeout = 100;
nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
maxsize = 2 * 1024 * 1024;
nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDBUF,&maxsize,sizeof(maxsize));
printf("connected to push.(%s) %d\n",pushaddr,pushsock);
peer->connected = (uint32_t)time(NULL);
peer->pushsock = pushsock;
if ( enabled != 0 && (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 )
if ( (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 )
{
timeout = 1;
nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout));
nn_setsockopt(subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0);
nanomsg_tcpname(subaddr,peer->ipaddr,subport);
nanomsg_transportname(0,subaddr,peer->ipaddr,subport);
if ( nn_connect(subsock,subaddr) >= 0 )
{
peer->subsock = subsock;
printf("connected to sub.(%s) %d\n",subaddr,peer->subsock);
Client_connections += amclient;
} else nn_close(subsock);
}
}
@ -115,13 +114,16 @@ struct LP_peerinfo *LP_addpeer(int32_t amclient,struct LP_peerinfo *mypeer,int32
} else peer->numpeers = 1; // will become mypeer
portable_mutex_unlock(&LP_peermutex);
if ( mypubsock >= 0 )
LP_send(mypubsock,jprint(LP_peerjson(peer),1),1);
{
char *msg = jprint(LP_peerjson(peer),1);
LP_send(mypubsock,msg,(int32_t)strlen(msg)+1,1);
}
}
} else printf("LP_addpeer: checkip.(%s) vs (%s)\n",checkip,ipaddr);
return(peer);
}
int32_t LP_peersparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now)
int32_t LP_peersparse(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now)
{
struct LP_peerinfo *peer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0;
if ( (array= cJSON_Parse(retstr)) != 0 )
@ -140,7 +142,7 @@ int32_t LP_peersparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubs
argipbits = (uint32_t)calc_ipbits(argipaddr);
if ( (peer= LP_peerfind(argipbits,argport)) == 0 )
{
peer = LP_addpeer(amclient,mypeer,mypubsock,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos"));
peer = LP_addpeer(mypeer,mypubsock,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos"));
}
if ( peer != 0 )
{
@ -156,19 +158,17 @@ int32_t LP_peersparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubs
return(n);
}
void LP_peersquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *myipaddr,uint16_t myport,double myprofit)
void LP_peersquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *myipaddr,uint16_t myport,double myprofit)
{
char *retstr; struct LP_peerinfo *peer,*tmp; uint32_t now,flag = 0;
peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport);
if ( peer != 0 && peer->errors > 0 )
return;
if ( (retstr= issue_LP_getpeers(destipaddr,destport,myipaddr,myport,myprofit,mypeer!=0?mypeer->numpeers:0,mypeer!=0?mypeer->numutxos:0)) != 0 )
{
//printf("got.(%s)\n",retstr);
now = (uint32_t)time(NULL);
LP_peersparse(amclient,mypeer,mypubsock,destipaddr,destport,retstr,now);
LP_peersparse(mypeer,mypubsock,destipaddr,destport,retstr,now);
free(retstr);
if ( amclient == 0 )
if ( IAMLP != 0 )
{
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
@ -183,6 +183,15 @@ void LP_peersquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock
if ( flag != 0 )
printf(" <- missing peers\n");
}
} else if ( peer != 0 )
peer->errors++;
}
}
int32_t LP_numpeers()
{
struct LP_peerinfo *peer,*tmp; int32_t numpeers = 0;
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
numpeers++;
}
return(numpeers);
}

506
iguana/exchanges/LP_prices.c

@ -18,7 +18,9 @@
// marketmaker
//
#define LP_MAXPRICEINFOS 64
struct LP_orderbookentry { bits256 txid,txid2,pubkey; double price; uint64_t basesatoshis; int32_t vout,vout2; };
#define LP_MAXPRICEINFOS 256
struct LP_priceinfo
{
char symbol[16];
@ -39,6 +41,45 @@ struct LP_cacheinfo
uint32_t timestamp;
} *LP_cacheinfos;
struct LP_pubkeyinfo
{
UT_hash_handle hh;
bits256 pubkey;
double matrix[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS];
uint32_t timestamp,istrusted,numerrors;
} *LP_pubkeyinfos;
struct LP_priceinfo *LP_priceinfofind(char *symbol)
{
int32_t i; struct LP_priceinfo *pp; uint64_t coinbits;
if ( symbol == 0 || symbol[0] == 0 )
return(0);
if ( LP_numpriceinfos > 0 )
{
coinbits = stringbits(symbol);
pp = LP_priceinfos;
for (i=0; 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)
{
uint64_t basebits,relbits; int32_t offset = 0;
@ -54,6 +95,8 @@ int32_t LP_cachekey(uint8_t *key,char *base,char *rel,bits256 txid,int32_t vout)
struct LP_cacheinfo *LP_cachefind(char *base,char *rel,bits256 txid,int32_t vout)
{
struct LP_cacheinfo *ptr=0; uint8_t key[sizeof(bits256)+sizeof(uint64_t)*2+sizeof(vout)];
if ( base == 0 || rel == 0 )
return(0);
if ( LP_cachekey(key,base,rel,txid,vout) == sizeof(key) )
{
portable_mutex_lock(&LP_cachemutex);
@ -70,6 +113,131 @@ struct LP_cacheinfo *LP_cachefind(char *base,char *rel,bits256 txid,int32_t vout
return(ptr);
}
struct LP_pubkeyinfo *LP_pubkeyfind(bits256 pubkey)
{
struct LP_pubkeyinfo *pubp=0;
portable_mutex_lock(&LP_pubkeymutex);
HASH_FIND(hh,LP_pubkeyinfos,&pubkey,sizeof(pubkey),pubp);
portable_mutex_unlock(&LP_pubkeymutex);
return(pubp);
}
struct LP_pubkeyinfo *LP_pubkeyadd(bits256 pubkey)
{
struct LP_pubkeyinfo *pubp=0;
if ( (pubp= LP_pubkeyfind(pubkey)) == 0 )
{
portable_mutex_lock(&LP_pubkeymutex);
pubp = calloc(1,sizeof(*pubp));
pubp->pubkey = pubkey;
HASH_ADD_KEYPTR(hh,LP_pubkeyinfos,&pubp->pubkey,sizeof(pubp->pubkey),pubp);
portable_mutex_unlock(&LP_pubkeymutex);
if ( (pubp= LP_pubkeyfind(pubkey)) == 0 )
printf("pubkeyadd find error after add\n");
}
return(pubp);
}
int32_t LP_pubkey_istrusted(bits256 pubkey)
{
struct LP_pubkeyinfo *pubp;
if ( (pubp= LP_pubkeyfind(pubkey)) != 0 )
return(pubp->istrusted != 0);
return(0);
}
char *LP_pubkey_trustset(bits256 pubkey,uint32_t trustval)
{
struct LP_pubkeyinfo *pubp;
if ( (pubp= LP_pubkeyfind(pubkey)) != 0 )
{
pubp->istrusted = trustval;
return(clonestr("{\"result\":\"success\"}"));
}
return(clonestr("{\"error\":\"pubkey not found\"}"));
}
cJSON *LP_pubkeyjson(struct LP_pubkeyinfo *pubp)
{
int32_t baseid,relid; char *base; double price; cJSON *item,*array,*obj;
obj = cJSON_CreateObject();
array = cJSON_CreateArray();
for (baseid=0; 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)
{
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;
if ( ptr->price == 0. && ptr->Q.satoshis != 0 )
{
printf("null ptr->price? ");
printf("LP_pricecache: null ptr->price? ");
ptr->price = (double)ptr->Q.destsatoshis / ptr->Q.satoshis;
}
//printf("found %s/%s %.8f\n",base,rel,ptr->price);
@ -89,63 +257,87 @@ double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,i
return(0.);
}
struct LP_priceinfo *LP_priceinfofind(char *symbol)
{
int32_t i; struct LP_priceinfo *pp; uint64_t coinbits;
if ( LP_numpriceinfos > 0 )
{
coinbits = stringbits(symbol);
pp = LP_priceinfos;
for (i=0; 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)
void LP_priceinfoupdate(char *base,char *rel,double price)
{
struct LP_priceinfo *basepp,*relpp;
if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
*indp = relpp->ind;
return(basepp);
}
else
{
*indp = -1;
return(0);
//dxblend(&basepp->relvals[relpp->ind],price,0.9);
//dxblend(&relpp->relvals[basepp->ind],1. / price,0.9);
basepp->relvals[relpp->ind] = price;
relpp->relvals[basepp->ind] = 1. / price;
}
}
void LP_priceinfoupdate(char *base,char *rel,double price)
double LP_myprice(double *bidp,double *askp,char *base,char *rel)
{
struct LP_priceinfo *basepp,*relpp;
struct LP_priceinfo *basepp,*relpp; double val;
*bidp = *askp = 0.;
if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
dxblend(&basepp->relvals[relpp->ind],price,0.9);
dxblend(&relpp->relvals[basepp->ind],1. / price,0.9);
if ( (*askp= basepp->myprices[relpp->ind]) > SMALLVAL )
{
if ( (val= relpp->myprices[basepp->ind]) > SMALLVAL )
{
*bidp = 1. / val;
return((*askp + *bidp) * 0.5);
}
else
{
*bidp = 0.;
return(*askp);
}
}
else
{
if ( (val= relpp->myprices[basepp->ind]) > SMALLVAL )
{
*bidp = 1. / val;
*askp = 0.;
return(*bidp);
}
}
}
return(0.);
}
double LP_myprice(double *bidp,double *askp,char *base,char *rel)
char *LP_myprices()
{
struct LP_priceinfo *basepp,*relpp;
if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
int32_t baseid,relid; double bid,ask; char *base,*rel; cJSON *item,*array;
array = cJSON_CreateArray();
for (baseid=0; baseid<LP_numpriceinfos; baseid++)
{
*askp = basepp->myprices[relpp->ind];
*bidp = relpp->myprices[basepp->ind];
return((*askp + *bidp) * 0.5);
} else return(0.);
base = LP_priceinfos[baseid].symbol;
for (relid=0; relid<LP_numpriceinfos; relid++)
{
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)
{
struct LP_priceinfo *basepp,*relpp;
if ( price != 0. && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
struct LP_priceinfo *basepp,*relpp; struct LP_pubkeyinfo *pubp;
if ( base != 0 && rel != 0 && price > SMALLVAL && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
basepp->myprices[relpp->ind] = price * LP_profitratio; // ask
relpp->myprices[basepp->ind] = (1. / price) * LP_profitratio; // bid
basepp->myprices[relpp->ind] = price; // ask
//relpp->myprices[basepp->ind] = (1. / price); // bid
if ( (pubp= LP_pubkeyadd(LP_mypubkey)) != 0 )
{
pubp->matrix[basepp->ind][relpp->ind] = price;
//pubp->matrix[relpp->ind][basepp->ind] = (1. / price);
pubp->timestamp = (uint32_t)time(NULL);
}
return(0);
} else return(-1);
}
@ -167,7 +359,7 @@ cJSON *LP_priceinfomatrix(int32_t usemyprices)
now = (uint32_t)time(NULL);
HASH_ITER(hh,LP_cacheinfos,ptr,tmp)
{
if ( ptr->timestamp < now-60 || ptr->price == 0. )
if ( ptr->timestamp < now-3600*2 || ptr->price == 0. )
continue;
LP_priceinfoupdate(ptr->Q.srccoin,ptr->Q.destcoin,ptr->price);
}
@ -180,7 +372,7 @@ cJSON *LP_priceinfomatrix(int32_t usemyprices)
{
if ( usemyprices == 0 || (val= pp->myprices[j]) == 0. )
val = pp->relvals[j];
if ( val != 0. )
if ( val > SMALLVAL )
{
sum += val;
n++;
@ -197,8 +389,11 @@ cJSON *LP_priceinfomatrix(int32_t usemyprices)
pp = LP_priceinfos;
for (i=0; i<LP_numpriceinfos; i++,pp++)
{
pp->diagval /= total;
jaddnum(vectorjson,pp->symbol,pp->diagval);
if ( pp->diagval > SMALLVAL )
{
pp->diagval /= total;
jaddnum(vectorjson,pp->symbol,pp->diagval);
}
}
}
return(vectorjson);
@ -207,6 +402,8 @@ cJSON *LP_priceinfomatrix(int32_t usemyprices)
struct LP_priceinfo *LP_priceinfoadd(char *symbol)
{
struct LP_priceinfo *pp; cJSON *retjson;
if ( symbol == 0 )
return(0);
if ( LP_numpriceinfos >= sizeof(LP_priceinfos)/sizeof(*LP_priceinfos) )
{
printf("cant add any more priceinfos\n");
@ -217,16 +414,6 @@ struct LP_priceinfo *LP_priceinfoadd(char *symbol)
safecopy(pp->symbol,symbol,sizeof(pp->symbol));
pp->coinbits = stringbits(symbol);
pp->ind = LP_numpriceinfos++;
/*pp->relvals = calloc(LP_numpriceinfos+1,sizeof(*pp->relvals));
//pp->myprices = calloc(LP_numpriceinfos+1,sizeof(*pp->myprices));
vecsize = sizeof(*LP_priceinfos[i].relvals) * (LP_numpriceinfos + 1);
for (i=0; 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++;
if ( (retjson= LP_priceinfomatrix(0)) != 0 )
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)
{
char str[65]; struct LP_cacheinfo *ptr=0;
if ( base == 0 || rel == 0 )
return(0);
if ( (ptr= LP_cachefind(base,rel,txid,vout)) == 0 )
{
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)
{
#define ptr_a ((struct LP_cacheinfo *)a)->price
#define ptr_b ((struct LP_cacheinfo *)b)->price
int32_t retval = 0;
#define ptr_a (*(struct LP_orderbookentry **)a)->price
#define ptr_b (*(struct LP_orderbookentry **)b)->price
if ( ptr_b > ptr_a )
return(1);
retval = -1;
else if ( ptr_b < ptr_a )
return(-1);
retval = 1;
else
{
#undef ptr_a
#undef ptr_b
#define ptr_a ((struct LP_cacheinfo *)a)->Q.satoshis
#define ptr_b ((struct LP_cacheinfo *)b)->Q.satoshis
#define ptr_a ((struct LP_orderbookentry *)a)->basesatoshis
#define ptr_b ((struct LP_orderbookentry *)b)->basesatoshis
if ( ptr_b > ptr_a )
return(1);
else if ( ptr_b < ptr_a )
return(-1);
else if ( ptr_b < ptr_a )
return(1);
}
return(0);
// printf("%.8f vs %.8f -> %d\n",ptr_a,ptr_b,retval);
return(retval);
#undef ptr_a
#undef ptr_b
}
static int _cmp_orderbookrev(const void *a,const void *b)
cJSON *LP_orderbookjson(struct LP_orderbookentry *op)
{
return(-_cmp_orderbook(a,b));
cJSON *item = cJSON_CreateObject();
if ( op->price > SMALLVAL )
{
jaddnum(item,"price",op->price);
jaddnum(item,"volume",dstr(op->basesatoshis));
jaddbits256(item,"txid",op->txid);
jaddnum(item,"vout",op->vout);
jaddbits256(item,"pubkey",op->pubkey);
}
return(item);
}
cJSON *LP_orderbookjson(struct LP_cacheinfo *ptr,int32_t polarity)
struct LP_orderbookentry *LP_orderbookentry(char *base,char *rel,bits256 txid,int32_t vout,bits256 txid2,int32_t vout2,double price,uint64_t basesatoshis,bits256 pubkey)
{
double price; cJSON *item = cJSON_CreateObject();
if ( ptr->Q.satoshis != 0 && ptr->Q.destsatoshis != 0 )
struct LP_orderbookentry *op;
if ( (op= calloc(1,sizeof(*op))) != 0 )
{
price = (double)ptr->Q.destsatoshis / ptr->Q.satoshis;
jaddnum(item,"price",polarity > 0 ? price : 1. / price);
jaddnum(item,"volume",polarity > 0 ? dstr(ptr->Q.satoshis) : dstr(ptr->Q.destsatoshis));
jaddbits256(item,"txid",ptr->Q.txid);
jaddnum(item,"vout",ptr->Q.vout);
op->txid = txid;
op->vout = vout;
op->txid2 = txid2;
op->vout2 = vout2;
op->price = price;
op->basesatoshis = basesatoshis;
op->pubkey = pubkey;
}
return(item);
return(op);
}
int32_t LP_orderbookfind(struct LP_orderbookentry **array,int32_t num,bits256 txid,int32_t vout)
{
int32_t i;
for (i=0; 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(num);
}
char *LP_orderbook(char *base,char *rel)
{
uint32_t now,i; struct LP_cacheinfo *ptr,*tmp,**bids = 0,**asks = 0; cJSON *retjson,*array; int32_t numbids=0,numasks=0;
uint32_t now,i; struct LP_priceinfo *basepp=0,*relpp=0; struct LP_orderbookentry **bids = 0,**asks = 0; cJSON *retjson,*array; int32_t numbids=0,numasks=0,cachenumbids,cachenumasks,baseid,relid;
if ( (basepp= LP_priceinfofind(base)) == 0 || (relpp= LP_priceinfofind(rel)) == 0 )
return(clonestr("{\"error\":\"base or rel not added\"}"));
baseid = basepp->ind;
relid = relpp->ind;
now = (uint32_t)time(NULL);
HASH_ITER(hh,LP_cacheinfos,ptr,tmp)
/*struct LP_cacheinfo *ptr,*tmp;
HASH_ITER(hh,LP_cacheinfos,ptr,tmp)
{
if ( ptr->timestamp < now-60 || ptr->price == 0. )
if ( ptr->timestamp < now-3600*2 || ptr->price == 0. )
continue;
if ( strcmp(ptr->Q.srccoin,base) == 0 && strcmp(ptr->Q.destcoin,rel) == 0 )
{
asks = realloc(asks,sizeof(*asks) * (numasks+1));
asks[numasks++] = ptr;
if ( (op= LP_orderbookentry(base,rel,ptr->Q.txid,ptr->Q.vout,ptr->Q.txid2,ptr->Q.vout2,ptr->price,ptr->Q.satoshis,ptr->Q.srchash)) != 0 )
asks[numasks++] = op;
}
else if ( strcmp(ptr->Q.srccoin,rel) == 0 && strcmp(ptr->Q.destcoin,base) == 0 )
{
bids = realloc(bids,sizeof(*bids) * (numbids+1));
bids[numbids++] = ptr;
if ( (op= LP_orderbookentry(base,rel,ptr->Q.txid,ptr->Q.vout,ptr->Q.txid2,ptr->Q.vout2,1./ptr->price,ptr->Q.satoshis,ptr->Q.srchash)) != 0 )
bids[numbids++] = op;
}
}
}*/
cachenumbids = numbids, cachenumasks = numasks;
//printf("start cache.(%d %d) numbids.%d numasks.%d\n",cachenumbids,cachenumasks,numbids,numasks);
numasks = LP_orderbook_utxoentries(now,1,base,rel,&asks,numasks,cachenumasks);
numbids = LP_orderbook_utxoentries(now,-1,rel,base,&bids,numbids,cachenumbids);
retjson = cJSON_CreateObject();
array = cJSON_CreateArray();
if ( numbids > 1 )
qsort(bids,numbids,sizeof(*bids),_cmp_orderbookrev);
qsort(bids,numbids,sizeof(*bids),_cmp_orderbook);
if ( numasks > 1 )
{
for (i=0; 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++)
jaddi(array,LP_orderbookjson(bids[i],-1));
{
jaddi(array,LP_orderbookjson(bids[i]));
free(bids[i]);
bids[i] = 0;
}
jadd(retjson,"bids",array);
jaddnum(retjson,"numbids",numbids);
array = cJSON_CreateArray();
if ( numasks > 1 )
qsort(asks,numasks,sizeof(*asks),_cmp_orderbook);
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);
jaddnum(retjson,"numasks",numasks);
jaddstr(retjson,"base",base);
jaddstr(retjson,"rel",rel);
jaddnum(retjson,"timestamp",now);
if ( bids != 0 )
free(bids);
if ( asks != 0 )
free(asks);
return(jprint(retjson,1));
}
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);
}
char *LP_pricestr(char *base,char *rel)
char *LP_pricestr(char *base,char *rel,double origprice)
{
double price = 0.; cJSON *retjson;
cJSON *retjson; double price = 0.;
if ( base != 0 && base[0] != 0 && rel != 0 && rel[0] != 0 )
{
price = LP_price(base,rel);
if ( price != 0. )
if ( origprice > SMALLVAL && origprice < price )
price = origprice;
}
if ( price > SMALLVAL )
{
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"method","postprice");
jaddbits256(retjson,"pubkey",LP_mypubkey);
jaddstr(retjson,"base",base);
jaddstr(retjson,"rel",rel);
jaddnum(retjson,"price",price);
@ -361,7 +666,24 @@ char *LP_pricestr(char *base,char *rel)
} else return(clonestr("{\"error\":\"cant find baserel pair\"}"));
}
void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32])
{
LP_priceinfoupdate(base,rel,price);
}
void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price)
{
struct LP_priceinfo *basepp,*relpp; struct LP_pubkeyinfo *pubp; char str[65];
if ( price > SMALLVAL && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
printf("PRICEFEED UPDATE.(%s/%s) %.8f %s\n",base,rel,price,bits256_str(str,pubkey));
if ( (pubp= LP_pubkeyadd(pubkey)) != 0 )
{
pubp->matrix[basepp->ind][relpp->ind] = price;
pubp->timestamp = (uint32_t)time(NULL);
} else printf("error creating pubkey entry\n");
} else printf("error finding %s/%s %.8f\n",base,rel,price);
}

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));
if ( bits256_nonz(swap->I.pubAm) != 0 && bits256_nonz(swap->I.pubBn) != 0 )
{
basilisk_alicescript(redeemscript,&len,script,0,coinaddr,swap->alicecoin.p2shtype,swap->I.pubAm,swap->I.pubBn);
basilisk_alicescript(redeemscript,&len,script,0,coinaddr,swap->alicecoin.taddr,swap->alicecoin.p2shtype,swap->I.pubAm,swap->I.pubBn);
LP_importaddress(swap->alicecoin.symbol,coinaddr);
fprintf(fp,",\"Apayment\":\"%s\"",coinaddr);
}
@ -427,13 +427,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
if ( bits256_nonz(privkey) != 0 )
{
privAm = privkey;
printf("set privAm <- %s\n",bits256_str(str,privAm));
//printf("set privAm <- %s\n",bits256_str(str,privAm));
}
privkey = jbits256(item,"privBn");
if ( bits256_nonz(privkey) != 0 )
{
privBn = privkey;
printf("set privBn <- %s\n",bits256_str(str,privBn));
//printf("set privBn <- %s\n",bits256_str(str,privBn));
}
expiration = juint(item,"expiration");
state = jint(item,"state");
@ -554,7 +554,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
} else if ( finishedflag == 0 )
printf("%s not finished\n",fname);
}
printf("alicepayment.%s bobpayment.%s bobdeposit.%s\n",alicepaymentaddr,bobpaymentaddr,bobdepositaddr);
//printf("alicepayment.%s bobpayment.%s bobdeposit.%s\n",alicepaymentaddr,bobpaymentaddr,bobdepositaddr);
//printf("iambob.%d src.%s dest.%s bob.%s alice.%s pubA0.(%s)\n",iambob,src,dest,bobcoin,alicecoin,bits256_str(str,pubA0));
Adestaddr[0] = destaddr[0] = 0;
Adest = Bdest = AAdest = ABdest = 0;
@ -568,12 +568,12 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
{
if ( (alice= LP_coinfind(alicecoin)) != 0 )
{
bitcoin_address(Adestaddr,alice->pubtype,pubkey33,33);
bitcoin_address(Adestaddr,alice->taddr,alice->pubtype,pubkey33,33);
AAdest = Adestaddr;
}
if ( (bob= LP_coinfind(bobcoin)) != 0 )
{
bitcoin_address(destaddr,bob->pubtype,pubkey33,33);
bitcoin_address(destaddr,bob->taddr,bob->pubtype,pubkey33,33);
Adest = destaddr;
}
}
@ -581,12 +581,12 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
{
if ( (bob= LP_coinfind(bobcoin)) != 0 )
{
bitcoin_address(destaddr,bob->pubtype,pubkey33,33);
bitcoin_address(destaddr,bob->taddr,bob->pubtype,pubkey33,33);
Bdest = destaddr;
}
if ( (alice= LP_coinfind(alicecoin)) != 0 )
{
bitcoin_address(Adestaddr,alice->pubtype,pubkey33,33);
bitcoin_address(Adestaddr,alice->taddr,alice->pubtype,pubkey33,33);
ABdest = Adestaddr;
}
}
@ -625,18 +625,18 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
{
char privaddr[64]; uint8_t privpub33[33];
bitcoin_pubkey33(ctx,privpub33,myprivs[0]);
bitcoin_address(privaddr,60,privpub33,33);
bitcoin_address(privaddr,0,60,privpub33,33);
printf("alicespend len.%d redeemlen.%d priv0addr.(%s) priv0.(%s)\n",len,redeemlen,privaddr,bits256_str(str,myprivs[0]));
}
for (j=0; j<32; j++)
rev.bytes[j] = myprivs[0].bytes[31 - j];
if ( (txbytes[BASILISK_ALICESPEND]= basilisk_swap_bobtxspend(&signedtxid,txfee,"alicespend",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,0,pubkey33,1,expiration,&values[BASILISK_ALICESPEND],0,0,bobpaymentaddr,1)) != 0 )
if ( (txbytes[BASILISK_ALICESPEND]= basilisk_swap_bobtxspend(&signedtxid,txfee,"alicespend",bobcoin,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,0,pubkey33,1,expiration,&values[BASILISK_ALICESPEND],0,0,bobpaymentaddr,1)) != 0 )
printf("alicespend.(%s)\n",txbytes[BASILISK_ALICESPEND]);
}
}
if ( txbytes[BASILISK_ALICESPEND] != 0 )
{
txids[BASILISK_ALICESPEND] = LP_broadcast("alicespend",bobcoin,txbytes[BASILISK_ALICESPEND]);
txids[BASILISK_ALICESPEND] = LP_broadcast("alicespend",bobcoin,txbytes[BASILISK_ALICESPEND],zero);
if ( bits256_nonz(txids[BASILISK_ALICESPEND]) != 0 ) // tested
{
sentflags[BASILISK_ALICESPEND] = 1;
@ -655,13 +655,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
if ( redeemlen > 0 )
{
len = basilisk_swapuserdata(userdata,zero,1,myprivs[0],redeemscript,redeemlen);
if ( (txbytes[BASILISK_ALICECLAIM]= basilisk_swap_bobtxspend(&signedtxid,txfee,"aliceclaim",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,0,pubkey33,0,expiration,&values[BASILISK_ALICECLAIM],0,0,bobdepositaddr,1)) != 0 )
if ( (txbytes[BASILISK_ALICECLAIM]= basilisk_swap_bobtxspend(&signedtxid,txfee,"aliceclaim",bobcoin,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,0,pubkey33,0,expiration,&values[BASILISK_ALICECLAIM],0,0,bobdepositaddr,1)) != 0 )
printf("privBn.(%s) aliceclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICECLAIM]);
}
}
if ( txbytes[BASILISK_ALICECLAIM] != 0 )
{
txids[BASILISK_ALICECLAIM] = LP_broadcast("aliceclaim",bobcoin,txbytes[BASILISK_ALICECLAIM]);
txids[BASILISK_ALICECLAIM] = LP_broadcast("aliceclaim",bobcoin,txbytes[BASILISK_ALICECLAIM],zero);
if ( bits256_nonz(txids[BASILISK_ALICECLAIM]) != 0 ) // tested
{
sentflags[BASILISK_ALICECLAIM] = 1;
@ -677,13 +677,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
privBn = basilisk_swap_privBn_extract(&txids[BASILISK_BOBREFUND],bobcoin,txids[BASILISK_BOBDEPOSIT],privBn);
if ( bits256_nonz(txids[BASILISK_ALICEPAYMENT]) != 0 && bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 )
{
if ( (txbytes[BASILISK_ALICERECLAIM]= basilisk_swap_Aspend("alicereclaim",alicecoin,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_ALICERECLAIM],alicepaymentaddr)) != 0 )
if ( (txbytes[BASILISK_ALICERECLAIM]= basilisk_swap_Aspend("alicereclaim",alicecoin,alice->taddr,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_ALICERECLAIM],alicepaymentaddr)) != 0 )
printf("privBn.(%s) alicereclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICERECLAIM]);
}
}
if ( txbytes[BASILISK_ALICERECLAIM] != 0 )
{
txids[BASILISK_ALICERECLAIM] = LP_broadcast("alicereclaim",alicecoin,txbytes[BASILISK_ALICERECLAIM]);
txids[BASILISK_ALICERECLAIM] = LP_broadcast("alicereclaim",alicecoin,txbytes[BASILISK_ALICERECLAIM],zero);
if ( bits256_nonz(txids[BASILISK_ALICERECLAIM]) != 0 ) // tested
{
sentflags[BASILISK_ALICERECLAIM] = 1;
@ -707,13 +707,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
}
if ( bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 )
{
if ( (txbytes[BASILISK_BOBSPEND]= basilisk_swap_Aspend("bobspend",alicecoin,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_BOBSPEND],alicepaymentaddr)) != 0 )
if ( (txbytes[BASILISK_BOBSPEND]= basilisk_swap_Aspend("bobspend",alicecoin,alice->taddr,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_BOBSPEND],alicepaymentaddr)) != 0 )
printf("bobspend.(%s)\n",txbytes[BASILISK_BOBSPEND]);
}
}
if ( txbytes[BASILISK_BOBSPEND] != 0 )
{
txids[BASILISK_BOBSPEND] = LP_broadcast("bobspend",alicecoin,txbytes[BASILISK_BOBSPEND]);
txids[BASILISK_BOBSPEND] = LP_broadcast("bobspend",alicecoin,txbytes[BASILISK_BOBSPEND],zero);
if ( bits256_nonz(txids[BASILISK_BOBSPEND]) != 0 ) // tested
{
sentflags[BASILISK_BOBSPEND] = 1;
@ -731,7 +731,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
if ( redeemlen > 0 )
{
len = basilisk_swapuserdata(userdata,zero,1,myprivs[1],redeemscript,redeemlen);
if ( (txbytes[BASILISK_BOBRECLAIM]= basilisk_swap_bobtxspend(&signedtxid,txfee,"bobrefund",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[1],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,0,pubkey33,0,expiration,&values[BASILISK_BOBRECLAIM],0,0,bobpaymentaddr,1)) != 0 )
if ( (txbytes[BASILISK_BOBRECLAIM]= basilisk_swap_bobtxspend(&signedtxid,txfee,"bobrefund",bobcoin,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[1],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,0,pubkey33,0,expiration,&values[BASILISK_BOBRECLAIM],0,0,bobpaymentaddr,1)) != 0 )
{
int32_t z;
for (z=0; z<20; z++)
@ -742,7 +742,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
}
if ( txbytes[BASILISK_BOBRECLAIM] != 0 )
{
txids[BASILISK_BOBRECLAIM] = LP_broadcast("bobreclaim",bobcoin,txbytes[BASILISK_BOBRECLAIM]);
txids[BASILISK_BOBRECLAIM] = LP_broadcast("bobreclaim",bobcoin,txbytes[BASILISK_BOBRECLAIM],zero);
if ( bits256_nonz(txids[BASILISK_BOBRECLAIM]) != 0 ) // tested
{
sentflags[BASILISK_BOBRECLAIM] = 1;
@ -761,12 +761,12 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
vcalc_sha256(0,secretBn256,privBn.bytes,sizeof(privBn));
redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,dlocktime,pubA0,pubB0,pubB1,privAm,privBn,secretAm,secretAm256,secretBn,secretBn256);
len = basilisk_swapuserdata(userdata,privBn,0,myprivs[0],redeemscript,redeemlen);
if ( (txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend(&signedtxid,txfee,"bobrefund",bobcoin,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,0,pubkey33,1,expiration,&values[BASILISK_BOBREFUND],0,0,bobdepositaddr,1)) != 0 )
if ( (txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend(&signedtxid,txfee,"bobrefund",bobcoin,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,0,pubkey33,1,expiration,&values[BASILISK_BOBREFUND],0,0,bobdepositaddr,1)) != 0 )
printf("pubB1.(%s) bobrefund.(%s)\n",bits256_str(str,pubB1),txbytes[BASILISK_BOBREFUND]);
}
if ( txbytes[BASILISK_BOBREFUND] != 0 )
{
txids[BASILISK_BOBREFUND] = LP_broadcast("bobrefund",bobcoin,txbytes[BASILISK_BOBREFUND]);
txids[BASILISK_BOBREFUND] = LP_broadcast("bobrefund",bobcoin,txbytes[BASILISK_BOBREFUND],zero);
if ( bits256_nonz(txids[BASILISK_BOBREFUND]) != 0 ) // tested
{
sentflags[BASILISK_BOBREFUND] = 1;
@ -867,6 +867,24 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
if ( finishedflag != 0 )
jaddstr(item,"status","finished");
else jaddstr(item,"status","pending");
if ( bits256_nonz(paymentspent) == 0 )
{
if ( bits256_nonz(txids[BASILISK_ALICESPEND]) != 0 )
paymentspent = txids[BASILISK_ALICESPEND];
else paymentspent = txids[BASILISK_BOBRECLAIM];
}
if ( bits256_nonz(depositspent) == 0 )
{
if ( bits256_nonz(txids[BASILISK_BOBREFUND]) != 0 )
depositspent = txids[BASILISK_BOBREFUND];
else depositspent = txids[BASILISK_ALICECLAIM];
}
if ( bits256_nonz(Apaymentspent) == 0 )
{
if ( bits256_nonz(txids[BASILISK_BOBSPEND]) != 0 )
Apaymentspent = txids[BASILISK_BOBSPEND];
else Apaymentspent = txids[BASILISK_ALICERECLAIM];
}
bits256_str(str,paymentspent), jaddbits256(item,"paymentspent",paymentspent);
bits256_str(str,Apaymentspent), jaddbits256(item,"Apaymentspent",Apaymentspent);
bits256_str(str,depositspent), jaddbits256(item,"depositspent",depositspent);
@ -888,7 +906,8 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
char *basilisk_swaplist()
{
char fname[512],*status; FILE *fp; cJSON *item,*retjson,*array,*totalsobj; uint32_t quoteid,requestid; int64_t KMDtotals[16],BTCtotals[16],Btotal,Ktotal; int32_t i;
char fname[512]; FILE *fp; cJSON *item,*retjson,*array,*totalsobj; uint32_t quoteid,requestid; int64_t KMDtotals[16],BTCtotals[16],Btotal,Ktotal; int32_t i;
portable_mutex_lock(&LP_swaplistmutex);
memset(KMDtotals,0,sizeof(KMDtotals));
memset(BTCtotals,0,sizeof(BTCtotals));
//,statebits; int32_t optionduration; struct basilisk_request R; bits256 privkey;
@ -914,8 +933,8 @@ char *basilisk_swaplist()
if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid)) != 0 )
{
jaddi(array,item);
if ( 1 && (status= jstr(item,"status")) != 0 && strcmp(status,"pending") == 0 )
break;
//if ( (status= jstr(item,"status")) != 0 && strcmp(status,"pending") == 0 )
// break;
}
}
}
@ -949,6 +968,36 @@ char *basilisk_swaplist()
jaddi(array,linfo_json(&myinfo->linfos[i]));
}
jadd(retjson,"quotes",array);*/
portable_mutex_unlock(&LP_swaplistmutex);
return(jprint(retjson,1));
}
char *basilisk_swapentry(uint32_t requestid,uint32_t quoteid)
{
char *liststr,*retstr = 0; cJSON *retjson,*array,*item; int32_t i,n;
if ( (liststr= basilisk_swaplist()) != 0 )
{
if ( (retjson= cJSON_Parse(liststr)) != 0 )
{
if ( (array= jarray(&n,retjson,"swaps")) != 0 )
{
for (i=0; 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);
}

230
iguana/exchanges/LP_rpc.c

@ -17,45 +17,167 @@
// LP_rpc.c
// 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 url[512],*retstr;
char url[512];
sprintf(url,"http://%s:%u/api/stats/getpeers?ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,profitmargin,numpeers,numutxos);
//printf("send.(%s)\n",url);
retstr = issue_curl(url);
//printf("GETPEERS.(%s)\n",retstr);
return(retstr);
return(LP_issue_curl("getpeers",destip,port,url));
}
char *issue_LP_getutxos(char *destip,uint16_t destport,char *coin,int32_t lastn,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos)
{
char url[512];
sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,coin,lastn,ipaddr,port,profitmargin,numpeers,numutxos);
return(issue_curl(url));
return(LP_issue_curl("getutxos",destip,destport,url));
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
}
char *issue_LP_clientgetutxos(char *destip,uint16_t destport,char *coin,int32_t lastn)
{
char url[512];
char url[512];//,*retstr;
sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=127.0.0.1&port=0",destip,destport,coin,lastn);
//printf("getutxos.(%s)\n",url);
return(issue_curl(url));
return(LP_issue_curl("clientgetutxos",destip,destport,url));
//retstr = issue_curlt(url,LP_HTTP_TIMEOUT);
//printf("%s clientgetutxos.(%s)\n",url,retstr);
//return(retstr);
}
char *issue_LP_notify(char *destip,uint16_t destport,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos)
{
char url[512];
char url[512],*retstr;
if ( (retstr= LP_isitme(destip,destport)) != 0 )
{
free(retstr);
return(0);
}
sprintf(url,"http://%s:%u/api/stats/notify?ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,profitmargin,numpeers,numutxos);
return(issue_curl(url));
return(LP_issue_curl("notify",destip,destport,url));
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
}
char *issue_LP_notifyutxo(char *destip,uint16_t destport,struct LP_utxoinfo *utxo)
{
char url[4096],str[65],str2[65];
sprintf(url,"http://%s:%u/api/stats/notifyutxo?ipaddr=%s&port=%u&profit=%.6f&coin=%s&txid=%s&vout=%d&value=%.8f&txid2=%s&vout2=%d&value2=%.8f&script=%s&address=%s",destip,destport,utxo->ipaddr,utxo->port,utxo->profitmargin,utxo->coin,bits256_str(str,utxo->txid),utxo->vout,dstr(utxo->satoshis),bits256_str(str2,utxo->txid2),utxo->vout2,dstr(utxo->satoshis2),utxo->spendscript,utxo->coinaddr);
if ( strlen(url) > 1024 )
printf("WARNING long url.(%s)\n",url);
return(issue_curl(url));
char url[4096],str[65],str2[65],str3[65],*retstr; struct _LP_utxoinfo u; uint64_t val,val2;
if ( (retstr= LP_isitme(destip,destport)) != 0 )
{
free(retstr);
return(0);
}
if ( utxo->iambob == 0 )
{
printf("issue_LP_notifyutxo trying to send Alice %s/v%d\n",bits256_str(str,utxo->payment.txid),utxo->payment.vout);
return(0);
}
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee;
if ( LP_iseligible(&val,&val2,utxo->iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,u.txid,u.vout,utxo->pubkey) > 0 )
{
sprintf(url,"http://%s:%u/api/stats/notified?iambob=%d&pubkey=%s&profit=%.6f&coin=%s&txid=%s&vout=%d&value=%llu&txid2=%s&vout2=%d&value2=%llu&script=%s&address=%s&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 )
printf("WARNING long url.(%s)\n",url);
return(LP_issue_curl("notifyutxo",destip,destport,url));
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
}
else
{
printf("issue_LP_notifyutxo: ineligible utxo iambob.%d %.8f %.8f\n",utxo->iambob,dstr(val),dstr(val2));
return(0);
}
}
char *issue_LP_register(char *destip,uint16_t destport,bits256 pubkey,char *ipaddr,uint16_t pushport)
{
char url[512],str[65];//*retstr;
sprintf(url,"http://%s:%u/api/stats/register?client=%s&pushaddr=%s&pushport=%u",destip,destport,bits256_str(str,pubkey),ipaddr,pushport);
return(LP_issue_curl("register",destip,destport,url));
//retstr = issue_curlt(url,LP_HTTP_TIMEOUT);
//printf("getutxo.(%s) -> (%s)\n",url,retstr!=0?retstr:"");
//return(retstr);
}
char *issue_LP_psock(char *destip,uint16_t destport,int32_t ispaired)
{
char url[512];
sprintf(url,"http://%s:%u/api/stats/psock?ispaired=%d",destip,destport,ispaired);
return(LP_issue_curl("psock",destip,destport,url));
//retstr = issue_curlt(url,LP_HTTP_TIMEOUT);
//printf("getutxo.(%s) -> (%s)\n",url,retstr!=0?retstr:"");
//return(retstr);
}
uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired)
{
uint16_t publicport = 0; char *retstr,*addr; cJSON *retjson; struct LP_peerinfo *peer,*tmp;
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
connectaddr[0] = publicaddr[0] = 0;
if ( peer->errors < LP_MAXPEER_ERRORS && (retstr= issue_LP_psock(peer->ipaddr,peer->port,ispaired)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (addr= jstr(retjson,"publicaddr")) != 0 )
safecopy(publicaddr,addr,128);
if ( (addr= jstr(retjson,"connectaddr")) != 0 )
safecopy(connectaddr,addr,128);
if ( publicaddr[0] != 0 && connectaddr[0] != 0 )
publicport = juint(retjson,"publicport");
free_json(retjson);
}
printf("got.(%s) connect.%s public.%s\n",retstr,connectaddr,publicaddr);
free(retstr);
}
if ( publicport != 0 )
break;
}
return(publicport);
}
char *issue_LP_lookup(char *destip,uint16_t destport,bits256 pubkey)
{
char url[512],str[65];
sprintf(url,"http://%s:%u/api/stats/lookup?client=%s",destip,destport,bits256_str(str,pubkey));
//printf("getutxo.(%s)\n",url);
return(LP_issue_curl("lookup",destip,destport,url));
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
}
char *issue_LP_getprices(char *destip,uint16_t destport)
{
char url[512];
sprintf(url,"http://%s:%u/api/stats/getprices",destip,destport);
//printf("getutxo.(%s)\n",url);
return(LP_issue_curl("getprices",destip,destport,url));
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
}
cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params)
@ -71,8 +193,9 @@ cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params)
retjson = cJSON_Parse(retstr);
free(retstr);
}
//usleep(1000);
//printf("dpow_gettxout.(%s)\n",retstr);
}
} else printf("bitcoin_json cant talk to NULL coin\n");
return(retjson);
}
@ -87,10 +210,16 @@ cJSON *LP_getinfo(char *symbol)
return(bitcoin_json(coin,"getinfo","[]"));
}
cJSON *LP_getmempool(char *symbol)
{
struct iguana_info *coin = LP_coinfind(symbol);
return(bitcoin_json(coin,"getrawmempool","[]"));
}
cJSON *LP_gettxout(char *symbol,bits256 txid,int32_t vout)
{
char buf[128],str[65]; struct iguana_info *coin = LP_coinfind(symbol);
sprintf(buf,"\"%s\", %d",bits256_str(str,txid),vout);
sprintf(buf,"\"%s\", %d, true",bits256_str(str,txid),vout);
return(bitcoin_json(coin,"gettxout",buf));
}
@ -101,6 +230,20 @@ cJSON *LP_gettx(char *symbol,bits256 txid)
return(bitcoin_json(coin,"getrawtransaction",buf));
}
cJSON *LP_getblock(char *symbol,bits256 txid)
{
char buf[128],str[65]; struct iguana_info *coin = LP_coinfind(symbol);
sprintf(buf,"[\"%s\"]",bits256_str(str,txid));
return(bitcoin_json(coin,"getblock",buf));
}
cJSON *LP_getblockhashstr(char *symbol,char *blockhashstr)
{
char buf[128]; struct iguana_info *coin = LP_coinfind(symbol);
sprintf(buf,"[\"%s\"]",blockhashstr);
return(bitcoin_json(coin,"getblock",buf));
}
cJSON *LP_listunspent(char *symbol,char *coinaddr)
{
char buf[128]; struct iguana_info *coin = LP_coinfind(symbol);
@ -152,15 +295,15 @@ int32_t LP_importaddress(char *symbol,char *address)
sprintf(buf,"[\"%s\", \"%s\", false]",address,address);
if ( (retstr= bitcoind_passthru(symbol,coin->serverport,coin->userpass,"importaddress",buf)) != 0 )
{
printf("importaddress.(%s %s) -> (%s)\n",symbol,address,retstr);
//printf("importaddress.(%s %s) -> (%s)\n",symbol,address,retstr);
free(retstr);
} else printf("importaddress.(%s %s)\n",symbol,address);
} //else printf("importaddress.(%s %s)\n",symbol,address);
return(1);
}
double LP_getestimatedrate(char *symbol)
{
char buf[512],*retstr; double rate = 200; struct iguana_info *coin = LP_coinfind(symbol);
char buf[512],*retstr; double rate = 20; struct iguana_info *coin = LP_coinfind(symbol);
if ( coin != 0 )
{
sprintf(buf,"[%d]",3);
@ -168,7 +311,7 @@ double LP_getestimatedrate(char *symbol)
{
if ( retstr[0] != '-' )
{
rate = atof(retstr) / 1024.;
coin->estimatedrate = rate = atof(retstr) / 1024.;
printf("estimated rate.(%s) %s -> %.8f\n",symbol,retstr,rate);
}
free(retstr);
@ -185,6 +328,19 @@ uint64_t LP_txfee(char *symbol)
return(txfee);
}
char *LP_blockhashstr(char *symbol,int32_t height)
{
cJSON *array; char *paramstr,*retstr; struct iguana_info *coin = LP_coinfind(symbol);
if ( coin == 0 )
return(0);
array = cJSON_CreateArray();
jaddinum(array,height);
paramstr = jprint(array,1);
retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"getblockhash",paramstr);
free(paramstr);
return(retstr);
}
char *LP_sendrawtransaction(char *symbol,char *signedtx)
{
cJSON *array; char *paramstr,*retstr; struct iguana_info *coin = LP_coinfind(symbol);
@ -194,7 +350,7 @@ char *LP_sendrawtransaction(char *symbol,char *signedtx)
jaddistr(array,signedtx);
paramstr = jprint(array,1);
retstr = bitcoind_passthru(symbol,coin->serverport,coin->userpass,"sendrawtransaction",paramstr);
printf(">>>>>>>>>>> %s dpow_sendrawtransaction.(%s) -> (%s)\n",coin->symbol,paramstr,retstr);
//printf(">>>>>>>>>>> %s dpow_sendrawtransaction.(%s) -> (%s)\n",coin->symbol,paramstr,retstr);
free(paramstr);
return(retstr);
}
@ -238,3 +394,31 @@ char *LP_signrawtx(char *symbol,bits256 *signedtxidp,int32_t *completedp,cJSON *
free(paramstr);
return(signedtx);
}
cJSON *LP_blockjson(int32_t *heightp,char *symbol,char *blockhashstr,int32_t height)
{
cJSON *json = 0; int32_t flag = 0;
if ( blockhashstr == 0 )
blockhashstr = LP_blockhashstr(symbol,height), flag = 1;
if ( blockhashstr != 0 )
{
if ( (json= LP_getblockhashstr(symbol,blockhashstr)) != 0 )
{
if ( *heightp != 0 )
{
*heightp = juint(json,"height");
if ( height >= 0 && *heightp != height )
{
printf("unexpected height %d vs %d\n",*heightp,height);
*heightp = -1;
free_json(json);
json = 0;
}
}
}
if ( flag != 0 && blockhashstr != 0 )
free(blockhashstr);
}
return(json);
}

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))
{
uint8_t *ptr; bits256 srchash,desthash; uint32_t crc32,_msgbits,quoteid; int32_t i,size,offset,retval = -1; struct basilisk_swapmessage *mp = 0;
while ( (size= nn_recv(swap->subsock,&ptr,NN_MSG,0)) >= 0 )
while ( (size= nn_recv(swap->subsock,&ptr,NN_MSG,NN_DONTWAIT)) >= 0 )
{
swap->lasttime = (uint32_t)time(NULL);
memset(srchash.bytes,0,sizeof(srchash));
@ -404,18 +404,12 @@ cJSON *LP_createvins(struct basilisk_rawtx *dest,struct vin_info *V,struct basil
int32_t _basilisk_rawtx_gen(char *str,uint32_t swapstarted,uint8_t *pubkey33,int32_t iambob,int32_t lockinputs,struct basilisk_rawtx *rawtx,uint32_t locktime,uint8_t *script,int32_t scriptlen,int64_t txfee,int32_t minconf,int32_t delay,bits256 privkey)
{
char scriptstr[1024],wifstr[256],coinaddr[64],*signedtx,*rawtxbytes; uint32_t basilisktag; int32_t retval = -1; cJSON *vins,*privkeys,*addresses,*valsobj; struct vin_info *V;
//bitcoin_address(coinaddr,rawtx->coin->chain->pubtype,myinfo->persistent_pubkey33,33);
if ( rawtx->coin->changeaddr[0] == 0 )
{
bitcoin_address(rawtx->coin->changeaddr,rawtx->coin->pubtype,pubkey33,33);
printf("set change address.(%s)\n",rawtx->coin->changeaddr);
}
init_hexbytes_noT(scriptstr,script,scriptlen);
basilisktag = (uint32_t)rand();
valsobj = cJSON_CreateObject();
jaddstr(valsobj,"coin",rawtx->coin->symbol);
jaddstr(valsobj,"spendscript",scriptstr);
jaddstr(valsobj,"changeaddr",rawtx->coin->changeaddr);
jaddstr(valsobj,"changeaddr",rawtx->coin->smartaddr);
jadd64bits(valsobj,"satoshis",rawtx->I.amount);
if ( strcmp(rawtx->coin->symbol,"BTC") == 0 && txfee > 0 && txfee < 50000 )
txfee = 50000;
@ -990,7 +984,6 @@ cJSON *basilisk_privkeyarray(struct iguana_info *coin,cJSON *vins)
{
cJSON *privkeyarray,*item,*sobj; struct iguana_waddress *waddr; struct iguana_waccount *wacct; char coinaddr[64],account[128],wifstr[64],str[65],typestr[64],*hexstr; uint8_t script[1024]; int32_t i,n,len,vout; bits256 txid,privkey; double bidasks[2];
privkeyarray = cJSON_CreateArray();
//printf("%s persistent.(%s) (%s) change.(%s) scriptstr.(%s)\n",coin->symbol,myinfo->myaddr.BTC,coinaddr,coin->changeaddr,scriptstr);
if ( (n= cJSON_GetArraySize(vins)) > 0 )
{
for (i=0; 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);
}*/
/*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);
}*/

356
iguana/exchanges/LP_swap.c

@ -17,22 +17,12 @@
// LP_swap.c
// marketmaker
//
/*
resume handling: list of tx broadcast, tx pending + required items, reconnect state machine or have statemachine assume off by one or state/otherstate specific handling
make sure to broadcast deposit before claiming refund, or to just skip it if neither is done
*/
// Todo: monitor blockchains, ie complete extracting scriptsig
// mode to autocreate required outputs
// more better LP commands
// depends on just three external functions:
// - basilisk_sendrawtransaction(coin,signedtx);
// - basilisk_value(rawtx->coin,0,0,myinfo->myaddr.persistent,argjson,0)
// basilisk_bitcoinrawtx(rawtx->coin,"",basilisktag,jint(valsobj,"timeout"),valsobj,V)
// included from basilisk.c
/* https://bitcointalk.org/index.php?topic=1340621.msg13828271#msg13828271
https://bitcointalk.org/index.php?topic=1364951
@ -130,6 +120,8 @@ void basilisk_rawtx_purge(struct basilisk_rawtx *rawtx)
void basilisk_swap_finished(struct basilisk_swap *swap)
{
int32_t i;
if ( swap->utxo != 0 && swap->sentflag == 0 )
LP_availableset(swap->utxo);
swap->I.finished = (uint32_t)time(NULL);
// save to permanent storage
basilisk_rawtx_purge(&swap->bobdeposit);
@ -148,6 +140,8 @@ void basilisk_swap_finished(struct basilisk_swap *swap)
free(swap->messages[i].data), swap->messages[i].data = 0;
free(swap->messages), swap->messages = 0;
swap->nummessages = 0;
if ( swap->N.pair >= 0 )
nn_close(swap->N.pair), swap->N.pair = -1;
}
uint32_t basilisk_quoteid(struct basilisk_request *rp)
@ -257,6 +251,11 @@ int32_t LP_choosei_verify(struct basilisk_swap *swap,uint8_t *data,int32_t datal
vcalc_sha256(0,swap->I.secretAm256,swap->I.privAm.bytes,sizeof(swap->I.privAm));
swap->I.pubAm = bitcoin_pubkey33(swap->ctx,pubkey33,swap->I.privAm);
printf("set privAm.%s %s\n",bits256_str(str,swap->I.privAm),bits256_str(str2,*(bits256 *)swap->I.secretAm256));
swap->bobdeposit.I.pubkey33[0] = 2;
swap->bobpayment.I.pubkey33[0] = 2;
for (i=0; i<32; i++)
swap->bobpayment.I.pubkey33[i+1] = swap->bobdeposit.I.pubkey33[i+1] = swap->I.pubA0.bytes[i];
printf("SET bobdeposit pubkey33.(02%s)\n",bits256_str(str,swap->I.pubA0));
//basilisk_bobscripts_set(swap,0);
}
return(0);
@ -404,13 +403,15 @@ int32_t LP_waitfor(int32_t pairsock,struct basilisk_swap *swap,int32_t timeout,i
void *data; int32_t datalen,retval = -1; uint32_t expiration = (uint32_t)time(NULL) + timeout;
while ( time(NULL) < expiration )
{
//printf("start wait\n");
if ( (datalen= nn_recv(pairsock,&data,NN_MSG,0)) >= 0 )
{
printf("wait for got.%d\n",datalen);
//printf("wait for got.%d\n",datalen);
retval = (*verify)(swap,data,datalen);
nn_freemsg(data);
//printf("retval.%d\n",retval);
return(retval);
} else printf("error nn_recv\n");
} // else printf("error nn_recv\n");
}
printf("waitfor timedout\n");
return(retval);
@ -419,30 +420,39 @@ int32_t LP_waitfor(int32_t pairsock,struct basilisk_swap *swap,int32_t timeout,i
int32_t LP_waitsend(char *statename,int32_t timeout,int32_t pairsock,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen,int32_t (*verify)(struct basilisk_swap *swap,uint8_t *data,int32_t datalen),int32_t (*datagen)(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen))
{
int32_t datalen,sendlen,retval = -1;
printf("waitsend.%s\n",statename);
if ( LP_waitfor(pairsock,swap,timeout,verify) == 0 )
{
printf("waited for %s\n",statename);
if ( (datalen= (*datagen)(swap,data,maxlen)) > 0 )
{
if ( (sendlen= nn_send(pairsock,data,datalen,0)) == datalen )
{
printf("sent.%d after waitfor.%s\n",sendlen,statename);
retval = 0;
else printf("send %s error\n",statename);
}
} else printf("didnt get valid data\n");
} else printf("send %s error\n",statename);
} else printf("%s datagen no data\n",statename);
} else printf("didnt get valid data after %d\n",timeout);
return(retval);
}
int32_t LP_sendwait(char *statename,int32_t timeout,int32_t pairsock,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen,int32_t (*verify)(struct basilisk_swap *swap,uint8_t *data,int32_t datalen),int32_t (*datagen)(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen))
{
int32_t datalen,sendlen,retval = -1;
//printf("sendwait.%s\n",statename);
if ( (datalen= (*datagen)(swap,data,maxlen)) > 0 )
{
//printf("generated %d for %s\n",datalen,statename);
if ( (sendlen= nn_send(pairsock,data,datalen,0)) == datalen )
{
//printf("sendwait.%s sent %d\n",statename,sendlen);
if ( LP_waitfor(pairsock,swap,timeout,verify) == 0 )
{
//printf("waited! sendwait.%s sent %d\n",statename,sendlen);
retval = 0;
else printf("didnt get %s\n",statename);
} else printf("didnt get %s\n",statename);
} else printf("send pubkeys error\n");
}
} else printf("no datagen for %s\n",statename);
return(retval);
}
@ -456,7 +466,7 @@ void LP_swapsfp_update(struct basilisk_request *rp)
if ( (swapsfp= fopen(fname,"rb+")) == 0 )
swapsfp = fopen(fname,"wb+");
else fseek(swapsfp,0,SEEK_END);
printf("LIST fp.%p\n",swapsfp);
//printf("LIST fp.%p\n",swapsfp);
}
if ( swapsfp != 0 )
{
@ -477,9 +487,90 @@ struct basilisk_rawtx *LP_swapdata_rawtx(struct basilisk_swap *swap,uint8_t *dat
return(0);
}
int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys)
{
bits256 otherhash,myhash,txid; int32_t i,offset=0,datalen=0,retval=-1,hexlen,n; uint8_t *data; cJSON *txobj,*skey,*vouts,*vout; char *hexstr,redeemaddr[64],checkaddr[64]; uint32_t quoteid,msgbits;
for (i=0; i<32; i++)
otherhash.bytes[i] = recvbuf[offset++];
for (i=0; i<32; i++)
myhash.bytes[i] = recvbuf[offset++];
offset += iguana_rwnum(0,&recvbuf[offset],sizeof(quoteid),&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)
{
uint8_t sendbuf[32768]; int32_t sendlen;
uint8_t sendbuf[32768]; int32_t sendlen,retval = -1;
if ( LP_swapdata_rawtx(swap,data,maxlen,rawtx) != 0 )
{
if ( bits256_nonz(rawtx->I.signedtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 )
@ -496,6 +587,7 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3
sendbuf[sendlen++] = rawtx->I.datalen & 0xff;
sendbuf[sendlen++] = (rawtx->I.datalen >> 8) & 0xff;
sendbuf[sendlen++] = rawtx->I.redeemlen;
//int32_t z; for (z=0; 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);
memcpy(&sendbuf[sendlen],rawtx->txbytes,rawtx->I.datalen), sendlen += rawtx->I.datalen;
if ( rawtx->I.redeemlen > 0 && rawtx->I.redeemlen < 0x100 )
@ -506,7 +598,15 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3
basilisk_dontforget_update(swap,rawtx);
//printf("sendlen.%d datalen.%d redeemlen.%d\n",sendlen,rawtx->datalen,rawtx->redeemlen);
if ( suppress_swapsend == 0 )
return(LP_swapsend(pairsock,swap,msgbits,sendbuf,sendlen,nextbits,rawtx->I.crcs));
{
retval = LP_swapsend(pairsock,swap,msgbits,sendbuf,sendlen,nextbits,rawtx->I.crcs);
if ( LP_waitmempool(rawtx->coin->symbol,rawtx->I.signedtxid,LP_SWAPSTEP_TIMEOUT) < 0 )
{
char str[65]; printf("failed to find %s %s in the mempool?\n",rawtx->name,bits256_str(str,rawtx->I.actualtxid));
retval = -1;
}
return(retval);
}
else
{
printf("suppress swapsend %x\n",msgbits);
@ -520,108 +620,162 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3
return(0);
}
void LP_bobloop(void *_utxo)
int32_t LP_swapwait(uint32_t requestid,uint32_t quoteid,int32_t duration,int32_t sleeptime)
{
char *retstr; cJSON *retjson=0; uint32_t divisor=8,expiration = (uint32_t)(time(NULL) + duration);
printf("wait %d:%d for SWAP.(r%u/q%u) to complete\n",duration,sleeptime,requestid,quoteid);
sleep(10);
if ( sleeptime < divisor*60 )
sleeptime = divisor * 60;
while ( time(NULL) < expiration )
{
if ( (retstr= basilisk_swapentry(requestid,quoteid)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( jstr(retjson,"status") != 0 && strcmp(jstr(retjson,"status"),"finished") == 0 )
break;
free_json(retjson);
retjson = 0;
}
free(retstr);
}
sleep(sleeptime/divisor);
if ( divisor > 1 )
divisor--;
}
if ( retjson != 0 )
{
printf("\n>>>>>>>>>>>>>>>>>>>>>>>>>\nSWAP completed! %u-%u %s\n",requestid,quoteid,jprint(retjson,0));
free_json(retjson);
if ( (retstr= basilisk_swapentry(requestid,quoteid)) != 0 )
{
printf("second call.(%s)\n",retstr);
free(retstr);
}
return(0);
} else return(-1);
}
void LP_bobloop(void *_swap)
{
uint8_t *data; char *retstr; int32_t maxlen; uint32_t expiration; struct basilisk_swap *swap; struct LP_utxoinfo *utxo = _utxo;
uint8_t *data; int32_t maxlen,n; uint32_t expiration; struct basilisk_swap *swap = _swap;
fprintf(stderr,"start swap iambob\n");
maxlen = 1024*1024 + sizeof(*swap);
data = malloc(maxlen);
expiration = (uint32_t)time(NULL) + 10;
while ( (swap= utxo->swap) == 0 && time(NULL) < expiration )
sleep(1);
if ( (utxo->swap= swap) != 0 )
expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT;
if ( swap != 0 )
{
if ( LP_waitsend("pubkeys",10,utxo->pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 )
if ( LP_waitsend("pubkeys",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 )
printf("error waitsend pubkeys\n");
else if ( LP_waitsend("choosei",10,utxo->pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 )
else if ( LP_waitsend("choosei",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 )
printf("error waitsend choosei\n");
else if ( LP_waitsend("mostprivs",10,utxo->pair,swap,data,maxlen,LP_mostprivs_verify,LP_mostprivs_data) < 0 )
else if ( LP_waitsend("mostprivs",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_mostprivs_verify,LP_mostprivs_data) < 0 )
printf("error waitsend mostprivs\n");
else if ( basilisk_bobscripts_set(swap,1,1) < 0 )
printf("error bobscripts deposit\n");
else
{
swap->bobrefund.utxovout = 0;
swap->bobrefund.utxotxid = swap->bobdeposit.I.signedtxid;
basilisk_bobdeposit_refund(swap,swap->I.putduration);
//printf("depositlen.%d\n",swap->bobdeposit.I.datalen);
LP_swapsfp_update(&swap->I.req);
if ( LP_waitfor(utxo->pair,swap,10,LP_verify_otherfee) < 0 )
if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT,LP_verify_otherfee) < 0 )
printf("error waiting for alicefee\n");
else if ( LP_swapdata_rawtxsend(utxo->pair,swap,0x200,data,maxlen,&swap->bobdeposit,0x100,0) == 0 )
else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x200,data,maxlen,&swap->bobdeposit,0x100,0) == 0 )
printf("error sending bobdeposit\n");
else if ( LP_waitfor(utxo->pair,swap,10,LP_verify_alicepayment) < 0 )
else if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT,LP_verify_alicepayment) < 0 )
printf("error waiting for alicepayment\n");
else if ( basilisk_bobscripts_set(swap,0,1) < 0 )
printf("error bobscripts payment\n");
else if ( LP_swapdata_rawtxsend(utxo->pair,swap,0x8000,data,maxlen,&swap->bobpayment,0x4000,0) == 0 )
printf("error sending bobpayment\n");
else
{
printf("looping on swaplist\n");
while ( 1 )
if ( basilisk_bobscripts_set(swap,0,1) < 0 )
printf("error bobscripts payment\n");
else
{
if ( (retstr= basilisk_swaplist()) != 0 )
while ( (n= LP_numconfirms(swap,&swap->alicepayment)) < 1 ) // sync with alice
{
printf("%s\n",retstr);
free(retstr);
char str[65];printf("%d waiting for alicepayment to be confirmed.%d %s %s\n",n,1,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid));
sleep(3);
}
sleep(100);
if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x8000,data,maxlen,&swap->bobpayment,0x4000,0) == 0 )
printf("error sending bobpayment\n");
swap->sentflag = 1;
swap->bobreclaim.utxovout = 0;
swap->bobreclaim.utxotxid = swap->bobpayment.I.signedtxid;
basilisk_bobpayment_reclaim(swap,swap->I.callduration);
if ( swap->N.pair >= 0 )
nn_close(swap->N.pair), swap->N.pair = -1;
LP_swapwait(swap->I.req.requestid,swap->I.req.quoteid,4*3600,300);
}
}
}
basilisk_swap_finished(swap);
free(utxo->swap);
free(swap);
} else printf("swap timed out\n");
utxo->swap = 0;
nn_close(utxo->pair);
utxo->pair = -1;
}
void LP_aliceloop(void *_qp)
void LP_aliceloop(void *_swap)
{
uint8_t *data; char *retstr; int32_t maxlen; uint32_t expiration; struct basilisk_swap *swap = 0; struct LP_quoteinfo *qp = _qp;
fprintf(stderr,"start swap iamalice pair.%d\n",qp->pair);
uint8_t *data; int32_t maxlen,n; uint32_t expiration; struct basilisk_swap *swap = _swap;
maxlen = 1024*1024 + sizeof(*swap);
data = malloc(maxlen);
expiration = (uint32_t)time(NULL) + 10;
swap = LP_swapinit(0,0,qp->privkey,&qp->R,qp);
expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT;
if ( swap != 0 )
{
if ( LP_sendwait("pubkeys",10,qp->pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 )
fprintf(stderr,"start swap iamalice pair.%d\n",swap->N.pair);
if ( LP_sendwait("pubkeys",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 )
printf("error LP_sendwait pubkeys\n");
else if ( LP_sendwait("choosei",10,qp->pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 )
else if ( LP_sendwait("choosei",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 )
printf("error LP_sendwait choosei\n");
else if ( LP_sendwait("mostprivs",10,qp->pair,swap,data,maxlen,LP_mostprivs_verify,LP_mostprivs_data) < 0 )
else if ( LP_sendwait("mostprivs",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_mostprivs_verify,LP_mostprivs_data) < 0 )
printf("error LP_sendwait mostprivs\n");
else if ( basilisk_alicetxs(qp->pair,swap,data,maxlen) != 0 )
else if ( basilisk_alicetxs(swap->N.pair,swap,data,maxlen) != 0 )
printf("basilisk_alicetxs error\n");
else
{
LP_swapsfp_update(&swap->I.req);
if ( LP_swapdata_rawtxsend(qp->pair,swap,0x80,data,maxlen,&swap->myfee,0x40,0) == 0 )
if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x80,data,maxlen,&swap->myfee,0x40,0) == 0 )
printf("error sending alicefee\n");
else if ( LP_waitfor(qp->pair,swap,10,LP_verify_bobdeposit) < 0 )
else if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT,LP_verify_bobdeposit) < 0 )
printf("error waiting for bobdeposit\n");
else if ( LP_swapdata_rawtxsend(qp->pair,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0) == 0 )
else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0) == 0 )
printf("error sending alicepayment\n");
else if ( LP_waitfor(qp->pair,swap,10,LP_verify_bobpayment) < 0 )
printf("error waiting for bobpayment\n");
else
{
printf("looping on swaplist\n");
while ( 1 )
while ( (n= LP_numconfirms(swap,&swap->alicepayment)) < 1 )
{
if ( (retstr= basilisk_swaplist()) != 0 )
char str[65];printf("%d waiting for alicepayment to be confirmed.%d %s %s\n",n,1,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid));
sleep(LP_SWAPSTEP_TIMEOUT);
}
swap->sentflag = 1;
if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT,LP_verify_bobpayment) < 0 )
printf("error waiting for bobpayment\n");
else
{
while ( (n= LP_numconfirms(swap,&swap->bobpayment)) < swap->I.bobconfirms )
{
char str[65];printf("%d waiting for bobpayment to be confirmed.%d %s %s\n",n,swap->I.bobconfirms,swap->bobcoin.symbol,bits256_str(str,swap->bobpayment.I.signedtxid));
sleep(LP_SWAPSTEP_TIMEOUT);
}
if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x20000,data,maxlen,&swap->alicespend,0x40000,0) == 0 )
printf("error sending alicespend\n");
while ( (n= LP_numconfirms(swap,&swap->alicespend)) < swap->I.aliceconfirms )
{
printf("%s\n",retstr);
free(retstr);
char str[65];printf("%d waiting for alicespend to be confirmed.%d %s %s\n",n,swap->I.aliceconfirms,swap->bobcoin.symbol,bits256_str(str,swap->alicespend.I.signedtxid));
sleep(LP_SWAPSTEP_TIMEOUT);
}
sleep(100);
if ( swap->N.pair >= 0 )
nn_close(swap->N.pair), swap->N.pair = -1;
LP_swapwait(swap->I.req.requestid,swap->I.req.quoteid,4*3600,300);
}
}
}
basilisk_swap_finished(swap);
free(swap);
}
nn_close(qp->pair);
free(qp);
free(data);
nn_close(swap->N.pair);
}
bits256 instantdex_derivekeypair(void *ctx,bits256 *newprivp,uint8_t pubkey[33],bits256 privkey,bits256 orderhash)
@ -704,6 +858,9 @@ int32_t instantdex_pubkeyargs(struct basilisk_swap *swap,int32_t numpubs,bits256
void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx *rawtx,struct iguana_info *coin,int32_t numconfirms,int32_t vintype,uint64_t satoshis,int32_t vouttype,uint8_t *pubkey33,int32_t jumblrflag)
{
#ifdef BASILISK_DISABLEWAITTX
numconfirms = 0;
#endif
strcpy(rawtx->name,name);
rawtx->coin = coin;
strcpy(rawtx->I.coinstr,coin->symbol);
@ -717,13 +874,13 @@ void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx *
if ( strcmp(coin->symbol,"BTC") == 0 && (quoteid % 10) == 0 )
decode_hex(rawtx->I.rmd160,20,TIERNOLAN_RMD160);
else decode_hex(rawtx->I.rmd160,20,INSTANTDEX_RMD160);
bitcoin_address(rawtx->I.destaddr,rawtx->coin->pubtype,rawtx->I.rmd160,20);
bitcoin_address(rawtx->I.destaddr,rawtx->coin->taddr,rawtx->coin->pubtype,rawtx->I.rmd160,20);
}
if ( pubkey33 != 0 )
{
memcpy(rawtx->I.pubkey33,pubkey33,33);
bitcoin_address(rawtx->I.destaddr,rawtx->coin->pubtype,rawtx->I.pubkey33,33);
bitcoin_addr2rmd160(&rawtx->I.addrtype,rawtx->I.rmd160,rawtx->I.destaddr);
bitcoin_address(rawtx->I.destaddr,rawtx->coin->taddr,rawtx->coin->pubtype,rawtx->I.pubkey33,33);
bitcoin_addr2rmd160(rawtx->coin->taddr,&rawtx->I.addrtype,rawtx->I.rmd160,rawtx->I.destaddr);
}
if ( rawtx->I.vouttype <= 1 && rawtx->I.destaddr[0] != 0 )
{
@ -732,10 +889,10 @@ void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx *
} else printf("%s vouttype.%d destaddr.(%s)\n",name,rawtx->I.vouttype,rawtx->I.destaddr);
}
struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 pubkey25519,struct basilisk_swap *swap,int32_t optionduration,uint32_t statebits)
struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 pubkey25519,struct basilisk_swap *swap,int32_t optionduration,uint32_t statebits,struct LP_quoteinfo *qp)
{
//FILE *fp; char fname[512];
uint8_t *alicepub33=0,*bobpub33=0; int32_t jumblrflag=-2,x = -1; struct iguana_info *coin;
uint8_t *alicepub33=0,*bobpub33=0; int32_t bobistrusted,aliceistrusted,jumblrflag=-2,x = -1; struct iguana_info *coin;
swap->I.putduration = swap->I.callduration = INSTANTDEX_LOCKTIME;
if ( optionduration < 0 )
swap->I.putduration -= optionduration;
@ -761,11 +918,15 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256
{
swap->I.iambob = 0;
swap->I.otherhash = swap->I.req.desthash;
aliceistrusted = 1;
bobistrusted = LP_pubkey_istrusted(swap->I.req.desthash);
}
else
{
swap->I.iambob = 1;
swap->I.otherhash = swap->I.req.srchash;
bobistrusted = 1;
aliceistrusted = LP_pubkey_istrusted(swap->I.req.desthash);
}
if ( bits256_nonz(privkey) == 0 || (x= instantdex_pubkeyargs(swap,2 + INSTANTDEX_DECKSIZE,privkey,swap->I.orderhash,0x02+swap->I.iambob)) != 2 + INSTANTDEX_DECKSIZE )
{
@ -790,41 +951,38 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256
}
if ( strcmp("BTC",swap->bobcoin.symbol) == 0 )
{
swap->I.bobconfirms = (1*0 + sqrt(dstr(swap->I.bobsatoshis) * .1));
swap->I.aliceconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.bobconfirms * 3);
swap->I.bobconfirms = (1 + sqrt(dstr(swap->I.bobsatoshis) * .1));
swap->I.aliceconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.bobconfirms);
}
else if ( strcmp("BTC",swap->alicecoin.symbol) == 0 )
{
swap->I.aliceconfirms = (1*0 + sqrt(dstr(swap->I.alicesatoshis) * .1));
swap->I.bobconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.bobconfirms * 3);
swap->I.aliceconfirms = (1 + sqrt(dstr(swap->I.alicesatoshis) * .1));
swap->I.bobconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.aliceconfirms);
}
else
{
swap->I.bobconfirms = BASILISK_DEFAULT_NUMCONFIRMS;
swap->I.aliceconfirms = BASILISK_DEFAULT_NUMCONFIRMS;
}
/*if ( swap->I.bobconfirms == 0 )
swap->I.bobconfirms = swap->bobcoin->chain->minconfirms;
if ( swap->I.aliceconfirms == 0 )
swap->I.aliceconfirms = swap->alicecoin->chain->minconfirms;*/
//jumblrflag = (bits256_cmp(pubkey25519,myinfo->jumblr_pubkey) == 0 || bits256_cmp(pubkey25519,myinfo->jumblr_depositkey) == 0);
printf(">>>>>>>>>> jumblrflag.%d <<<<<<<<< use smart address, %.8f bobconfs.%d, %.8f aliceconfs.%d\n",jumblrflag,dstr(swap->I.bobsatoshis),swap->I.bobconfirms,dstr(swap->I.alicesatoshis),swap->I.aliceconfirms);
swap->I.bobconfirms *= !bobistrusted;
swap->I.aliceconfirms *= !aliceistrusted;
printf(">>>>>>>>>> jumblrflag.%d <<<<<<<<< use smart address, %.8f bobconfs.%d, %.8f aliceconfs.%d taddr.%d %d\n",jumblrflag,dstr(swap->I.bobsatoshis),swap->I.bobconfirms,dstr(swap->I.alicesatoshis),swap->I.aliceconfirms,swap->bobcoin.taddr,swap->alicecoin.taddr);
if ( swap->I.iambob != 0 )
{
basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,&swap->bobcoin,0,0,swap->I.bobsatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag);
basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,&swap->alicecoin,0,0,swap->I.alicesatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag);
basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,&swap->bobcoin,0,0,LP_DEXFEE(swap->I.bobsatoshis),0,0,jumblrflag);
basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,&swap->alicecoin,0,0,LP_DEXFEE(swap->I.alicesatoshis),0,0,jumblrflag);
bobpub33 = pubkey33;
}
else
{
basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,&swap->bobcoin,0,0,swap->I.bobsatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag);
basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,&swap->alicecoin,0,0,swap->I.alicesatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag);
basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,&swap->bobcoin,0,0,LP_DEXFEE(swap->I.bobsatoshis),0,0,jumblrflag);
basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,&swap->alicecoin,0,0,LP_DEXFEE(swap->I.alicesatoshis),0,0,jumblrflag);
alicepub33 = pubkey33;
}
basilisk_rawtx_setparms("bobdeposit",swap->I.req.quoteid,&swap->bobdeposit,&swap->bobcoin,swap->I.bobconfirms,0,swap->I.bobsatoshis + (swap->I.bobsatoshis>>3) + swap->bobcoin.txfee,4,0,jumblrflag);
basilisk_rawtx_setparms("bobrefund",swap->I.req.quoteid,&swap->bobrefund,&swap->bobcoin,1,4,swap->I.bobsatoshis + (swap->I.bobsatoshis>>3),1,bobpub33,jumblrflag);
basilisk_rawtx_setparms("bobdeposit",swap->I.req.quoteid,&swap->bobdeposit,&swap->bobcoin,swap->I.bobconfirms,0,LP_DEPOSITSATOSHIS(swap->I.bobsatoshis) + swap->bobcoin.txfee,4,0,jumblrflag);
basilisk_rawtx_setparms("bobrefund",swap->I.req.quoteid,&swap->bobrefund,&swap->bobcoin,1,4,LP_DEPOSITSATOSHIS(swap->I.bobsatoshis),1,bobpub33,jumblrflag);
swap->bobrefund.I.suppress_pubkeys = 1;
basilisk_rawtx_setparms("aliceclaim",swap->I.req.quoteid,&swap->aliceclaim,&swap->bobcoin,1,4,swap->I.bobsatoshis + (swap->I.bobsatoshis>>3),1,alicepub33,jumblrflag);
basilisk_rawtx_setparms("aliceclaim",swap->I.req.quoteid,&swap->aliceclaim,&swap->bobcoin,1,4,LP_DEPOSITSATOSHIS(swap->I.bobsatoshis),1,alicepub33,jumblrflag);
swap->aliceclaim.I.suppress_pubkeys = 1;
swap->aliceclaim.I.locktime = swap->I.started + swap->I.putduration+swap->I.callduration + 1;
@ -839,7 +997,13 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256
swap->bobspend.I.suppress_pubkeys = 1;
basilisk_rawtx_setparms("alicereclaim",swap->I.req.quoteid,&swap->alicereclaim,&swap->alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,alicepub33,jumblrflag);
swap->alicereclaim.I.suppress_pubkeys = 1;
printf("IAMBOB.%d\n",swap->I.iambob);
swap->bobpayment.utxotxid = qp->txid, swap->bobpayment.utxovout = qp->vout;
swap->bobdeposit.utxotxid = qp->txid2, swap->bobdeposit.utxovout = qp->vout2;
swap->alicepayment.utxotxid = qp->desttxid, swap->alicepayment.utxovout = qp->destvout;
if ( swap->I.iambob != 0 )
swap->otherfee.utxotxid = qp->feetxid, swap->otherfee.utxovout = qp->feevout;
else swap->myfee.utxotxid = qp->feetxid, swap->myfee.utxovout = qp->feevout;
char str[65],str2[65],str3[65]; printf("IAMBOB.%d %s %s %s\n",swap->I.iambob,bits256_str(str,qp->txid),bits256_str(str2,qp->txid2),bits256_str(str3,qp->feetxid));
return(swap);
}
@ -857,18 +1021,12 @@ struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256
swap->persistent_privkey = privkey;
memcpy(swap->persistent_pubkey33,pubkey33,33);
calc_rmd160_sha256(swap->changermd160,pubkey33,33);
if ( bitcoin_swapinit(privkey,pubkey33,pubkey25519,swap,optionduration,!iambob) == 0 )
if ( bitcoin_swapinit(privkey,pubkey33,pubkey25519,swap,optionduration,!iambob,qp) == 0 )
{
printf("error doing swapinit\n");
free(swap);
swap = 0;
}
swap->bobpayment.utxotxid = qp->txid, swap->bobpayment.utxovout = qp->vout;
swap->bobdeposit.utxotxid = qp->txid2, swap->bobdeposit.utxovout = qp->vout2;
swap->alicepayment.utxotxid = qp->desttxid, swap->alicepayment.utxovout = qp->destvout;
if ( iambob != 0 )
swap->otherfee.utxotxid = qp->feetxid, swap->otherfee.utxovout = qp->feevout;
else swap->myfee.utxotxid = qp->feetxid, swap->myfee.utxovout = qp->feevout;
return(swap);
}

585
iguana/exchanges/LP_transaction.c

File diff suppressed because it is too large

766
iguana/exchanges/LP_utxos.c

@ -18,35 +18,240 @@
// marketmaker
//
struct LP_utxoinfo *LP_utxofind(bits256 txid,int32_t vout)
int32_t LP_ismine(struct LP_utxoinfo *utxo)
{
if ( utxo != 0 && bits256_cmp(utxo->pubkey,LP_mypubkey) == 0 )
return(1);
else return(0);
}
int32_t LP_isavailable(struct LP_utxoinfo *utxo)
{
if ( time(NULL) > utxo->T.swappending )
utxo->T.swappending = 0;
if ( utxo != 0 && utxo->T.swappending == 0 && utxo->S.swap == 0 )
return(1);
else return(0);
}
int32_t LP_isunspent(struct LP_utxoinfo *utxo)
{
if ( utxo != 0 && utxo->T.spentflag == 0 && LP_isavailable(utxo) > 0 )
return(1);
else return(0);
}
void LP_utxosetkey(uint8_t *key,bits256 txid,int32_t vout)
{
struct LP_utxoinfo *utxo=0; uint8_t key[sizeof(txid) + sizeof(vout)];
memcpy(key,txid.bytes,sizeof(txid));
memcpy(&key[sizeof(txid)],&vout,sizeof(vout));
}
struct LP_utxoinfo *_LP_utxofind(int32_t iambob,bits256 txid,int32_t vout)
{
struct LP_utxoinfo *utxo=0; uint8_t key[sizeof(txid) + sizeof(vout)];
LP_utxosetkey(key,txid,vout);
HASH_FIND(hh,LP_utxoinfos[iambob],key,sizeof(key),utxo);
return(utxo);
}
struct LP_utxoinfo *_LP_utxo2find(int32_t iambob,bits256 txid2,int32_t vout2)
{
struct LP_utxoinfo *utxo=0; uint8_t key2[sizeof(txid2) + sizeof(vout2)];
LP_utxosetkey(key2,txid2,vout2);
HASH_FIND(hh2,LP_utxoinfos2[iambob],key2,sizeof(key2),utxo);
return(utxo);
}
struct LP_utxoinfo *LP_utxofind(int32_t iambob,bits256 txid,int32_t vout)
{
struct LP_utxoinfo *utxo=0;
portable_mutex_lock(&LP_utxomutex);
HASH_FIND(hh,LP_utxoinfos,key,sizeof(key),utxo);
utxo = _LP_utxofind(iambob,txid,vout);
portable_mutex_unlock(&LP_utxomutex);
return(utxo);
}
struct LP_utxoinfo *LP_utxo2find(int32_t iambob,bits256 txid2,int32_t vout2)
{
struct LP_utxoinfo *utxo=0;
portable_mutex_lock(&LP_utxomutex);
utxo = _LP_utxo2find(iambob,txid2,vout2);
portable_mutex_unlock(&LP_utxomutex);
return(utxo);
}
struct LP_utxoinfo *LP_utxofinds(int32_t iambob,bits256 txid,int32_t vout,bits256 txid2,int32_t vout2)
{
struct LP_utxoinfo *utxo;
if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 || (utxo= LP_utxofind(iambob,txid2,vout2)) != 0 || (utxo= LP_utxo2find(iambob,txid,vout)) != 0 || (utxo= LP_utxo2find(iambob,txid2,vout2)) != 0 )
return(utxo);
else return(0);
}
int32_t LP_utxoaddptrs(struct LP_utxoinfo *ptrs[],int32_t n,struct LP_utxoinfo *utxo)
{
int32_t i;
for (i=0; 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)
{
struct _LP_utxoinfo u;
jaddstr(item,"method","notified");
if ( utxo->gui[0] != 0 )
jaddstr(item,"gui",utxo->gui);
jaddstr(item,"coin",utxo->coin);
jaddnum(item,"now",time(NULL));
jaddnum(item,"iambob",utxo->iambob);
jaddstr(item,"address",utxo->coinaddr);
jaddbits256(item,"txid",utxo->txid);
jaddnum(item,"vout",utxo->vout);
jaddnum(item,"value",dstr(utxo->satoshis));
jaddbits256(item,"txid2",utxo->txid2);
jaddnum(item,"vout2",utxo->vout2);
jaddnum(item,"value2",dstr(utxo->satoshis2));
if ( utxo->swappending != 0 )
jaddnum(item,"pending",utxo->swappending);
if ( bits256_nonz(utxo->otherpubkey) != 0 )
jaddbits256(item,"desthash",utxo->otherpubkey);
if ( utxo->pair >= 0 )
jaddnum(item,"socket",utxo->pair);
if ( utxo->swap != 0 )
jaddbits256(item,"txid",utxo->payment.txid);
jaddnum(item,"vout",utxo->payment.vout);
jadd64bits(item,"value",utxo->payment.value);
jadd64bits(item,"satoshis",utxo->S.satoshis);
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee;
if ( bits256_nonz(u.txid) != 0 )
{
jaddbits256(item,"txid2",u.txid);
jaddnum(item,"vout2",u.vout);
jadd64bits(item,"value2",u.value);
}
if ( utxo->T.swappending != 0 )
jaddnum(item,"pending",utxo->T.swappending);
if ( utxo->iambob != 0 )
{
jaddbits256(item,"srchash",LP_mypubkey);
if ( bits256_nonz(utxo->S.otherpubkey) != 0 )
jaddbits256(item,"desthash",utxo->S.otherpubkey);
}
else
{
jaddbits256(item,"desthash",LP_mypubkey);
if ( bits256_nonz(utxo->S.otherpubkey) != 0 )
jaddbits256(item,"srchash",utxo->S.otherpubkey);
}
if ( utxo->S.swap != 0 )
jaddstr(item,"swap","in progress");
if ( utxo->T.spentflag != 0 )
jaddnum(item,"spent",utxo->T.spentflag);
return(item);
}
@ -54,94 +259,276 @@ cJSON *LP_utxojson(struct LP_utxoinfo *utxo)
{
cJSON *item = cJSON_CreateObject();
item = LP_inventoryjson(item,utxo);
jaddstr(item,"ipaddr",utxo->ipaddr);
jaddnum(item,"port",utxo->port);
jaddnum(item,"profit",utxo->profitmargin);
jaddbits256(item,"pubkey",utxo->pubkey);
jaddnum(item,"profit",utxo->S.profitmargin);
jaddstr(item,"base",utxo->coin);
jaddstr(item,"script",utxo->spendscript);
return(item);
}
char *LP_utxos(struct LP_peerinfo *mypeer,char *coin,int32_t lastn)
int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2,bits256 pubkey)
{
uint64_t val,val2=0,threshold; char destaddr[64],destaddr2[64];
destaddr[0] = destaddr2[0] = 0;
if ( (val= LP_txvalue(destaddr,symbol,txid,vout)) >= satoshis )
{
threshold = (iambob != 0) ? LP_DEPOSITSATOSHIS(satoshis) : LP_DEXFEE(satoshis);
if ( (val2= LP_txvalue(destaddr2,symbol,txid2,vout2)) >= threshold )
{
if ( strcmp(destaddr,destaddr2) != 0 )
printf("mismatched %s destaddr %s vs %s\n",symbol,destaddr,destaddr2);
else if ( (iambob == 0 && val2 > val) || (iambob != 0 && val2 <= satoshis) )
printf("iambob.%d ineligible due to offsides: val %.8f and val2 %.8f vs %.8f diff %lld\n",iambob,dstr(val),dstr(val2),dstr(satoshis),(long long)(val2 - val));
else
{
*valp = val;
*val2p = val2;
return(1);
}
} else printf("no val2\n");
} else printf("mismatched %s txid value %.8f < %.8f\n",symbol,dstr(val),dstr(satoshis));
*valp = val;
*val2p = val2;
return(0);
}
char *LP_utxos(int32_t iambob,struct LP_peerinfo *mypeer,char *symbol,int32_t lastn)
{
int32_t i,firsti; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray();
int32_t i,firsti,n; uint64_t val,val2; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray();
i = 0;
if ( lastn >= mypeer->numutxos )
n = mypeer != 0 ? mypeer->numutxos : 0;
if ( lastn <= 0 )
lastn = LP_PROPAGATION_SLACK * 2;
if ( lastn >= n )
firsti = -1;
else firsti = (mypeer->numutxos - lastn);
HASH_ITER(hh,LP_utxoinfos,utxo,tmp)
else firsti = (lastn - n);
//printf("LP_utxos iambob.%d symbol.%s firsti.%d lastn.%d\n",iambob,symbol==0?"":symbol,firsti,lastn);
HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp)
{
//char str[65]; printf("check %s.%s\n",utxo->coin,bits256_str(str,utxo->payment.txid));
if ( i++ < firsti )
continue;
if ( coin == 0 || coin[0] == 0 || strcmp(coin,utxo->coin) == 0 )
if ( (symbol == 0 || symbol[0] == 0 || strcmp(symbol,utxo->coin) == 0) && utxo->T.spentflag == 0 )
{
jaddi(utxosjson,LP_utxojson(utxo));
u = (iambob != 0) ? utxo->deposit : utxo->fee;
if ( LP_iseligible(&val,&val2,iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,u.txid,u.vout,utxo->pubkey) == 0 )
{
char str[65]; printf("iambob.%d not eligible (%.8f %.8f) %s %s/v%d\n",iambob,dstr(val),dstr(val2),utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout);
continue;
} else jaddi(utxosjson,LP_utxojson(utxo));
}
}
return(jprint(utxosjson,1));
}
struct LP_utxoinfo *LP_addutxo(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *coin,bits256 txid,int32_t vout,int64_t satoshis,bits256 deposittxid,int32_t depositvout,int64_t depositsatoshis,char *spendscript,char *coinaddr,char *ipaddr,uint16_t port,double profitmargin)
int32_t LP_inventory_prevent(int32_t iambob,bits256 txid,int32_t vout)
{
struct LP_utxoinfo *utxo = 0;
if ( coin == 0 || coin[0] == 0 || spendscript == 0 || spendscript[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(deposittxid) == 0 || vout < 0 || depositvout < 0 || satoshis <= 0 || depositsatoshis <= 0 )
struct LP_utxoinfo *utxo;
if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 || (utxo= LP_utxo2find(iambob,txid,vout)) != 0 )
{
printf("malformed addutxo %d %d %d %d %d %d %d %d %d\n", coin == 0,spendscript == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(deposittxid) == 0,vout < 0,depositvout < 0,satoshis <= 0,depositsatoshis <= 0);
//if ( utxo->T.spentflag != 0 )
{
//char str[65]; printf("prevent adding %s/v%d to inventory\n",bits256_str(str,txid),vout);
return(1);
}
}
return(0);
}
struct LP_utxoinfo *LP_utxo_bestfit(char *symbol,uint64_t destsatoshis)
{
struct LP_utxoinfo *utxo,*tmp,*bestutxo = 0;
if ( symbol == 0 || destsatoshis == 0 )
return(0);
HASH_ITER(hh,LP_utxoinfos[0],utxo,tmp)
{
//char str[65]; printf("check %s.%s\n",utxo->coin,bits256_str(str,utxo->payment.txid));
if ( strcmp(symbol,utxo->coin) == 0 && LP_isavailable(utxo) > 0 && LP_ismine(utxo) > 0 )
{
if ( utxo->S.satoshis >= destsatoshis && (bestutxo == 0 || utxo->S.satoshis < bestutxo->S.satoshis) )
bestutxo = utxo;
}
}
if ( IAMCLIENT == 0 && strcmp(ipaddr,"127.0.0.1") == 0 )
return(bestutxo);
}
void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector)
{
cJSON *argjson; struct _LP_utxoinfo u; char *msg;
utxo->T.spentflag = (uint32_t)time(NULL);
if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 )
LP_mypeer->numutxos--;
if ( LP_mypubsock >= 0 )
{
argjson = cJSON_CreateObject();
jaddstr(argjson,"method","checktxid");
jaddbits256(argjson,"txid",utxo->payment.txid);
jaddnum(argjson,"vout",utxo->payment.vout);
if ( selector != 0 )
{
if ( bits256_nonz(utxo->deposit.txid) != 0 )
u = utxo->deposit;
else u = utxo->fee;
jaddbits256(argjson,"checktxid",u.txid);
jaddnum(argjson,"checkvout",u.vout);
}
msg = jprint(argjson,1);
LP_send(LP_mypubsock,msg,(int32_t)strlen(msg)+1,1);
}
}
char *LP_spentcheck(cJSON *argjson)
{
char destaddr[64]; bits256 txid,checktxid; int32_t vout,checkvout; struct LP_utxoinfo *utxo; int32_t iambob,retval = 0;
txid = jbits256(argjson,"txid");
vout = jint(argjson,"vout");
for (iambob=0; iambob<=1; iambob++)
{
printf("LP node got localhost utxo\n");
if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 && utxo->T.spentflag == 0 )
{
if ( jobj(argjson,"check") == 0 )
checktxid = txid, checkvout = vout;
else
{
checktxid = jbits256(argjson,"checktxid");
checkvout = jint(argjson,"checkvout");
}
if ( LP_txvalue(destaddr,utxo->coin,checktxid,checkvout) == 0 )
{
if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 )
LP_mypeer->numutxos--;
utxo->T.spentflag = (uint32_t)time(NULL);
retval++;
//printf("indeed txid was spent\n");
}
}
}
if ( retval > 0 )
return(clonestr("{\"result\":\"marked as spent\"}"));
return(clonestr("{\"error\":\"cant find txid to check spent status\"}"));
}
struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bits256 txid,int32_t vout,int64_t value,bits256 txid2,int32_t vout2,int64_t value2,char *spendscript,char *coinaddr,bits256 pubkey,double profitmargin,char *gui)
{
uint64_t val,val2=0,tmpsatoshis,bigtxfee = 100000; int32_t spendvini,selector; bits256 spendtxid; char *msg; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo = 0;
if ( symbol == 0 || symbol[0] == 0 || spendscript == 0 || spendscript[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 || vout < 0 || vout2 < 0 || value <= 0 || value2 <= 0 )
{
printf("malformed addutxo %d %d %d %d %d %d %d %d %d\n", symbol == 0,spendscript == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(txid2) == 0,vout < 0,vout2 < 0,value <= 0,value2 <= 0);
return(0);
}
if ( iambob != 0 && value2 < 9 * (value >> 3) + bigtxfee ) // big txfee padding
{
if ( value2 > bigtxfee+20000 )
tmpsatoshis = (((value2 - bigtxfee) / 9) << 3);
else return(0);
} else tmpsatoshis = value;
char str[65],str2[65],dispflag = (iambob == 0);
if ( iambob == 0 && bits256_cmp(pubkey,LP_mypubkey) != 0 )
{
printf("trying to add Alice utxo when not mine? %s/v%d\n",bits256_str(str,txid),vout);
return(0);
}
if ( LP_iseligible(&val,&val2,iambob,symbol,txid,vout,tmpsatoshis,txid2,vout2,pubkey) <= 0 )
{
printf("iambob.%d utxoadd got ineligible txid value %.8f, value2 %.8f, tmpsatoshis %.8f\n",iambob,dstr(value),dstr(value2),dstr(tmpsatoshis));
return(0);
}
if ( dispflag != 0 )
printf("%.8f %.8f %s iambob.%d %s utxoadd.(%.8f %.8f) %s %s\n",dstr(val),dstr(val2),coinaddr,iambob,symbol,dstr(value),dstr(value2),bits256_str(str,txid),bits256_str(str2,txid2));
dispflag = 1;
if ( 0 && (selector= LP_mempool_vinscan(&spendtxid,&spendvini,symbol,txid,vout,txid2,vout2)) >= 0 )
{
printf("utxoadd selector.%d in mempool %s vini.%d",selector,bits256_str(str,spendtxid),spendvini);
return(0);
}
if ( (utxo= LP_utxofind(txid,vout)) != 0 )
if ( (utxo= LP_utxofinds(iambob,txid,vout,txid2,vout2)) != 0 )
{
if ( bits256_cmp(txid,utxo->txid) != 0 || bits256_cmp(deposittxid,utxo->txid2) != 0 || vout != utxo->vout || satoshis != utxo->satoshis || depositvout != utxo->vout2 || depositsatoshis != utxo->satoshis2 || strcmp(coin,utxo->coin) != 0 || strcmp(spendscript,utxo->spendscript) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || strcmp(ipaddr,utxo->ipaddr) != 0 || port != utxo->port )
if ( 0 && LP_ismine(utxo) == 0 )
{
char str2[65],str3[65]; printf("iambob.%d %s %s utxoadd.(%.8f %.8f) %s %s\n",iambob,bits256_str(str3,pubkey),symbol,dstr(value),dstr(value2),bits256_str(str,txid),bits256_str(str2,txid2));
printf("duplicate %.8f %.8f %.8f vs utxo.(%.8f %.8f %.8f)\n",dstr(value),dstr(value2),dstr(tmpsatoshis),dstr(utxo->payment.value),dstr(utxo->deposit.value),dstr(utxo->S.satoshis));
}
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee;
if ( bits256_cmp(txid,utxo->payment.txid) != 0 || bits256_cmp(txid2,u.txid) != 0 || vout != utxo->payment.vout || value != utxo->payment.value || tmpsatoshis != utxo->S.satoshis || vout2 != u.vout || value2 != u.value || strcmp(symbol,utxo->coin) != 0 || strcmp(spendscript,utxo->spendscript) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || bits256_cmp(pubkey,utxo->pubkey) != 0 )
{
utxo->errors++;
char str[65],str2[65]; printf("error on subsequent utxo add.(%s v %s) %d %d %d %d %d %d %d %d %d %d %d\n",bits256_str(str,txid),bits256_str(str2,utxo->txid),bits256_cmp(txid,utxo->txid) != 0,bits256_cmp(deposittxid,utxo->txid2) != 0,vout != utxo->vout,satoshis != utxo->satoshis,depositvout != utxo->vout2,depositsatoshis != utxo->satoshis2,strcmp(coin,utxo->coin) != 0,strcmp(spendscript,utxo->spendscript) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,strcmp(ipaddr,utxo->ipaddr) != 0,port != utxo->port);
utxo->T.errors++;
char str[65],str2[65],str3[65],str4[65],str5[65],str6[65];
if ( dispflag != 0 )
printf("error on subsequent utxo iambob.%d %.8f %.8f add.(%s %s) when.(%s %s) %d %d %d %d %d %d %d %d %d %d %d pubkeys.(%s vs %s)\n",iambob,dstr(val),dstr(val2),bits256_str(str,txid),bits256_str(str2,txid2),bits256_str(str3,utxo->payment.txid),bits256_str(str4,utxo->deposit.txid),bits256_cmp(txid,utxo->payment.txid) != 0,bits256_cmp(txid2,u.txid) != 0,vout != utxo->payment.vout,tmpsatoshis != utxo->S.satoshis,vout2 != u.vout,value2 != u.value,strcmp(symbol,utxo->coin) != 0,strcmp(spendscript,utxo->spendscript) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,bits256_cmp(pubkey,utxo->pubkey) != 0,value != utxo->payment.value,bits256_str(str5,pubkey),bits256_str(str6,utxo->pubkey));
if ( utxo->T.spentflag != 0 || LP_txvalue(utxo->coinaddr,utxo->coin,utxo->payment.txid,utxo->payment.vout) < utxo->payment.value || LP_txvalue(utxo->coinaddr,utxo->coin,u.txid,u.vout) < u.value )
{
if ( utxo->T.spentflag == 0 )
utxo->T.spentflag = (uint32_t)time(NULL);
printf("original utxo pair not valid\n");
utxo = 0;
}
}
else if ( profitmargin != 0. )
utxo->profitmargin = profitmargin;
else if ( profitmargin > SMALLVAL )
utxo->S.profitmargin = profitmargin;
if ( utxo != 0 )
return(utxo);
}
utxo = calloc(1,sizeof(*utxo));
utxo->S.profitmargin = profitmargin;
utxo->pubkey = pubkey;
safecopy(utxo->gui,gui,sizeof(utxo->gui));
safecopy(utxo->coin,symbol,sizeof(utxo->coin));
safecopy(utxo->coinaddr,coinaddr,sizeof(utxo->coinaddr));
safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript));
utxo->payment.txid = txid;
utxo->payment.vout = vout;
utxo->payment.value = value;
utxo->S.satoshis = tmpsatoshis;
if ( (utxo->iambob= iambob) != 0 )
{
utxo->deposit.txid = txid2;
utxo->deposit.vout = vout2;
utxo->deposit.value = value2;
}
else
{
utxo = calloc(1,sizeof(*utxo));
utxo->pair = -1;
utxo->profitmargin = profitmargin;
strcpy(utxo->ipaddr,ipaddr);
utxo->port = port;
safecopy(utxo->coin,coin,sizeof(utxo->coin));
safecopy(utxo->coinaddr,coinaddr,sizeof(utxo->coinaddr));
safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript));
utxo->txid = txid;
utxo->vout = vout;
utxo->satoshis = satoshis;
utxo->txid2 = deposittxid;
utxo->vout2 = depositvout;
utxo->satoshis2 = depositsatoshis;
memcpy(utxo->key,txid.bytes,sizeof(txid));
memcpy(&utxo->key[sizeof(txid)],&vout,sizeof(vout));
portable_mutex_lock(&LP_utxomutex);
HASH_ADD_KEYPTR(hh,LP_utxoinfos,utxo->key,sizeof(utxo->key),utxo);
if ( mypeer != 0 )
mypeer->numutxos++;
portable_mutex_unlock(&LP_utxomutex);
utxo->fee.txid = txid2;
utxo->fee.vout = vout2;
utxo->fee.value = value2;
}
LP_utxosetkey(utxo->key,txid,vout);
LP_utxosetkey(utxo->key2,txid2,vout2);
portable_mutex_lock(&LP_utxomutex);
HASH_ADD_KEYPTR(hh,LP_utxoinfos[iambob],utxo->key,sizeof(utxo->key),utxo);
if ( _LP_utxo2find(iambob,txid2,vout2) == 0 )
HASH_ADD_KEYPTR(hh2,LP_utxoinfos2[iambob],utxo->key2,sizeof(utxo->key2),utxo);
portable_mutex_unlock(&LP_utxomutex);
if ( iambob != 0 )
{
if ( mypubsock >= 0 )
LP_send(mypubsock,jprint(LP_utxojson(utxo),1),1);
char str[65],str2[65]; printf("amclient.%d %s:%u %s LP_addutxo.(%.8f %.8f) numutxos.%d %s %s\n",IAMCLIENT,ipaddr,port,utxo->coin,dstr(satoshis),dstr(depositsatoshis),mypeer!=0?mypeer->numutxos:0,bits256_str(str,utxo->txid),bits256_str(str2,txid));
{
msg = jprint(LP_utxojson(utxo),1);
LP_send(mypubsock,msg,(int32_t)strlen(msg)+1,1);
} else LP_utxo_clientpublish(utxo);
if ( LP_mypeer != 0 && LP_ismine(utxo) > 0 )
LP_mypeer->numutxos++;
}
return(utxo);
}
int32_t LP_utxosparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now)
struct LP_utxoinfo *LP_utxoaddjson(int32_t iambob,int32_t pubsock,cJSON *argjson)
{
struct LP_peerinfo *peer,*destpeer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; bits256 txid; struct LP_utxoinfo *utxo;
if ( amclient != 0 )
struct LP_utxoinfo *utxo;
if ( jobj(argjson,"iambob") == 0 || iambob != jint(argjson,"iambob") )
{
printf("LP_utxosparse not for clientside\n");
return(-1);
printf("LP_utxoaddjson: iambob.%d != arg.%d obj.%p (%s)\n",iambob,jint(argjson,"iambob"),jobj(argjson,"iambob"),jprint(argjson,0));
return(0);
}
portable_mutex_lock(&LP_UTXOmutex);
utxo = LP_utxoadd(iambob,pubsock,jstr(argjson,"coin"),jbits256(argjson,"txid"),jint(argjson,"vout"),j64bits(argjson,"value"),jbits256(argjson,"txid2"),jint(argjson,"vout2"),j64bits(argjson,"value2"),jstr(argjson,"script"),jstr(argjson,"address"),jbits256(argjson,"pubkey"),jdouble(argjson,"profit"),jstr(argjson,"gui"));
portable_mutex_unlock(&LP_UTXOmutex);
return(utxo);
}
int32_t LP_utxosparse(char *destipaddr,uint16_t destport,char *retstr,uint32_t now)
{
struct LP_peerinfo *destpeer,*peer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; bits256 txid; struct LP_utxoinfo *utxo;
//printf("parse.(%s)\n",retstr);
if ( (array= cJSON_Parse(retstr)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
@ -157,24 +544,23 @@ int32_t LP_utxosparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubs
subport = argport + 2;
argipbits = (uint32_t)calc_ipbits(argipaddr);
if ( (peer= LP_peerfind(argipbits,argport)) == 0 )
peer = LP_addpeer(amclient,mypeer,mypubsock,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos"));
if ( jobj(item,"txid") != 0 )
peer = LP_addpeer(0,-1,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos"));
}
if ( jobj(item,"txid") != 0 )
{
txid = jbits256(item,"txid");
//printf("parse.(%s)\n",jprint(item,0));
if ( (utxo= LP_utxoaddjson(1,-1,item)) != 0 )
{
txid = jbits256(item,"txid");
utxo = LP_addutxo(amclient,mypeer,mypubsock,jstr(item,"coin"),txid,jint(item,"vout"),SATOSHIDEN*jdouble(item,"value"),jbits256(item,"txid2"),jint(item,"vout2"),SATOSHIDEN * jdouble(item,"value2"),jstr(item,"script"),jstr(item,"address"),argipaddr,argport,jdouble(item,"profit"));
if ( utxo != 0 )
utxo->lasttime = now;
//if ( strcmp(utxo->coin,"HUSH") == 0 )
// printf("%s set lasttime (%s)\n",destipaddr,jprint(item,0));
utxo->T.lasttime = now;
}
}
}
if ( (destpeer= LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport)) != 0 )
{
destpeer->numutxos = n;
if ( destpeer->numutxos < n )
{
//destpeer->numutxos = n;
//printf("got.(%s) from %s numutxos.%d\n",retstr,destpeer->ipaddr,destpeer->numutxos);
}
}
}
free_json(array);
@ -182,29 +568,27 @@ int32_t LP_utxosparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubs
return(n);
}
void LP_utxosquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *coin,int32_t lastn,char *myipaddr,uint16_t myport,double myprofit)
int32_t LP_utxosquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *coin,int32_t lastn,char *myipaddr,uint16_t myport,double myprofit)
{
char *retstr; struct LP_peerinfo *peer; int32_t i,firsti; uint32_t now;
if ( amclient != 0 )
{
printf("LP_utxosquery not for clientside\n");
return;
}
char *retstr; struct LP_peerinfo *peer; uint32_t now; int32_t retval = -1;
peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport);
if ( mypeer == 0 ) //(peer != 0 && peer->errors > 0) ||
return;
if ( coin == 0 )
coin = "";
if ( (retstr= issue_LP_getutxos(destipaddr,destport,coin,lastn,myipaddr,myport,myprofit,mypeer->numpeers,mypeer->numutxos)) != 0 )
//printf("utxo query.(%s)\n",destipaddr);
if ( IAMLP != 0 )
retstr = issue_LP_getutxos(destipaddr,destport,coin,lastn,myipaddr,myport,myprofit,mypeer != 0 ? mypeer->numpeers : 0,mypeer != 0 ? mypeer->numutxos : 0);
else retstr = issue_LP_clientgetutxos(destipaddr,destport,coin,100);
if ( retstr != 0 )
{
now = (uint32_t)time(NULL);
LP_utxosparse(amclient,mypeer,mypubsock,destipaddr,destport,retstr,now);
retval = LP_utxosparse(destipaddr,destport,retstr,now);
//printf("got.(%s)\n",retstr);
free(retstr);
i = 0;
/*i = 0;
if ( lastn >= mypeer->numutxos )
firsti = -1;
else firsti = (mypeer->numutxos - lastn);
/*HASH_ITER(hh,LP_utxoinfos,utxo,tmp)
HASH_ITER(hh,LP_utxoinfos,utxo,tmp)
{
if ( i++ < firsti )
continue;
@ -218,22 +602,25 @@ void LP_utxosquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock
}
if ( flag != 0 )
printf(" <- missing utxos\n");*/
} else if ( peer != 0 )
peer->errors++;
}
return(retval);
}
char *LP_inventory(char *symbol)
cJSON *LP_inventory(char *symbol,int32_t iambob)
{
struct LP_utxoinfo *utxo,*tmp; char *myipaddr; cJSON *array = cJSON_CreateArray();
struct LP_utxoinfo *utxo,*tmp; char *myipaddr; cJSON *array;
array = cJSON_CreateArray();
if ( LP_mypeer != 0 )
myipaddr = LP_mypeer->ipaddr;
else myipaddr = "127.0.0.1";
HASH_ITER(hh,LP_utxoinfos,utxo,tmp)
HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp)
{
if ( strcmp(symbol,utxo->coin) == 0 && (IAMCLIENT != 0 || strcmp(utxo->ipaddr,myipaddr) == 0) )
//char str[65]; printf("iambob.%d iterate %s\n",iambob,bits256_str(str,LP_mypubkey));
if ( LP_isunspent(utxo) != 0 && strcmp(symbol,utxo->coin) == 0 && utxo->iambob == iambob && LP_ismine(utxo) > 0 )
jaddi(array,LP_inventoryjson(cJSON_CreateObject(),utxo));
//else printf("skip %s %d %d %d %d\n",bits256_str(str,utxo->pubkey),LP_isunspent(utxo) != 0,strcmp(symbol,utxo->coin) == 0,utxo->iambob == iambob,LP_ismine(utxo) > 0);
}
return(jprint(array,1));
return(array);
}
int32_t LP_maxvalue(uint64_t *values,int32_t n)
@ -265,102 +652,145 @@ int32_t LP_nearestvalue(uint64_t *values,int32_t n,uint64_t targetval)
return(mini);
}
uint64_t LP_privkey_init(struct LP_peerinfo *mypeer,int32_t mypubsock,char *symbol,char *passphrase,char *wifstr,int32_t amclient)
uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 myprivkey,bits256 mypub,uint8_t *pubkey33)
{
static uint32_t counter;
char coinaddr[64],*script; struct LP_utxoinfo *utxo; cJSON *array,*item,*retjson; bits256 userpass,userpub,txid,deposittxid; int32_t used,i,n,vout,depositvout; uint64_t *values,satoshis,depositval,targetval,value,total = 0; bits256 privkey,pubkey; uint8_t pubkey33[33],tmptype,rmd160[20]; struct iguana_info *coin = LP_coinfind(symbol);
char *script; struct LP_utxoinfo *utxo; cJSON *array,*item; bits256 txid,deposittxid; int32_t used,i,n,iambob,vout,depositvout; uint64_t *values=0,satoshis,depositval,targetval,value,total = 0;
if ( coin == 0 )
{
printf("cant add privkey for %s, coin not active\n",symbol);
printf("coin not active\n");
return(0);
}
if ( passphrase != 0 )
conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase));
else privkey = iguana_wif2privkey(wifstr);
iguana_priv2pub(pubkey33,coinaddr,privkey,coin->pubtype);
if ( strcmp("BTC",symbol) == 0 )
strcpy(BTCADDR,coinaddr);
else if ( strcmp("KMD",symbol) == 0 )
strcpy(KMDADDR,coinaddr);
if ( counter == 0 )
{
char tmpstr[128];
counter++;
bitcoin_priv2wif(USERPASS_WIFSTR,privkey,188);
bitcoin_priv2wif(tmpstr,privkey,coin->wiftype);
conv_NXTpassword(userpass.bytes,pubkey.bytes,(uint8_t *)tmpstr,(int32_t)strlen(tmpstr));
userpub = curve25519(userpass,curve25519_basepoint9());
printf("userpass.(%s)\n",bits256_str(USERPASS,userpub));
printf("%s (%s) %d wif.(%s) (%s)\n",symbol,coinaddr,coin->pubtype,tmpstr,passphrase);
if ( (retjson= LP_importprivkey(coin->symbol,tmpstr,coinaddr,-1)) != 0 )
printf("importprivkey -> (%s)\n",jprint(retjson,1));
}
bitcoin_addr2rmd160(&tmptype,rmd160,coinaddr);
LP_privkeyadd(privkey,rmd160);
if ( (array= LP_listunspent(symbol,coinaddr)) != 0 )
//printf("privkey init.(%s) %s\n",coin->symbol,coin->smartaddr);
if ( coin->inactive == 0 && (array= LP_listunspent(coin->symbol,coin->smartaddr)) != 0 )
{
if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{
values = calloc(n,sizeof(*values));
for (i=0; i<n; i++)
{
item = jitem(array,i);
satoshis = SATOSHIDEN * jdouble(item,"amount");
values[i] = satoshis;
//printf("%.8f ",dstr(satoshis));
}
//printf("array.%d\n",n);
used = 0;
while ( used < n )
for (iambob=0; iambob<=1; iambob++)
{
if ( (i= LP_maxvalue(values,n)) >= 0 )
if ( iambob == 0 )
values = calloc(n,sizeof(*values));
else memset(values,0,n * sizeof(*values));
//if ( iambob == 0 && IAMLP != 0 )
// continue;
used = 0;
for (i=0; i<n; i++)
{
item = jitem(array,i);
deposittxid = jbits256(item,"txid");
depositvout = juint(item,"vout");
script = jstr(item,"scriptPubKey");
depositval = values[i];
values[i] = 0, used++;
if ( amclient != 0 )
targetval = (depositval / 776) + 50000;
else targetval = (depositval / 9) * 8;
//printf("i.%d %.8f target %.8f\n",i,dstr(depositval),dstr(targetval));
if ( (i= LP_nearestvalue(values,n,targetval)) >= 0 )
satoshis = SATOSHIDEN * jdouble(item,"amount");
if ( LP_inventory_prevent(iambob,jbits256(item,"txid"),juint(item,"vout")) == 0 )
values[i] = satoshis;
else used++;
//printf("%.8f ",dstr(satoshis));
}
//printf("array.%d\n",n);
while ( used < n-1 )
{
//printf("used.%d of n.%d\n",used,n);
if ( (i= LP_maxvalue(values,n)) >= 0 )
{
item = jitem(array,i);
txid = jbits256(item,"txid");
vout = juint(item,"vout");
if ( jstr(item,"scriptPubKey") != 0 && strcmp(script,jstr(item,"scriptPubKey")) == 0 )
deposittxid = jbits256(item,"txid");
depositvout = juint(item,"vout");
script = jstr(item,"scriptPubKey");
depositval = values[i];
values[i] = 0, used++;
if ( iambob == 0 )
targetval = (depositval / 776) + 100000;
else targetval = (depositval / 9) * 8 + 100000;
//printf("i.%d %.8f target %.8f\n",i,dstr(depositval),dstr(targetval));
if ( (i= LP_nearestvalue(values,n,targetval)) < 0 && iambob != 0 )
targetval /= 4;
if ( (i= LP_nearestvalue(values,n,targetval)) >= 0 )
{
value = values[i];
values[i] = 0, used++;
if ( amclient == 0 )
{
if ( (utxo= LP_addutxo(amclient,mypeer,mypubsock,symbol,txid,vout,value,deposittxid,depositvout,depositval,script,coinaddr,LP_peerinfos[0].ipaddr,LP_peerinfos[0].port,LP_peerinfos[0].profitmargin)) != 0 )
utxo->mypub = curve25519(privkey,curve25519_basepoint9());
}
else
item = jitem(array,i);
txid = jbits256(item,"txid");
vout = juint(item,"vout");
if ( jstr(item,"scriptPubKey") != 0 && strcmp(script,jstr(item,"scriptPubKey")) == 0 )
{
if ( (utxo= LP_addutxo(amclient,mypeer,mypubsock,symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coinaddr,"127.0.0.1",0,0)) != 0 )
utxo->mypub = curve25519(privkey,curve25519_basepoint9());
value = values[i];
values[i] = 0, used++;
portable_mutex_lock(&LP_UTXOmutex);
if ( iambob != 0 )
{
if ( (utxo= LP_utxoadd(1,mypubsock,coin->symbol,txid,vout,value,deposittxid,depositvout,depositval,script,coin->smartaddr,mypub,LP_mypeer != 0 ? LP_mypeer->profitmargin : 0.01,LP_gui)) != 0 )
{
}
}
else
{
if ( (utxo= LP_utxoadd(0,mypubsock,coin->symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coin->smartaddr,mypub,0.,LP_gui)) != 0 )
{
}
}
portable_mutex_unlock(&LP_UTXOmutex);
total += value;
}
total += value;
}
}
} else break;
} else break;
}
if ( iambob == 1 )
free(values);
}
free(values);
}
free_json(array);
}
//printf("privkey.%s %.8f\n",symbol,dstr(total));
return(total);
}
void LP_privkey_updates(struct LP_peerinfo *mypeer,int32_t pubsock,char *passphrase,int32_t amclient)
bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguana_info *coin,char *passphrase,char *wifstr)
{
int32_t i;
for (i=0; i<sizeof(activecoins)/sizeof(*activecoins); i++)
LP_privkey_init(mypeer,pubsock,activecoins[i],passphrase,"",amclient);
static uint32_t counter;
bits256 privkey,userpub,userpass; char tmpstr[128]; cJSON *retjson; uint8_t tmptype,rmd160[20];
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
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)
{
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)

24
iguana/exchanges/client

@ -1,2 +1,24 @@
source randval
pkill -15 marketmaker; git pull; cd ..; ./m_mm; ./marketmaker "{\"client\":1,\"passphrase\":\"$randval\"}" &
pkill -15 marketmaker;
git pull;
cd ..;
./m_mm;
./marketmaker "{\"gui\":\"nogui\",\"client\":1,\"coins\":[{\"coin\":\"REVS\",\"active\":1, \"asset\":\"REVS\",\"rpcport\":10196},{\"coin\":\"JUMBLR\",\"active\":1, \"asset\":\"JUMBLR\",\"rpcport\":15106},
{\"coin\":\"DOGE\", \"name\":\"dogecoin\", \"pubtype\":30, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000000},
{\"active\":0,\"coin\":\"HUSH\",\"name\":\"hush\",\"rpcport\":8822,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000 },
{\"active\":0,\"coin\":\"ZEC\",\"name\":\"zcash\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000 },
{\"coin\":\"DGB\", \"name\":\"digibyte\", \"pubtype\":30, \"p2shtype\":5, \"wiftype\":128, \"txfee\":10000},
{\"coin\":\"MZC\", \"name\":\"mazacoin\", \"pubtype\":50, \"p2shtype\":9, \"wiftype\":224, \"txfee\":0},
{\"coin\":\"SYS\", \"name\":\"syscoin\", \"pubtype\":0, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000},
{\"coin\":\"UNO\", \"name\":\"unobtanium\", \"pubtype\":130, \"p2shtype\":30, \"wiftype\":224, \"txfee\":1000000},
{\"coin\":\"ZET\", \"name\":\"zetacoin\", \"pubtype\":80, \"p2shtype\":9, \"wiftype\":224, \"txfee\":10000},
{\"coin\":\"ZEC\", \"name\":\"zcash\", \"pubtype\":184, \"p2shtype\":189, \"wiftype\":128, \"txfee\":10000},
{\"coin\":\"BTM\", \"name\":\"bitmark\", \"pubtype\":85, \"p2shtype\":5, \"wiftype\":213, \"txfee\":0},
{\"coin\":\"CARB\", \"name\":\"carboncoin\", \"pubtype\":47, \"p2shtype\":5, \"wiftype\":175, \"txfee\":0},
{\"coin\":\"ANC\", \"name\":\"anoncoin\", \"pubtype\":23, \"p2shtype\":5, \"wiftype\":151, \"txfee\":2000000},
{\"coin\":\"FRK\", \"name\":\"franko\", \"pubtype\":35, \"p2shtype\":5, \"wiftype\":163, \"txfee\":0},
{\"coin\":\"GAME\", \"name\":\"gamecredits\", \"pubtype\":38, \"p2shtype\":5, \"wiftype\":166, \"txfee\":100000},
{\"coin\":\"LTC\", \"name\":\"litecoin\", \"rpcport\":9332, \"pubtype\":48, \"p2shtype\":5, \"wiftype\":176, \"txfee\":100000 },
{\"coin\":\"SUPERNET\",\"asset\":\"SUPERNET\",\"rpcport\":11341},{\"coin\":\"WLC\",\"asset\":\"WLC\",\"rpcport\":12167},{\"coin\":\"PANGEA\",\"asset\":\"PANGEA\",\"rpcport\":14068},{\"coin\":\"DEX\",\"asset\":\"DEX\",\"rpcport\":11890},{\"coin\":\"BET\",\"asset\":\"BET\",\"rpcport\":14250},{\"coin\":\"CRYPTO\",\"asset\":\"CRYPTO\",\"rpcport\":8516},{\"coin\":\"HODL\",\"asset\":\"HODL\",\"rpcport\":14431},{\"coin\":\"SHARK\",\"asset\":\"SHARK\",\"rpcport\":10114},{\"coin\":\"BOTS\",\"asset\":\"BOTS\",\"rpcport\":11964},{\"coin\":\"MGW\",\"asset\":\"MGW\",\"rpcport\":12386},{\"coin\":\"COQUI\",\"asset\":\"COQUI\",\"rpcport\":12456},{\"coin\":\"KV\",\"asset\":\"KV\",\"rpcport\":9747},{\"coin\":\"CEAL\",\"asset\":\"CEAL\",\"rpcport\":11116},{\"coin\":\"MESH\",\"asset\":\"MESH\",\"rpcport\":9455}
], \"userhome\":\"/${HOME#"/"}\",\"passphrase\":\"$randval\"}" &

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
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
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 "OS_portable.h"
#define MAX(a,b) ((a) > (b) ? (a) : (b))
char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port);
char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,cJSON *argjson,char *remoteaddr,uint16_t port);
#include "stats.c"
void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32]);
#if defined(__APPLE__) || defined(WIN32) || defined(USE_STATIC_NANOMSG)
//defined(__APPLE__) ||
#if defined(WIN32) || defined(USE_STATIC_NANOMSG)
#include "../../crypto777/nanosrc/nn.h"
#include "../../crypto777/nanosrc/bus.h"
#include "../../crypto777/nanosrc/pubsub.h"
@ -70,7 +71,7 @@ char *DEX_swapstatus()
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"getswaplist\"}");
return(bitcoind_RPC(0,"InstantDEX",url,0,"getswaplist",postdata));
return(bitcoind_RPC(0,"InstantDEX",url,0,"getswaplist",postdata,0));
}
char *DEX_amlp(char *blocktrail)
@ -78,7 +79,7 @@ char *DEX_amlp(char *blocktrail)
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"amlp\",\"blocktrail\":\"%s\"}",blocktrail);
return(bitcoind_RPC(0,"tradebot",url,0,"amlp",postdata));
return(bitcoind_RPC(0,"tradebot",url,0,"amlp",postdata,0));
}
char *DEX_openorders(char *exchange)
@ -86,7 +87,7 @@ char *DEX_openorders(char *exchange)
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"openorders\",\"exchange\":\"%s\"}",exchange);
return(bitcoind_RPC(0,"InstantDEX",url,0,"openorders",postdata));
return(bitcoind_RPC(0,"InstantDEX",url,0,"openorders",postdata,0));
}
char *DEX_tradehistory(char *exchange)
@ -94,7 +95,7 @@ char *DEX_tradehistory(char *exchange)
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"tradehistory\",\"exchange\":\"%s\"}",exchange);
return(bitcoind_RPC(0,"InstantDEX",url,0,"tradehistory",postdata));
return(bitcoind_RPC(0,"InstantDEX",url,0,"tradehistory",postdata,0));
}
char *DEX_orderstatus(char *exchange,char *orderid)
@ -102,7 +103,7 @@ char *DEX_orderstatus(char *exchange,char *orderid)
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"orderstatus\",\"exchange\":\"%s\",\"orderid\":\"%s\"}",exchange,orderid);
return(bitcoind_RPC(0,"InstantDEX",url,0,"orderstatus",postdata));
return(bitcoind_RPC(0,"InstantDEX",url,0,"orderstatus",postdata,0));
}
char *DEX_cancelorder(char *exchange,char *orderid)
@ -110,7 +111,7 @@ char *DEX_cancelorder(char *exchange,char *orderid)
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"cancelorder\",\"exchange\":\"%s\",\"orderid\":\"%s\"}",exchange,orderid);
return(bitcoind_RPC(0,"InstantDEX",url,0,"cancelorder",postdata));
return(bitcoind_RPC(0,"InstantDEX",url,0,"cancelorder",postdata,0));
}
char *DEX_balance(char *exchange,char *base,char *coinaddr)
@ -120,12 +121,12 @@ char *DEX_balance(char *exchange,char *base,char *coinaddr)
if ( strcmp(exchange,"DEX") == 0 )
{
sprintf(postdata,"{\"agent\":\"dex\",\"method\":\"getbalance\",\"address\":\"%s\",\"symbol\":\"%s\"}",coinaddr,base);
return(bitcoind_RPC(0,"dex",url,0,"getbalance",postdata));
return(bitcoind_RPC(0,"dex",url,0,"getbalance",postdata,0));
}
else
{
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"balance\",\"exchange\":\"%s\",\"base\":\"%s\"}",exchange,base);
return(bitcoind_RPC(0,"InstantDEX",url,0,"balance",postdata));
return(bitcoind_RPC(0,"InstantDEX",url,0,"balance",postdata,0));
}
}
@ -134,7 +135,7 @@ char *DEX_apikeypair(char *exchange,char *apikey,char *apisecret)
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"apikeypair\",\"exchange\":\"%s\",\"apikey\":\"%s\",\"apisecret\":\"%s\"}",exchange,apikey,apisecret);
return(bitcoind_RPC(0,"InstantDEX",url,0,"apikeypair",postdata));
return(bitcoind_RPC(0,"InstantDEX",url,0,"apikeypair",postdata,0));
}
char *DEX_setuserid(char *exchange,char *userid,char *tradepassword)
@ -142,7 +143,7 @@ char *DEX_setuserid(char *exchange,char *userid,char *tradepassword)
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"setuserid\",\"exchange\":\"%s\",\"userid\":\"%s\",\"tradepassword\":\"%s\"}",exchange,userid,tradepassword);
return(bitcoind_RPC(0,"InstantDEX",url,0,"setuserid",postdata));
return(bitcoind_RPC(0,"InstantDEX",url,0,"setuserid",postdata,0));
}
char *DEX_trade(char *exchange,char *base,char *rel,int32_t dir,double price,double volume)
@ -151,7 +152,7 @@ char *DEX_trade(char *exchange,char *base,char *rel,int32_t dir,double price,dou
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"%s\",\"exchange\":\"%s\",\"base\":\"%s\",\"rel\":\"%s\",\"price\":%.8f,\"volume\":%.8f,\"dotrade\":1}",dir>0?"buy":"sell",exchange,base,rel,price,volume);
//printf("DEX_trade.(%s)\n",postdata);
return(bitcoind_RPC(0,"InstantDEX",url,0,dir>0?"buy":"sell",postdata));
return(bitcoind_RPC(0,"InstantDEX",url,0,dir>0?"buy":"sell",postdata,0));
}
char *DEX_withdraw(char *exchange,char *base,char *destaddr,double amount)
@ -159,7 +160,7 @@ char *DEX_withdraw(char *exchange,char *base,char *destaddr,double amount)
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"withdraw\",\"exchange\":\"%s\",\"destaddr\":\"%s\",\"amount\":%.8f}",exchange,destaddr,amount);
return(bitcoind_RPC(0,"InstantDEX",url,0,"withdraw",postdata));
return(bitcoind_RPC(0,"InstantDEX",url,0,"withdraw",postdata,0));
}
char *iguana_walletpassphrase(char *passphrase,int32_t timeout)
@ -167,7 +168,7 @@ char *iguana_walletpassphrase(char *passphrase,int32_t timeout)
char url[512],postdata[1024];
sprintf(url,"%s/coin=KMD&agent=bitcoinrpc&method=walletpassphrase?",IGUANA_URL);
sprintf(postdata,"[\"%s\", %d]",passphrase,timeout);
return(bitcoind_RPC(0,"",url,0,"walletpassphrase",postdata));
return(bitcoind_RPC(0,"",url,0,"walletpassphrase",postdata,0));
}
/*char *iguana_listunspent(char *coin,char *coinaddr)
@ -194,7 +195,7 @@ char *DEX_listunspent(char *coin,char *coinaddr)
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"dex\",\"method\":\"listunspent\",\"address\":\"%s\",\"symbol\":\"%s\",\"timeout\":60000}",coinaddr,coin);
return(bitcoind_RPC(0,"dex",url,0,"listunspent",postdata));
return(bitcoind_RPC(0,"dex",url,0,"listunspent",postdata,0));
}
bits256 iguana_wif2privkey(char *wifstr)
@ -203,7 +204,7 @@ bits256 iguana_wif2privkey(char *wifstr)
memset(privkey.bytes,0,sizeof(privkey));
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"SuperNET\",\"method\":\"wif2priv\",\"wif\":\"%s\"}",wifstr);
if ( (retstr= bitcoind_RPC(0,"SuperNET",url,0,"wif2priv",postdata)) != 0 )
if ( (retstr= bitcoind_RPC(0,"SuperNET",url,0,"wif2priv",postdata,0)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
@ -219,28 +220,6 @@ bits256 iguana_wif2privkey(char *wifstr)
return(privkey);
}
void iguana_priv2pub(uint8_t *pubkey33,char *coinaddr,bits256 privkey,uint8_t addrtype)
{
char privstr[65],url[512],postdata[1024],*retstr,*pubstr,*addr; cJSON *retjson;
memset(pubkey33,0,33);
coinaddr[0] = 0;
bits256_str(privstr,privkey);
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"SuperNET\",\"method\":\"priv2pub\",\"privkey\":\"%s\",\"addrtype\":%u}",privstr,addrtype);
if ( (retstr= bitcoind_RPC(0,"SuperNET",url,0,"priv2pub",postdata)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (pubstr= jstr(retjson,"secp256k1")) != 0 && strlen(pubstr) == 66 )
decode_hex(pubkey33,33,pubstr);
if ( (addr= jstr(retjson,"result")) != 0 && strlen(addr) < 64 )
strcpy(coinaddr,addr);
free_json(retjson);
}
free(retstr);
}
}
double bittrex_balance(char *base,char *coinaddr)
{
char *retstr; cJSON *retjson; double balance = 0.;
@ -623,7 +602,7 @@ int32_t marketmaker_spread(char *exchange,char *base,char *rel,double bid,double
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"%s\",\"vals\":%s}",base,jprint(vals,1));
//printf("(%s)\n",postdata);
if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata)) != 0 )
if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata,0)) != 0 )
{
//printf("(%s) -> (%s)\n",postdata,retstr);
free(retstr);
@ -643,7 +622,7 @@ int32_t marketmaker_spread(char *exchange,char *base,char *rel,double bid,double
jaddnum(vals,"minvol",MAX(1,(int32_t)(vol * 0.01 * PAXPRICES[i])));
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"%s\",\"vals\":%s}","KMD",jprint(vals,1));
if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata)) != 0 )
if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata,0)) != 0 )
{
//printf("(%s) -> (%s)\n",postdata,retstr);
free(retstr);
@ -811,15 +790,15 @@ void LP_main(void *ptr)
if ( (passphrase= jstr(argjson,"passphrase")) != 0 )
{
profitmargin = jdouble(argjson,"profitmargin");
LPinit(7779,7780,7781,profitmargin,passphrase,jint(argjson,"client"),jstr(argjson,"userhome"));
LPinit(7779,7780,7781,profitmargin,passphrase,jint(argjson,"client"),jstr(argjson,"userhome"),argjson);
}
}
int main(int argc, const char * argv[])
{
char *base,*rel,*name,*exchange,*apikey,*apisecret,*blocktrail,*retstr,*baseaddr,*reladdr,*passphrase;
double profitmargin,maxexposure,incrratio,start_rel,start_base,minask,maxbid,incr,theoretical = 0.;
cJSON *retjson,*loginjson,*matchjson; int32_t i;
double profitmargin,maxexposure,incrratio,start_rel,start_base,minask,maxbid,incr;
cJSON *retjson,*loginjson; int32_t i;
if ( argc > 1 && (retjson= cJSON_Parse(argv[1])) != 0 )
{
if ( (passphrase= jstr(retjson,"passphrase")) == 0 )
@ -829,29 +808,7 @@ int main(int argc, const char * argv[])
printf("error launching LP_main (%s)\n",jprint(retjson,0));
exit(-1);
} else printf("(%s) launched.(%s)\n",argv[1],passphrase);
if ( (0) && (retstr= basilisk_swaplist()) != 0 )
{
printf("%s\ngetchar to continue\n",retstr);
getchar();
free(retstr);
}
incr = 100.;
while ( (0) && IAMCLIENT != 0 )
{
theoretical = marketmaker_updateprice("komodo","REVS","KMD",theoretical,&incr);
sleep(3);
LP_privkey_updates(0,-1,passphrase,1);
if ( jint(retjson,"client") != 0 )
{
struct LP_utxoinfo *utxo,*utmp;
HASH_ITER(hh,LP_utxoinfos,utxo,utmp)
{
if ( strcmp(utxo->coin,"REVS") == 0 && (matchjson= LP_autotrade(utxo,"KMD",0.)) != 0 )
printf("bestprice (%s)\n",jprint(matchjson,1));
}
}
sleep(1000);
}
while ( 1 )
sleep(1);
profitmargin = jdouble(retjson,"profitmargin");

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 issue_NXTPOST(cmdstr) bitcoind_RPC(0,"curl",myinfo->NXTAPIURL,0,0,cmdstr)
#define issue_NXTPOST(cmdstr) bitcoind_RPC(0,"curl",myinfo->NXTAPIURL,0,0,cmdstr,0)
#define NXT_MSTYPE 5
#define NXT_ASSETTYPE 2
#define NXT_GENESISTIME 1385294400

2
iguana/exchanges/orderbook

@ -1,2 +1,2 @@
source userpass
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"orderbook\",\"base\":\"REVS\",\"rel\":\"KMD\"}"
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"orderbook\",\"base\":\"KMD\",\"rel\":\"BTC\"}"

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
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);
}
extern void *bitcoin_ctx();
char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *postflagp,char *urlstr,char *remoteaddr,char *filetype,uint16_t port)
{
cJSON *tokens,*argjson,*origargjson,*tmpjson=0,*json = 0; long filesize;
char symbol[64],buf[4096],*userpass=0,urlmethod[16],*data,url[8192],furl[8192],*retstr,*filestr,*token = 0; int32_t i,j,n,num=0;
static void *ctx;
cJSON *tokens,*argjson,*origargjson,*tmpjson=0,*json = 0; long filesize; double profitmargin = 0.; char *myipaddr="127.0.0.1",symbol[64],buf[4096],*userpass=0,urlmethod[16],*data,url[8192],furl[8192],*retstr,*filestr,*token = 0; int32_t i,j,n,num=0;
//printf("rpcparse.(%s)\n",urlstr);
if ( ctx == 0 )
ctx = bitcoin_ctx();
for (i=0; i<sizeof(urlmethod)-1&&urlstr[i]!=0&&urlstr[i]!=' '; i++)
urlmethod[i] = urlstr[i];
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 )
jaddstr(argjson,"userpass",userpass);
//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 )
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));
if ( userpass != 0 && jstr(arg,"userpass") == 0 )
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(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",
"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)
{

3
iguana/m_notary

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

2
iguana/tests/dexlistunspent

@ -1,2 +1,2 @@
#!/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);
void ensure_jsonitem(cJSON *json,char *field,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);
int32_t expand_nxt64bits(char *str,uint64_t nxt64bits);
char *nxt64str(uint64_t nxt64bits);

Loading…
Cancel
Save