Browse Source

Merge pull request #367 from jl777/spvdex

MNZ support
etomic
jl777 7 years ago
committed by GitHub
parent
commit
fc2923882a
  1. 12
      crypto777/iguana_OS.c
  2. 2
      iguana/coins/basilisk/mnz
  3. 2
      iguana/coins/mnz_7776
  4. 29
      iguana/exchanges/LP_bitcoin.c
  5. 29
      iguana/exchanges/LP_coins.c
  6. 187
      iguana/exchanges/LP_commands.c
  7. 61
      iguana/exchanges/LP_include.h
  8. 387
      iguana/exchanges/LP_nativeDEX.c
  9. 19
      iguana/exchanges/LP_network.c
  10. 721
      iguana/exchanges/LP_ordermatch.c
  11. 41
      iguana/exchanges/LP_peers.c
  12. 22
      iguana/exchanges/LP_portfolio.c
  13. 348
      iguana/exchanges/LP_prices.c
  14. 723
      iguana/exchanges/LP_remember.c
  15. 459
      iguana/exchanges/LP_rpc.c
  16. 111
      iguana/exchanges/LP_scan.c
  17. 311
      iguana/exchanges/LP_socket.c
  18. 608
      iguana/exchanges/LP_statemachine.c
  19. 52
      iguana/exchanges/LP_swap.c
  20. 108
      iguana/exchanges/LP_transaction.c
  21. 534
      iguana/exchanges/LP_utxo.c
  22. 495
      iguana/exchanges/LP_utxos.c
  23. 1
      iguana/exchanges/autofill
  24. 1
      iguana/exchanges/autoprice
  25. 1
      iguana/exchanges/autotrade
  26. 3
      iguana/exchanges/balance
  27. 1
      iguana/exchanges/balance_loop
  28. 1
      iguana/exchanges/bestfit
  29. 3
      iguana/exchanges/buy
  30. 1
      iguana/exchanges/cancelorder
  31. 1
      iguana/exchanges/client
  32. 1
      iguana/exchanges/client_osx
  33. 2
      iguana/exchanges/coins
  34. 1
      iguana/exchanges/debug
  35. 1
      iguana/exchanges/deletemessages
  36. 1
      iguana/exchanges/disable
  37. 1
      iguana/exchanges/dividends
  38. 3
      iguana/exchanges/electrum
  39. 3
      iguana/exchanges/electrum.chips
  40. 3
      iguana/exchanges/electrum.chips2
  41. 3
      iguana/exchanges/electrum.kmd
  42. 3
      iguana/exchanges/electrum.kmd2
  43. 3
      iguana/exchanges/electrum.kmd3
  44. 39
      iguana/exchanges/electrums
  45. 3
      iguana/exchanges/enable
  46. 1
      iguana/exchanges/getcoin
  47. 1
      iguana/exchanges/getcoins
  48. 1
      iguana/exchanges/getmessages
  49. 1
      iguana/exchanges/getpeers
  50. 1
      iguana/exchanges/getpeersIP
  51. 1
      iguana/exchanges/getprices
  52. 1
      iguana/exchanges/getutxos
  53. 1
      iguana/exchanges/goal
  54. 1
      iguana/exchanges/goals
  55. 1
      iguana/exchanges/help
  56. 5
      iguana/exchanges/install
  57. 3
      iguana/exchanges/inv
  58. 3
      iguana/exchanges/listunspent
  59. 1
      iguana/exchanges/loop
  60. 1
      iguana/exchanges/message
  61. 1
      iguana/exchanges/myprice
  62. 1
      iguana/exchanges/myprices
  63. 1
      iguana/exchanges/numutxos
  64. 1
      iguana/exchanges/orderbook
  65. 1
      iguana/exchanges/ordermatch
  66. 1
      iguana/exchanges/portfolio
  67. 1
      iguana/exchanges/pricearray
  68. 1
      iguana/exchanges/pub
  69. 1
      iguana/exchanges/register
  70. 1
      iguana/exchanges/registerall
  71. 1
      iguana/exchanges/run
  72. 1
      iguana/exchanges/run_osx
  73. 1
      iguana/exchanges/secretaddresses
  74. 3
      iguana/exchanges/sell
  75. 1
      iguana/exchanges/setprice
  76. 1
      iguana/exchanges/snapshot
  77. 1
      iguana/exchanges/snapshot_balance
  78. 1
      iguana/exchanges/snapshot_loop
  79. 1
      iguana/exchanges/status
  80. 1
      iguana/exchanges/swapstatus
  81. 1
      iguana/exchanges/trade
  82. 1
      iguana/exchanges/utxos
  83. 2
      iguana/iguana_notary.c
  84. 1
      iguana/m_notary

12
crypto777/iguana_OS.c

@ -297,11 +297,11 @@ void *queue_dequeue(queue_t *queue)//,int32_t offsetflag)
void *queue_delete(queue_t *queue,struct queueitem *copy,int32_t copysize,int32_t freeitem)
{
struct allocitem *ptr;
struct queueitem *item = 0;
struct queueitem *tmp,*item = 0;
lock_queue(queue);
if ( queue->list != 0 )
{
DL_FOREACH(queue->list,item)
DL_FOREACH_SAFE(queue->list,item,tmp)
{
ptr = (void *)((long)item - sizeof(struct allocitem));
if ( item == copy || (ptr->allocsize == copysize && memcmp((void *)((long)item + sizeof(struct queueitem)),(void *)((long)item + sizeof(struct queueitem)),copysize) == 0) )
@ -321,11 +321,11 @@ void *queue_delete(queue_t *queue,struct queueitem *copy,int32_t copysize,int32_
void *queue_free(queue_t *queue)
{
struct queueitem *item = 0;
struct queueitem *tmp,*item = 0;
lock_queue(queue);
if ( queue->list != 0 )
{
DL_FOREACH(queue->list,item)
DL_FOREACH_SAFE(queue->list,item,tmp)
{
DL_DELETE(queue->list,item);
myfree(item,sizeof(struct queueitem));
@ -338,11 +338,11 @@ void *queue_free(queue_t *queue)
void *queue_clone(queue_t *clone,queue_t *queue,int32_t size)
{
struct queueitem *ptr,*item = 0;
struct queueitem *ptr,*tmp,*item = 0;
lock_queue(queue);
if ( queue->list != 0 )
{
DL_FOREACH(queue->list,item)
DL_FOREACH_SAFE(queue->list,item,tmp)
{
ptr = mycalloc('c',1,sizeof(*ptr));
memcpy(ptr,item,size);

2
iguana/coins/basilisk/mnz

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"MNZ.conf\",\"path\":\"${HOME#"/"}/.komodo/MNZ\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":0,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"MNZ\",\"name\":\"MNZ\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"53d06fde\",\"p2p\":14336,\"rpc\":14337,\"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/mnz_7776

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"MNZ.conf\",\"path\":\"${HOME#"/"}/.komodo/MNZ\",\"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\":\"MNZ\",\"name\":\"MNZ\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"53d06fde\",\"p2p\":14336,\"rpc\":14337,\"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\"}"

29
iguana/exchanges/LP_bitcoin.c

@ -325,14 +325,12 @@ enum opcodetype
OP_INVALIDOPCODE = 0xff,
};
struct { bits256 privkey; uint8_t rmd160[20]; } LP_privkeys[100]; int32_t LP_numprivkeys;
bits256 LP_privkeyfind(uint8_t rmd160[20])
{
int32_t i; static bits256 zero;
for (i=0; i<LP_numprivkeys; i++)
if ( memcmp(rmd160,LP_privkeys[i].rmd160,20) == 0 )
return(LP_privkeys[i].privkey);
for (i=0; i<G.LP_numprivkeys; i++)
if ( memcmp(rmd160,G.LP_privkeys[i].rmd160,20) == 0 )
return(G.LP_privkeys[i].privkey);
//for (i=0; i<20; i++)
// printf("%02x",rmd160[i]);
//printf(" -> no privkey\n");
@ -345,13 +343,13 @@ int32_t LP_privkeyadd(bits256 privkey,uint8_t rmd160[20])
tmpkey = LP_privkeyfind(rmd160);
if ( bits256_nonz(tmpkey) != 0 )
return(-bits256_cmp(privkey,tmpkey));
LP_privkeys[LP_numprivkeys].privkey = privkey;
memcpy(LP_privkeys[LP_numprivkeys].rmd160,rmd160,20);
G.LP_privkeys[G.LP_numprivkeys].privkey = privkey;
memcpy(G.LP_privkeys[G.LP_numprivkeys].rmd160,rmd160,20);
//int32_t i; for (i=0; i<20; i++)
// printf("%02x",rmd160[i]);
//char str[65]; printf(" -> add privkey.(%s)\n",bits256_str(str,privkey));
LP_numprivkeys++;
return(LP_numprivkeys);
G.LP_numprivkeys++;
return(G.LP_numprivkeys);
}
int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp)
@ -2619,7 +2617,8 @@ cJSON *bitcoin_txscript(char *asmstr,char **vardata,int32_t numvars)
{
int32_t i; cJSON *scriptjson,*array;
scriptjson = cJSON_CreateObject();
jaddstr(scriptjson,"asm",asmstr);
if ( asmstr != 0 )
jaddstr(scriptjson,"asm",asmstr);
jaddnum(scriptjson,"numvars",numvars);
if ( numvars > 0 )
{
@ -3186,7 +3185,7 @@ int32_t iguana_parsevoutobj(uint8_t *serialized,int32_t maxsize,struct iguana_ms
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;
char scriptstr[IGUANA_MAXSCRIPTSIZE+1]; int32_t i,m,n,scriptlen,asmtype; struct vin_info *vp;
uint8_t space[8192]; cJSON *addrs,*skey,*json = cJSON_CreateObject();
vp = calloc(1,sizeof(*vp));
jadd64bits(json,"satoshis",vout->value);
@ -3196,12 +3195,12 @@ cJSON *iguana_voutjson(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,struct igu
if ( vout->pk_script != 0 && vout->pk_scriptlen*2+1 < sizeof(scriptstr) )
{
memset(vp,0,sizeof(*vp));
if ( (asmtype= iguana_calcrmd160(taddr,pubtype,p2shtype,asmstr,vp,vout->pk_script,vout->pk_scriptlen,txid,txi,0xffffffff)) >= 0 )
if ( (asmtype= iguana_calcrmd160(taddr,pubtype,p2shtype,0,vp,vout->pk_script,vout->pk_scriptlen,txid,txi,0xffffffff)) >= 0 )
{
skey = cJSON_CreateObject();
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);
scriptlen = iguana_scriptgen(taddr,pubtype,p2shtype,&m,&n,vp->coinaddr,space,0,vp->rmd160,asmtype,vp,txi);
//if ( asmstr[0] != 0 )
// jaddstr(skey,"asm",asmstr);
addrs = cJSON_CreateArray();
if ( vp->N == 1 )
{

29
iguana/exchanges/LP_coins.c

@ -172,13 +172,14 @@ int32_t LP_userpass(char *userpass,char *symbol,char *assetname,char *confroot,c
cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif)
{
char wifstr[128]; uint8_t tmptype; bits256 checkkey; cJSON *item = cJSON_CreateObject();
struct electrum_info *ep; char wifstr[128],ipaddr[64]; uint8_t tmptype; bits256 checkkey; cJSON *item = cJSON_CreateObject();
jaddstr(item,"coin",coin->symbol);
jaddnum(item,"height",coin->height);
if ( showwif != 0 )
{
bitcoin_priv2wif(coin->wiftaddr,wifstr,LP_mypriv25519,coin->wiftype);
bitcoin_priv2wif(coin->wiftaddr,wifstr,G.LP_mypriv25519,coin->wiftype);
bitcoin_wif2priv(coin->wiftaddr,&tmptype,&checkkey,wifstr);
if ( bits256_cmp(LP_mypriv25519,checkkey) == 0 )
if ( bits256_cmp(G.LP_mypriv25519,checkkey) == 0 )
jaddstr(item,"wif",wifstr);
else jaddstr(item,"wif","error creating wif");
}
@ -187,6 +188,11 @@ cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif)
else jaddstr(item,"status","active");
if ( coin->isPoS != 0 )
jaddstr(item,"type","PoS");
if ( (ep= coin->electrum) != 0 )
{
sprintf(ipaddr,"%s:%u",ep->ipaddr,ep->port);
jaddstr(item,"electrum",ipaddr);
}
jaddstr(item,"smartaddress",coin->smartaddr);
jaddstr(item,"rpc",coin->serverport);
jaddnum(item,"pubtype",coin->pubtype);
@ -196,6 +202,19 @@ cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif)
return(item);
}
struct iguana_info *LP_conflicts_find(struct iguana_info *refcoin)
{
struct iguana_info *coin=0,*tmp;
HASH_ITER(hh,LP_coins,coin,tmp)
{
if ( coin->inactive != 0 || coin->electrum != 0 || coin == refcoin )
continue;
if ( strcmp(coin->serverport,refcoin->serverport) == 0 )
break;
}
return(coin);
}
cJSON *LP_coinsjson(int32_t showwif)
{
struct iguana_info *coin,*tmp; cJSON *array = cJSON_CreateArray();
@ -243,6 +262,7 @@ struct iguana_info *LP_coinadd(struct iguana_info *cdata)
//printf("%s: (%s) (%s)\n",symbol,cdata.serverport,cdata.userpass);
*coin = *cdata;
portable_mutex_init(&coin->txmutex);
portable_mutex_init(&coin->addrmutex);
portable_mutex_lock(&LP_coinmutex);
HASH_ADD_KEYPTR(hh,LP_coins,coin->symbol,strlen(coin->symbol),coin);
portable_mutex_unlock(&LP_coinmutex);
@ -255,6 +275,7 @@ int32_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *asset
memset(coin,0,sizeof(*coin));
safecopy(coin->symbol,symbol,sizeof(coin->symbol));
sprintf(coin->serverport,"127.0.0.1:%u",port);
coin->updaterate = (uint32_t)time(NULL);
coin->isPoS = isPoS;
coin->taddr = taddr;
coin->wiftaddr = wiftaddr;
@ -290,6 +311,8 @@ int32_t LP_isdisabled(char *base,char *rel)
struct iguana_info *LP_coinfind(char *symbol)
{
struct iguana_info *coin,cdata; int32_t isinactive,isPoS,longestchain = 1; uint16_t port,busport; uint64_t txfee; double estimatedrate; uint8_t pubtype,p2shtype,wiftype; char *name,*assetname;
if ( symbol == 0 || symbol[0] == 0 )
return(0);
if ( (coin= LP_coinsearch(symbol)) != 0 )
return(coin);
if ( (port= LP_rpcport(symbol)) == 0 )

187
iguana/exchanges/LP_commands.c

@ -25,18 +25,19 @@ char *LP_numutxos()
{
jaddstr(retjson,"ipaddr",LP_mypeer->ipaddr);
jaddnum(retjson,"port",LP_mypeer->port);
jaddnum(retjson,"numutxos",LP_mypeer->numutxos);
//jaddnum(retjson,"numutxos",LP_mypeer->numutxos);
jaddnum(retjson,"numpeers",LP_mypeer->numpeers);
jaddnum(retjson,"session",LP_sessionid);
jaddnum(retjson,"session",G.LP_sessionid);
} else jaddstr(retjson,"error","client node");
return(jprint(retjson,1));
}
char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port
{
char *method,*ipaddr,*userpass,*base,*rel,*coin,*retstr = 0; uint16_t argport=0,pushport,subport; int32_t changed,otherpeers,othernumutxos,flag = 0; struct LP_peerinfo *peer; cJSON *retjson,*reqjson = 0; struct iguana_info *ptr;
char *method,*ipaddr,*userpass,*base,*rel,*coin,*retstr = 0; uint16_t argport=0,pushport,subport; int32_t changed,otherpeers,flag = 0; struct LP_peerinfo *peer; cJSON *retjson,*reqjson = 0; struct iguana_info *ptr;
//printf("stats_JSON(%s)\n",jprint(argjson,0));
if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 )
method = jstr(argjson,"method");
if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 && (method == 0 || strcmp(method,"electrum") != 0) )
{
if ( strcmp(ipaddr,"127.0.0.1") != 0 && argport >= 1000 )
{
@ -49,18 +50,18 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r
{
if ( 0 && (otherpeers= jint(argjson,"numpeers")) > peer->numpeers )
peer->numpeers = otherpeers;
if ( 0 && (othernumutxos= jint(argjson,"numutxos")) > peer->numutxos )
/*if ( 0 && (othernumutxos= jint(argjson,"numutxos")) > peer->numutxos )
{
printf("change.(%s) numutxos.%d -> %d mynumutxos.%d\n",peer->ipaddr,peer->numutxos,othernumutxos,LP_mypeer != 0 ? LP_mypeer->numutxos:0);
peer->numutxos = othernumutxos;
}
}*/
if ( peer->sessionid == 0 )
peer->sessionid = juint(argjson,"session");
//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,jint(argjson,"numpeers"),jint(argjson,"numutxos"),juint(argjson,"session"));
}
}
if ( (method= jstr(argjson,"method")) == 0 )
if ( method == 0 )
{
if ( flag == 0 || jobj(argjson,"result") != 0 )
printf("stats_JSON no method: (%s) (%s:%u)\n",jprint(argjson,0),ipaddr,argport);
@ -75,7 +76,7 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r
{
static char *laststr;
char *newstr; bits256 pubkey = jbits256(argjson,"pubkey");
if ( bits256_nonz(pubkey) == 0 || bits256_cmp(pubkey,LP_mypub25519) == 0 )
if ( bits256_nonz(pubkey) == 0 || bits256_cmp(pubkey,G.LP_mypub25519) == 0 )
{
newstr = jprint(argjson,0);
if ( laststr == 0 || strcmp(laststr,newstr) != 0 )
@ -103,9 +104,7 @@ enable(coin)\n\
disable(coin)\n\
inventory(coin)\n\
bestfit(rel, relvolume)\n\
ordermatch(base, txfee=0, rel, desttxfee=0, price, relvolume=0, txid, vout, feetxid, feevout, duration=3600)\n\
trade(price, timeout=10, duration=3600, <quotejson returned from ordermatch>)\n\
autotrade(base, rel, price, relvolume, timeout=10, duration=3600)\n\
buy(base, rel, price, relvolume, timeout=10, duration=3600)\n\
swapstatus()\n\
swapstatus(requestid, quoteid)\n\
public API:\n \
@ -113,8 +112,9 @@ getcoins()\n\
getcoin(coin)\n\
portfolio()\n\
getpeers()\n\
getutxos()\n\
getutxos(coin, lastn)\n\
passphrase(passphrase, gui)\n\
listunspent(coin, address)\n\
balance(coin, address)\n\
orderbook(base, rel, duration=3600)\n\
getprices(base, rel)\n\
sendmessage(base=coin, rel="", pubkey=zero, <argjson method2>)\n\
@ -126,22 +126,24 @@ snapshot(coin, height)\n\
snapshot_balance(coin, height, addresses[])\n\
dividends(coin, height, <args>)\n\
\"}"));
//sell(base, rel, price, basevolume, timeout=10, duration=3600)\n\
base = jstr(argjson,"base");
rel = jstr(argjson,"rel");
if ( USERPASS[0] != 0 && strcmp(remoteaddr,"127.0.0.1") == 0 && port != 0 )
coin = jstr(argjson,"coin");
if ( G.USERPASS[0] != 0 && strcmp(remoteaddr,"127.0.0.1") == 0 && port != 0 )
{
if ( USERPASS_COUNTER == 0 )
if ( G.USERPASS_COUNTER == 0 )
{
USERPASS_COUNTER = 1;
G.USERPASS_COUNTER = 1;
retjson = cJSON_CreateObject();
jaddstr(retjson,"userpass",USERPASS);
jaddbits256(retjson,"mypubkey",LP_mypub25519);
jaddstr(retjson,"userpass",G.USERPASS);
jaddbits256(retjson,"mypubkey",G.LP_mypub25519);
jadd(retjson,"coins",LP_coinsjson(LP_showwif));
return(jprint(retjson,1));
}
if ( (userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,USERPASS) != 0 )
return(clonestr("{\"error\":\"authentication error\"}"));
if ( (userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,G.USERPASS) != 0 )
return(clonestr("{\"error\":\"authentication error you need to make sure userpass is set\"}"));
jdelete(argjson,"userpass");
if ( strcmp(method,"sendmessage") == 0 )
{
@ -163,6 +165,18 @@ dividends(coin, height, <args>)\n\
LP_deletemessages(jint(argjson,"firsti"),jint(argjson,"num"));
return(clonestr("{\"result\":\"success\"}"));
}
else if ( strcmp(method,"passphrase") == 0 )
{
if ( LP_passphrase_init(jstr(argjson,"passphrase"),jstr(argjson,"gui")) < 0 )
return(clonestr("{\"error\":\"couldnt change passphrase\"}"));
{
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"userpass",G.USERPASS);
jaddbits256(retjson,"mypubkey",G.LP_mypub25519);
return(jprint(retjson,1));
}
}
else if ( strcmp(method,"portfolio") == 0 )
{
return(LP_portfolio());
@ -213,26 +227,18 @@ dividends(coin, height, <args>)\n\
return(jprint(retjson,1));
} else return(clonestr("{\"error\":\"no price set\"}"));
}
else if ( strcmp(method,"ordermatch") == 0 )
else if ( strcmp(method,"buy") == 0 )
{
if ( price > SMALLVAL )
return(LP_ordermatch(base,j64bits(argjson,"txfee"),price,jdouble(argjson,"relvolume"),rel,jbits256(argjson,"txid"),jint(argjson,"vout"),jbits256(argjson,"feetxid"),jint(argjson,"feevout"),j64bits(argjson,"desttxfee"),jint(argjson,"duration")));
else return(clonestr("{\"error\":\"no price set\"}"));
}
else if ( strcmp(method,"trade") == 0 )
{
struct LP_quoteinfo Q;
if ( price > SMALLVAL || jobj(argjson,"quote") != 0 )
{
LP_quoteparse(&Q,jobj(argjson,"quote"));
return(LP_trade(ctx,myipaddr,pubsock,&Q,price,jint(argjson,"timeout"),jint(argjson,"duration")));
} else return(clonestr("{\"error\":\"no price set or no quote object\"}"));
return(LP_autobuy(ctx,myipaddr,pubsock,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui")));
} else return(clonestr("{\"error\":\"no price set\"}"));
}
else if ( strcmp(method,"autotrade") == 0 )
else if ( strcmp(method,"sell") == 0 )
{
if ( price > SMALLVAL )
{
return(LP_autotrade(ctx,myipaddr,pubsock,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration")));
return(LP_autobuy(ctx,myipaddr,pubsock,rel,base,1./price,jdouble(argjson,"basevolume"),jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui")));
} else return(clonestr("{\"error\":\"no price set\"}"));
}
}
@ -248,7 +254,11 @@ dividends(coin, height, <args>)\n\
if ( strcmp(method,"enable") == 0 )
{
if ( (ptr= LP_coinsearch(coin)) != 0 )
ptr->inactive = 0;
{
if ( LP_conflicts_find(ptr) == 0 )
ptr->inactive = 0;
else return(clonestr("{\"error\":\"coin port conflicts with existing coin\"}"));
}
return(jprint(LP_coinsjson(0),1));
}
else if ( strcmp(method,"disable") == 0 )
@ -292,14 +302,15 @@ dividends(coin, height, <args>)\n\
{
//privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,ptr,"",USERPASS_WIFSTR);
//LP_utxopurge(0);
if ( bits256_nonz(LP_mypriv25519) != 0 )
LP_privkey_init(-1,ptr,LP_mypriv25519,LP_mypub25519);
if ( bits256_nonz(G.LP_mypriv25519) != 0 )
LP_privkey_init(-1,ptr,G.LP_mypriv25519,G.LP_mypub25519);
else printf("no LP_mypriv25519\n");
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));
jadd(retjson,"alice",LP_inventory(coin));
//jadd(retjson,"bob",LP_inventory(coin,1));
return(jprint(retjson,1));
}
}
@ -335,28 +346,67 @@ dividends(coin, height, <args>)\n\
argjson = reqjson;
}
}
if ( IAMLP == 0 && LP_isdisabled(base,rel) != 0 )
if ( strcmp(method,"postprice") == 0 )
retstr = LP_postedprice(argjson);
else if ( strcmp(method,"postutxos") == 0 )
retstr = LP_postedutxos(argjson);
else if ( strcmp(method,"getprices") == 0 )
return(LP_prices());
else if ( strcmp(method,"uitem") == 0 )
{
bits256 txid; int32_t vout,height; uint64_t value; char *coinaddr;
txid = jbits256(argjson,"txid");
vout = jint(argjson,"vout");
height = jint(argjson,"ht");
value = j64bits(argjson,"value");
coinaddr = jstr(argjson,"coinaddr");
if ( coin != 0 && coinaddr != 0 )
{
//char str[65]; printf("uitem %s %s %s/v%d %.8f ht.%d\n",coin,coinaddr,bits256_str(str,txid),vout,dstr(value),height);
LP_address_utxoadd(LP_coinfind(coin),coinaddr,txid,vout,value,height,-1);
}
return(clonestr("{\"result\":\"success\"}"));
}
else if ( strcmp(method,"orderbook") == 0 )
return(LP_orderbook(base,rel,jint(argjson,"duration")));
else if ( strcmp(method,"listunspent") == 0 )
{
if ( (ptr= LP_coinsearch(jstr(argjson,"coin"))) != 0 )
return(jprint(LP_address_utxos(ptr,jstr(argjson,"address"),1),1));
else return(clonestr("{\"error\":\"cant find coind\"}"));
}
else if ( strcmp(method,"balance") == 0 )
{
if ( (ptr= LP_coinsearch(jstr(argjson,"coin"))) != 0 )
return(jprint(LP_address_balance(ptr,jstr(argjson,"address"),1),1));
else return(clonestr("{\"error\":\"cant find coind\"}"));
}
else if ( IAMLP == 0 && LP_isdisabled(base,rel) != 0 )
return(clonestr("{\"result\":\"at least one of coins disabled\"}"));
else if ( IAMLP == 0 && LP_isdisabled(jstr(argjson,"coin"),0) != 0 )
retstr = clonestr("{\"result\":\"coin is disabled\"}");
else if ( strcmp(method,"reserved") == 0 )
{
//printf("RESERVED.(%s)\n",jprint(argjson,0));
retstr = LP_quotereceived(argjson);
}
else if ( strcmp(method,"connected") == 0 )
{
//printf("CONNECTED.(%s)\n",jprint(argjson,0));
retstr = LP_connectedalice(argjson);
}
else if ( strcmp(method,"checktxid") == 0 )
retstr = LP_spentcheck(argjson);
else if ( strcmp(method,"getcoins") == 0 )
return(jprint(LP_coinsjson(0),1));
else if ( strcmp(method,"numutxos") == 0 )
return(LP_numutxos());
else if ( strcmp(method,"postprice") == 0 )
retstr = LP_postedprice(argjson);
{
printf("deprecated numutxos received\n");
retstr = clonestr("{\"result\":\"couldnt add utxo\"}");
//return(LP_numutxos());
}
else if ( strcmp(method,"encrypted") == 0 )
retstr = clonestr("{\"result\":\"success\"}");
else if ( strcmp(method,"getprices") == 0 )
return(LP_prices());
else if ( strcmp(method,"orderbook") == 0 )
return(LP_orderbook(base,rel,jint(argjson,"duration")));
else if ( strcmp(method,"registerall") == 0 )
return(clonestr("{\"error\":\"you are running an obsolete version, update\"}"));
else if ( strcmp(method,"forward") == 0 )
@ -366,12 +416,20 @@ dividends(coin, height, <args>)\n\
else if ( strcmp(method,"getpeers") == 0 )
return(LP_peers());
else if ( strcmp(method,"getutxos") == 0 )
return(LP_utxos(1,LP_mypeer,jstr(argjson,"coin"),jint(argjson,"lastn")));
{
printf("deprecated getutxos received\n");
retstr = clonestr("{\"result\":\"couldnt add utxo\"}");
//return(LP_utxos(1,LP_mypeer,jstr(argjson,"coin"),jint(argjson,"lastn")));
}
else if ( strcmp(method,"utxo") == 0 )
{
if ( LP_utxoaddjson(1,LP_mypubsock,argjson) != 0 )
retstr = clonestr("{\"result\":\"success\",\"utxo\":\"received\"}");
else retstr = clonestr("{\"result\":\"couldnt add utxo\"}");
static uint32_t counter;
if ( counter++ < 3 )
printf("deprecated utxo received\n");
//if ( LP_utxoaddjson(1,LP_mypubsock,argjson) != 0 )
// retstr = clonestr("{\"result\":\"success\",\"utxo\":\"received\"}");
//else
retstr = clonestr("{\"result\":\"couldnt add utxo\"}");
}
else
{
@ -382,6 +440,25 @@ dividends(coin, height, <args>)\n\
firsttime = (uint32_t)(time(NULL)-30*24*3600);
return(jprint(LP_pricearray(base,rel,firsttime,juint(argjson,"lasttime"),jint(argjson,"timescale")),1));
}
else if ( strcmp(method,"notify") == 0 )
{
char *rmd160str,*secpstr; bits256 pub; struct LP_pubkeyinfo *pubp;
pub = jbits256(argjson,"pub");
if ( bits256_nonz(pub) != 0 && (rmd160str= jstr(argjson,"rmd160")) != 0 && strlen(rmd160str) == 40 )
{
if ( (pubp= LP_pubkeyadd(pub)) != 0 )
{
decode_hex(pubp->rmd160,20,rmd160str);
if ( (secpstr= jstr(argjson,"pubsecp")) != 0 )
{
decode_hex(pubp->pubsecp,sizeof(pubp->pubsecp),secpstr);
//printf("got pubkey.(%s)\n",secpstr);
}
}
//printf("NOTIFIED pub %s rmd160 %s\n",bits256_str(str,pub),rmd160str);
}
retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}");
}
if ( IAMLP != 0 )
{
if ( strcmp(method,"register") == 0 )
@ -393,6 +470,7 @@ dividends(coin, height, <args>)\n\
bits256 zero; char *cipherstr; int32_t cipherlen; uint8_t cipher[LP_ENCRYPTED_MAXSIZE];
if ( (reqjson= LP_dereference(argjson,"broadcast")) != 0 )
{
Broadcaststr = jprint(reqjson,0);
if ( (cipherstr= jstr(reqjson,"cipher")) != 0 )
{
cipherlen = (int32_t)strlen(cipherstr) >> 1;
@ -404,8 +482,11 @@ dividends(coin, height, <args>)\n\
}
else
{
char *msg;
memset(zero.bytes,0,sizeof(zero));
LP_broadcast_message(LP_mypubsock,base!=0?base:jstr(argjson,"coin"),rel,zero,jprint(reqjson,0));
msg = jprint(reqjson,0);
//printf("broadcast.(%s)\n",msg);
LP_broadcast_message(LP_mypubsock,base!=0?base:jstr(argjson,"coin"),rel,zero,msg);
}
retstr = clonestr("{\"result\":\"success\"}");
} else retstr = clonestr("{\"error\":\"couldnt dereference sendmessage\"}");
@ -422,8 +503,6 @@ dividends(coin, height, <args>)\n\
return(LP_psock(myipaddr,jint(argjson,"ispaired")));
else return(clonestr("{\"error\":\"you are running an obsolete version, update\"}"));
}
else if ( strcmp(method,"notify") == 0 )
retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}");
}
else
{

61
iguana/exchanges/LP_include.h

@ -45,10 +45,10 @@
#define LP_SWAPSTEP_TIMEOUT 30
#define LP_AUTOTRADE_TIMEOUT 60
#define LP_MIN_TXFEE 10000
#define LP_MINVOL 10
#define LP_MINCLIENTVOL 20
#define LP_MINVOL 20
#define LP_MINCLIENTVOL 50
#define LP_MINSIZE_TXFEEMULT 10
#define LP_REQUIRED_TXFEE 0.95
#define LP_REQUIRED_TXFEE 0.8
#define LP_DEXFEE(destsatoshis) ((destsatoshis) / INSTANTDEX_INSURANCEDIV)
#define LP_DEPOSITSATOSHIS(satoshis) ((satoshis) + (satoshis >> 3))
@ -75,8 +75,8 @@
#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 IAMLP,USERPASS_COUNTER;
extern char GLOBAL_DBDIR[];
extern int32_t IAMLP;
struct iguana_msgvin { bits256 prev_hash; uint8_t *vinscript,*userdata,*spendscript,*redeemscript; uint32_t prev_vout,sequence; uint16_t scriptlen,p2shlen,userdatalen,spendlen; };
@ -167,22 +167,23 @@ struct basilisk_swapinfo
uint8_t userdata_bobrefund[256],userdata_bobrefundlen;
};
struct LP_outpoint { bits256 spendtxid; uint64_t value,interest; int32_t spendvini,spendheight; char coinaddr[40]; };
struct LP_outpoint { bits256 spendtxid; uint64_t value,interest; int32_t spendvini,spendheight; char coinaddr[64]; };
struct LP_transaction
{
UT_hash_handle hh;
bits256 txid; int32_t height,numvouts,numvins; //uint32_t timestamp;
bits256 txid; int32_t height,numvouts,numvins,len; //uint32_t timestamp;
uint8_t *serialized;
struct LP_outpoint outpoints[];
};
struct iguana_info
{
UT_hash_handle hh;
portable_mutex_t txmutex; struct LP_transaction *transactions; struct LP_address *addresses;
portable_mutex_t txmutex,addrmutex; struct LP_transaction *transactions; struct LP_address *addresses;
uint64_t txfee;
int32_t longestchain,firstrefht,firstscanht,lastscanht,bussock,height; uint16_t busport;
uint32_t counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,unspenttime;
uint32_t lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,unspenttime,obooktime;
uint8_t pubtype,p2shtype,isPoS,wiftype,wiftaddr,taddr,noimportprivkey_flag;
char symbol[16],smartaddr[64],userpass[1024],serverport[128],lastunspent[64];
// portfolio
@ -192,7 +193,7 @@ struct iguana_info
uint8_t pubkey33[33];
};
struct _LP_utxoinfo { bits256 txid; uint64_t value; int32_t vout; };
struct _LP_utxoinfo { bits256 txid; uint64_t value; int32_t vout,height; };
struct LP_utxostats { uint32_t sessionid,lasttime,errors,swappending,spentflag,lastspentcheck,bestflag; };
@ -209,34 +210,35 @@ struct LP_utxoinfo
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)];
uint8_t key2[sizeof(bits256) + sizeof(int32_t)];
char coin[16],coinaddr[64],spendscript[256],gui[16];
char coin[16],coinaddr[64],gui[16];//spendscript[256];
};
struct LP_address_utxo
{
struct LP_address_utxo *next,*prev;
struct _LP_utxoinfo U;
uint32_t height,SPV,spentflag;
int32_t SPV,spendheight;
};
struct LP_address
{
UT_hash_handle hh;
struct LP_address_utxo *utxos;
int64_t balance;
uint32_t monitor;
bits256 pubkey;
int64_t balance,total;
uint32_t timestamp,n;
char coinaddr[40];
uint8_t pubsecp[33],pad;
};
struct LP_peerinfo
{
UT_hash_handle hh;
uint64_t ip_port;
uint32_t ipbits,errortime,errors,numpeers,numutxos,lasttime,connected,lastutxos,lastpeers,diduquery,good,sessionid;
uint32_t ipbits,errortime,errors,numpeers,needping,lasttime,connected,lastutxos,lastpeers,diduquery,good,sessionid;
int32_t pushsock,subsock;
uint16_t port;
char ipaddr[64];
@ -267,7 +269,7 @@ struct basilisk_swap
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];
uint8_t persistent_pubkey33[33],changermd160[20],pad[15],verifybuf[100000];
};
@ -285,24 +287,43 @@ int32_t LP_forward(void *ctx,char *myipaddr,int32_t pubsock,bits256 pubkey,char
int32_t LP_ismine(struct LP_utxoinfo *utxo);
int32_t LP_isavailable(struct LP_utxoinfo *utxo);
struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port);
uint64_t LP_value_extract(cJSON *obj,int32_t addinterest);
char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen);
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);
int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsock,int32_t pullsock);
uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired);
void LP_utxo_clientpublish(struct LP_utxoinfo *utxo);
//void LP_utxo_clientpublish(struct LP_utxoinfo *utxo);
int32_t LP_coinbus(uint16_t coin_busport);
struct iguana_info *LP_coinfind(char *symbol);
int32_t LP_crc32find(int32_t *duplicatep,int32_t ind,uint32_t crc32);
char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *rel,double price);
uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee);
struct LP_address *_LP_address(struct iguana_info *coin,char *coinaddr);
struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr);
struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr);
int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,struct iguana_msgtx *msgtx,char **signedtxp,bits256 *signedtxidp,struct vin_info *V,int32_t numinputs,char *rawtx,cJSON *vins,cJSON *privkeysjson);
int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t duration);
//void LP_butxo_swapfields_set(struct LP_utxoinfo *butxo);
struct LP_address_utxo *LP_address_utxofind(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout);
int32_t LP_destaddr(char *destaddr,cJSON *item);
int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t duration);
struct LP_transaction *LP_transactionfind(struct iguana_info *coin,bits256 txid);
int32_t LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter);
cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJSON *txobj);
int32_t LP_mempoolscan(char *symbol,bits256 searchtxid);
int32_t LP_txheight(struct iguana_info *coin,bits256 txid);
int32_t LP_address_utxoadd(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight);
cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrumret);
cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout);
void LP_postutxos(char *symbol,char *coinaddr);
int32_t LP_listunspent_both(char *symbol,char *coinaddr);
uint16_t LP_randpeer(char *destip);
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 LP_butxo_findeither(bits256 txid,int32_t vout);
cJSON *LP_listunspent(char *symbol,char *coinaddr);
int32_t LP_gettx_presence(char *symbol,bits256 expectedtxid);
double LP_getestimatedrate(struct iguana_info *coin);
struct LP_utxoinfo *_LP_utxofind(int32_t iambob,bits256 txid,int32_t vout);
struct LP_utxoinfo *_LP_utxo2find(int32_t iambob,bits256 txid,int32_t vout);
#endif

387
iguana/exchanges/LP_nativeDEX.c

@ -20,20 +20,22 @@
// marketmaker
//
// new features:
// better error message in ordermatch
// withdraw
// sign packets
// spv check
// dPoW security
// stats, fix pricearray
// verify portfolio
// bittrex balancing
// detect port conflicts on enable
// stats
// dynamic txid2 allocation
// unduplicated bugs:
// swap cancel should cleanly cancel
// -check for completed one being spent
#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,LP_coinmutex,LP_messagemutex,LP_portfoliomutex,LP_electrummutex;
portable_mutex_t LP_peermutex,LP_UTXOmutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex,LP_forwardmutex,LP_pubkeymutex,LP_networkmutex,LP_psockmutex,LP_coinmutex,LP_messagemutex,LP_portfoliomutex,LP_electrummutex,LP_butxomutex;
int32_t LP_canbind;
struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2];
char *Broadcaststr;
struct LP_peerinfo *LP_peerinfos,*LP_mypeer;
struct LP_forwardinfo *LP_forwardinfos;
struct iguana_info *LP_coins;
@ -41,7 +43,7 @@ struct iguana_info *LP_coins;
char *activecoins[] = { "BTC", "KMD" };
char GLOBAL_DBDIR[] = { "DB" };
char USERPASS[65],USERPASS_WIFSTR[64],LP_myipaddr[64],LP_publicaddr[64],USERHOME[512] = { "/root" };
char LP_myipaddr[64],LP_publicaddr[64],USERHOME[512] = { "/root" };
char LP_gui[16] = { "cli" };
char *default_LPnodes[] = { "5.9.253.195", "5.9.253.196", "5.9.253.197", "5.9.253.198", "5.9.253.199", "5.9.253.200", "5.9.253.201", "5.9.253.202", "5.9.253.203", };//"5.9.253.204" }; //
@ -51,11 +53,22 @@ uint16_t LP_fixed_pairport,LP_publicport;
int32_t LP_mybussock = -1;
int32_t LP_mypubsock = -1;
int32_t LP_mypullsock = -1;
int32_t LP_pendingswaps,LP_showwif,USERPASS_COUNTER,IAMLP = 0;
uint32_t LP_sessionid;
int32_t LP_showwif,IAMLP = 0;
double LP_profitratio = 1.;
bits256 LP_mypub25519,LP_mypriv25519;
uint8_t LP_myrmd160[20];
struct LP_privkey { bits256 privkey; uint8_t rmd160[20]; };
struct LP_globals
{
struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2];
bits256 LP_mypub25519,LP_mypriv25519;
uint64_t LP_skipstatus[10000];
uint8_t LP_myrmd160[20],LP_pubsecp[33];
uint32_t LP_sessionid,counter;
int32_t LP_pendingswaps,USERPASS_COUNTER,LP_numprivkeys,initializing,waiting,LP_numskips;
char USERPASS[65],USERPASS_WIFSTR[64],LP_myrmd160str[41],gui[16];
struct LP_privkey LP_privkeys[100];
} G;
// stubs
@ -84,8 +97,8 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_
#include "LP_bitcoin.c"
#include "LP_coins.c"
#include "LP_rpc.c"
#include "LP_prices.c"
#include "LP_utxo.c"
#include "LP_prices.c"
#include "LP_scan.c"
#include "LP_transaction.c"
#include "LP_remember.c"
@ -111,7 +124,7 @@ char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson
//if ( pubsock >= 0 ) //strncmp("{\"error\":",retstr,strlen("{\"error\":")) != 0 &&
//LP_send(pubsock,retstr,(int32_t)strlen(retstr)+1,0);
}
}
} //else printf("finished tradecommand (%s)\n",jprint(argjson,0));
return(retstr);
}
@ -124,7 +137,7 @@ char *LP_decrypt(uint8_t *ptr,int32_t *recvlenp)
cipherlen = recvlen - (2 + crypto_box_NONCEBYTES);
if ( cipherlen > 0 && cipherlen <= sizeof(decoded) )
{
if ( (jsonstr= (char *)_SuperNET_decipher(nonce,cipher,decoded,cipherlen,GENESIS_PUBKEY,LP_mypriv25519)) != 0 )
if ( (jsonstr= (char *)_SuperNET_decipher(nonce,cipher,decoded,cipherlen,GENESIS_PUBKEY,G.LP_mypriv25519)) != 0 )
{
recvlen = (cipherlen - crypto_box_ZEROBYTES);
if ( strlen(jsonstr)+1 != recvlen )
@ -151,7 +164,7 @@ char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock,
dup++;
else uniq++;
if ( (rand() % 1000) == 0 )
printf("%s dup.%d (%u / %u) %.1f%% encrypted.%d recv.%u [%02x %02x] vs %02x %02x U.%d\n",typestr,duplicate,dup,dup+uniq,(double)100*dup/(dup+uniq),encrypted,crc32,ptr[0],ptr[1],crc32&0xff,(crc32>>8)&0xff,LP_mypeer != 0 ? LP_mypeer->numutxos : -1);
printf("%s dup.%d (%u / %u) %.1f%% encrypted.%d recv.%u [%02x %02x] vs %02x %02x\n",typestr,duplicate,dup,dup+uniq,(double)100*dup/(dup+uniq),encrypted,crc32,ptr[0],ptr[1],crc32&0xff,(crc32>>8)&0xff);
if ( duplicate == 0 )
{
if ( i >= 0 )
@ -217,59 +230,12 @@ char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock,
return(retstr);
}
void LP_utxo_spentcheck(int32_t pubsock,struct LP_utxoinfo *utxo)
{
struct _LP_utxoinfo u; struct iguana_info *coin; char str[65]; uint32_t now = (uint32_t)time(NULL);
if ( IAMLP != 0 && (coin= LP_coinfind(utxo->coin)) != 0 && coin->inactive != 0 )
return;
//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(0,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(0,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)
int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int32_t sock,char *remoteaddr)
{
//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,int32_t interval,int32_t maxentries)
{
int32_t lastn,n = -1;
if ( peer->lastutxos < now-interval )
{
//lastn = peer->numutxos - mypeer->numutxos + LP_PROPAGATION_SLACK;
//if ( lastn < LP_PROPAGATION_SLACK * 2 )
lastn = LP_PROPAGATION_SLACK * 2;
if ( mypeer == 0 || strcmp(peer->ipaddr,mypeer->ipaddr) != 0 )
{
peer->lastutxos = now;
//printf("query utxos from %s\n",peer->ipaddr);
n = LP_utxosquery(mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,maxentries);
}
} //else printf("LP_peer_utxosquery skip.(%s) %u\n",peer->ipaddr,peer->lastutxos);
return(n);
}
int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int32_t sock)
{
int32_t recvlen=1,nonz = 0; void *ptr; char *retstr; struct nn_pollfd pfd;
int32_t recvlen=1,nonz = 0; cJSON *argjson; void *ptr; char *retstr,*str; struct nn_pollfd pfd;
if ( sock >= 0 )
{
while ( nonz < 1000 && recvlen > 0 )
while ( nonz < 100 && recvlen > 0 )
{
memset(&pfd,0,sizeof(pfd));
pfd.fd = sock;
@ -278,9 +244,28 @@ int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int
break;
if ( (recvlen= nn_recv(sock,&ptr,NN_MSG,0)) > 0 )
{
//printf("RECV.(%s)\n",(char *)ptr);
nonz++;
if ( (retstr= LP_process_message(ctx,typestr,myipaddr,pubsock,ptr,recvlen,sock)) != 0 )
free(retstr);
if ( Broadcaststr != 0 )
{
//printf("self broadcast.(%s)\n",Broadcaststr);
str = Broadcaststr;
Broadcaststr = 0;
if ( (argjson= cJSON_Parse(str)) != 0 )
{
if ( jobj(argjson,"method") != 0 && strcmp("connect",jstr(argjson,"method")) == 0 )
printf("self.(%s)\n",str);
if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,0,0) <= 0 )
{
if ( (retstr= stats_JSON(ctx,myipaddr,pubsock,argjson,remoteaddr,0)) != 0 )
free(retstr);
}
free_json(argjson);
}
free(str);
}
}
}
}
@ -289,7 +274,7 @@ int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int
void command_rpcloop(void *myipaddr)
{
int32_t nonz = 0; char *origipaddr; struct LP_peerinfo *peer,*tmp; void *ctx; //struct iguana_info *coin,*ctmp;
int32_t nonz = 0; char *origipaddr; struct LP_peerinfo *peer,*tmp; void *ctx;
ctx = bitcoin_ctx();
if ( (origipaddr= myipaddr) == 0 )
origipaddr = "127.0.0.1";
@ -302,10 +287,14 @@ void command_rpcloop(void *myipaddr)
{
if ( (rand() % 10000) == 0 )
peer->errors--;
else continue;
else
{
//printf("skip %s\n",peer->ipaddr);
continue;
}
}
//printf("check %s pubsock.%d\n",peer->ipaddr,peer->subsock);
nonz += LP_sock_check("PULL",ctx,origipaddr,LP_mypubsock,peer->subsock);
nonz += LP_sock_check("PULL",ctx,origipaddr,LP_mypubsock,peer->subsock,peer->ipaddr);
}
/*HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht
{
@ -315,7 +304,7 @@ void command_rpcloop(void *myipaddr)
nonz += LP_sock_check(coin->symbol,ctx,origipaddr,-1,coin->bussock,LP_profitratio - 1.);
}*/
if ( LP_mypullsock >= 0 )
nonz += LP_sock_check("SUB",ctx,origipaddr,-1,LP_mypullsock);
nonz += LP_sock_check("SUB",ctx,origipaddr,-1,LP_mypullsock,"127.0.0.1");
//if ( LP_mybussock >= 0 )
// nonz += LP_sock_check("BUS",ctx,origipaddr,-1,LP_mybussock);
if ( nonz == 0 )
@ -323,19 +312,118 @@ void command_rpcloop(void *myipaddr)
}
}
int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int32_t pubsock,char *pushaddr,uint16_t myport,char *passphrase)
int32_t LP_utxos_sync(struct LP_peerinfo *peer)
{
static uint32_t counter,numpeers,lastresync; //lastforward
struct LP_utxoinfo *utxo,*utmp; cJSON *retjson; struct iguana_info *coin,*ctmp; char *retstr,*origipaddr; struct LP_peerinfo *peer,*tmp,*mostpeer; uint32_t id,now; int32_t mostutxos,nonz = 0,n=0,num,lastn=-1;
int32_t i,j,n=0,m,v,posted=0; bits256 txid; cJSON *array,*item,*item2,*array2,*array3; uint64_t total,total2,metric; struct iguana_info *coin,*ctmp; struct LP_address *ap; char *retstr,*retstr2,*coinaddr;
HASH_ITER(hh,LP_coins,coin,ctmp)
{
if ( coin->inactive != 0 )//|| (coin->electrum != 0 && coin->obooktime == 0) )
continue;
total = 0;
LP_listunspent_both(coin->symbol,coin->smartaddr);
if ( (array= LP_address_utxos(coin,coin->smartaddr,1)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
total += j64bits(item,"value");
}
}
if ( n > 0 && total > 0 && (retstr= issue_LP_listunspent(peer->ipaddr,peer->port,coin->symbol,coin->smartaddr)) != 0 )
{
total2 = 0;
if ( (array2= cJSON_Parse(retstr)) != 0 )
{
if ( (m= cJSON_GetArraySize(array2)) > 0 )
{
for (i=0; i<m; i++)
{
item2 = jitem(array2,i);
total2 += j64bits(item2,"value");
}
}
if ( total != total2 || n != m )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
txid = jbits256(item,"tx_hash");
v = jint(item,"tx_pos");
for (j=0; j<m; j++)
{
if ( v == jint(jitem(array2,i),"tx_pos") && bits256_cmp(txid,jbits256(jitem(array2,i),"tx_hash")) == 0 )
break;
}
if ( j == m )
{
//printf("%s missing %s\n",peer->ipaddr,jprint(item,0));
if ( (retstr2= issue_LP_uitem(peer->ipaddr,peer->port,coin->symbol,coin->smartaddr,txid,v,jint(item,"height"),j64bits(item,"value"))) != 0 )
free(retstr2);
posted++;
}
}
if ( 0 && posted != 0 )
printf(">>>>>>>> %s compare %s %s (%.8f n%d) (%.8f m%d)\n",peer->ipaddr,coin->symbol,coin->smartaddr,dstr(total),n,dstr(total2),m);
} //else printf("%s matches\n",peer->ipaddr);
free_json(array2);
}
free(retstr);
}
}
if ( (retstr= issue_LP_listunspent(peer->ipaddr,peer->port,coin->symbol,"")) != 0 )
{
if ( (array2= cJSON_Parse(retstr)) != 0 )
{
if ( (m= cJSON_GetArraySize(array2)) > 0 )
{
for (j=0; j<m; j++)
{
item = jitem(array2,j);
if ( (coinaddr= jfieldname(item)) != 0 )
{
metric = j64bits(item,"coinaddr");
//printf("(%s) -> %.8f n.%d\n",coinaddr,dstr(metric>>16),(uint16_t)metric);
if ( (ap= LP_addressfind(coin,coinaddr)) == 0 || _LP_unspents_metric(ap->total,ap->n) != metric )
{
if ( ap == 0 || ap->n < (metric & 0xffff) )
{
if ( (retstr2= issue_LP_listunspent(peer->ipaddr,peer->port,coin->symbol,coinaddr)) != 0 )
{
if ( (array3= cJSON_Parse(retstr2)) != 0 )
{
LP_unspents_array(coin,coinaddr,array3);
//printf("pulled.(%s)\n",retstr2);
free_json(array3);
}
free(retstr2);
}
} //else printf("wait for %s to pull %d vs %d\n",peer->ipaddr,ap!=0?ap->n:-1,(uint16_t)metric);
}
}
}
}
free_json(array2);
}
//printf("processed.(%s)\n",retstr);
free(retstr);
}
}
return(posted);
}
int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int32_t pubsock,char *pushaddr,uint16_t myport)
{
static uint32_t counter,numpeers;
struct iguana_info *coin,*ctmp; char *retstr,*origipaddr; struct LP_peerinfo *peer,*tmp; uint32_t now; bits256 zero; int32_t needpings,height,nonz = 0;
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();
mostutxos = 0;
mostpeer = 0;
needpings = 0;
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
if ( peer->errors >= LP_MAXPEER_ERRORS )
@ -343,108 +431,53 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
if ( (rand() % 10000) == 0 )
{
peer->errors--;
peer->diduquery = 0;
if ( peer->errors < LP_MAXPEER_ERRORS )
peer->diduquery = 0;
}
if ( IAMLP == 0 )
continue;
}
if ( now > peer->lastpeers+60 && peer->numpeers > 0 && (peer->numpeers != numpeers || (rand() % 10000) == 0) )
if ( now > peer->lastpeers+60 && peer->numpeers > 0 && (peer->numpeers != numpeers || (rand() % 1000) == 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);
if ( IAMLP != 0 && LP_mypeer != 0 && strcmp(peer->ipaddr,myipaddr) != 0 )
{
if ( (retstr= issue_LP_numutxos(peer->ipaddr,peer->port,LP_mypeer->ipaddr,LP_mypeer->port,LP_mypeer->numpeers,LP_mypeer->numutxos)) != 0 )
{
//printf("%d <- (%s)\n",peer->numutxos,retstr);
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (num= jint(retjson,"numutxos")) > peer->numutxos )
peer->numutxos = num;
if ( (num= jint(retjson,"numpeers")) > peer->numpeers )
peer->numpeers = num;
if ( (id= juint(retjson,"session")) != 0 )
peer->sessionid = id;
free_json(retjson);
}
free(retstr);
retstr = 0;
}
LP_peersquery(mypeer,pubsock,peer->ipaddr,peer->port,myipaddr,myport);
peer->diduquery = 0;
LP_utxos_sync(peer);
}
}
if ( peer->diduquery == 0 )
{
if ( lastn != n || n < 20 )
{
lastn = n;
n = LP_peer_utxosquery(mypeer,myport,pubsock,peer,now,60,100);
}
LP_peer_pricesquery(peer->ipaddr,peer->port);
LP_peer_pricesquery(peer);
peer->diduquery = now;
}
if ( peer->numutxos > mostutxos )
if ( peer->needping != 0 )
{
mostutxos = peer->numutxos;
mostpeer = peer;
needpings++;
if ( (retstr= issue_LP_notify(peer->ipaddr,peer->port,"127.0.0.1",0,numpeers,G.LP_sessionid,G.LP_myrmd160str,G.LP_mypub25519)) != 0 )
free(retstr);
peer->needping = 0;
}
}
//printf("numutxos vs mine.%d\n",LP_mypeer != 0 ? LP_mypeer->numutxos : -1);
if ( LP_mypeer != 0 && mostpeer != 0 && ((LP_mypeer->numutxos < mostutxos && time(NULL) > lastresync+10) || time(NULL) > lastresync+60) )
if ( needpings != 0 || (counter % 6000) == 5 )
{
//printf("myutxos.%d most.%d %s\n",LP_mypeer->numutxos,mostutxos,mostpeer->ipaddr);
LP_peer_utxosquery(LP_mypeer,myport,pubsock,mostpeer,now,60,(mostutxos-LP_mypeer->numutxos) * 2);
lastresync = (uint32_t)time(NULL);
//LP_peer_pricesquery(mostpeer->ipaddr,mostpeer->port);
//printf("needpings.%d send notify\n",needpings);
LP_notify_pubkeys(ctx,pubsock);
}
if ( (counter % 6000) == 10 )
{
LP_myutxo_updates(ctx,pubsock,passphrase);
HASH_ITER(hh,LP_utxoinfos[0],utxo,utmp)
{
LP_utxo_spentcheck(pubsock,utxo);
}
HASH_ITER(hh,LP_utxoinfos[1],utxo,utmp)
{
LP_utxo_spentcheck(pubsock,utxo);
if ( LP_isunspent(utxo) > 0 && utxo->T.lasttime == 0 && LP_ismine(utxo) > 0 )
{
char str[65]; printf("publish mybob %s\n",bits256_str(str,utxo->payment.txid));
LP_utxo_clientpublish(utxo);
}
}
LP_privkey_updates(ctx,pubsock,0);
}
HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht
{
int32_t height; bits256 zero; //struct LP_address *ap,*atmp; struct LP_address_utxo *up;
//printf("%s ref.%d scan.%d to %d, longest.%d\n",coin->symbol,coin->firstrefht,coin->firstscanht,coin->lastscanht,coin->longestchain);
if ( coin->inactive != 0 || coin->electrum != 0 )
memset(&zero,0,sizeof(zero));
if ( coin->inactive != 0 )
continue;
/*if ( time(NULL) > coin->lastmonitor+60 )
{
portable_mutex_lock(&coin->txmutex);
HASH_ITER(hh,coin->addresses,ap,atmp)
{
if ( ap->monitor != 0 )
{
DL_FOREACH(ap->utxos,up)
{
if ( up->spentflag == 0 )
{
if ( LP_txvalue(0,coin->symbol,up->U.txid,up->U.vout) == 0 )
up->spentflag = (uint32_t)time(NULL);
}
}
}
}
portable_mutex_unlock(&coin->txmutex);
coin->lastmonitor = (uint32_t)time(NULL);
}*/
memset(zero.bytes,0,sizeof(zero));
if ( coin->electrum != 0 )
continue;
//if ( coin->obooktime == 0 )
// continue;
if ( time(NULL) > coin->lastgetinfo+LP_GETINFO_INCR )
{
if ( (height= LP_getheight(coin)) > coin->longestchain )
@ -453,16 +486,6 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
if ( coin->firstrefht != 0 )
printf(">>>>>>>>>> set %s longestchain %d (ref.%d [%d, %d])\n",coin->symbol,height,coin->firstrefht,coin->firstscanht,coin->lastscanht);
} else LP_mempoolscan(coin->symbol,zero);
/*if ( (obj= LP_getinfo(coin->symbol)) != 0 )
{
if ( (height= jint(obj,"blocks")) > coin->longestchain )
{
coin->longestchain = height;
if ( coin->firstrefht != 0 )
printf(">>>>>>>>>> set %s longestchain %d (ref.%d [%d, %d])\n",coin->symbol,height,coin->firstrefht,coin->firstscanht,coin->lastscanht);
} else LP_mempoolscan(coin->symbol,zero);
free_json(obj);
} else printf("error getting info.%s\n",coin->symbol);*/
coin->lastgetinfo = (uint32_t)time(NULL);
}
if ( coin->firstrefht == 0 )
@ -493,6 +516,7 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
continue;
}
coin->lastscanht++;
//LP_getestimatedrate(coin);
break;
}
if ( (counter % 6000) == 60 )
@ -507,7 +531,7 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
return(nonz);
}
void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins,char *passphrase)
void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins)
{
int32_t i,n; cJSON *item;
for (i=0; i<sizeof(activecoins)/sizeof(*activecoins); i++)
@ -527,7 +551,6 @@ void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins,char *passphrase)
}
}
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)
@ -535,7 +558,7 @@ void LP_initpeers(int32_t pubsock,struct LP_peerinfo *mypeer,char *myipaddr,uint
int32_t i,j; uint32_t r;
if ( IAMLP != 0 )
{
LP_mypeer = mypeer = LP_addpeer(mypeer,pubsock,myipaddr,myport,0,0,0,0,LP_sessionid);
LP_mypeer = mypeer = LP_addpeer(mypeer,pubsock,myipaddr,myport,0,0,0,0,G.LP_sessionid);
if ( myipaddr == 0 || mypeer == 0 )
{
printf("couldnt get myipaddr or null mypeer.%p\n",mypeer);
@ -629,11 +652,10 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
portable_mutex_init(&LP_electrummutex);
portable_mutex_init(&LP_messagemutex);
portable_mutex_init(&LP_portfoliomutex);
LP_sessionid = (uint32_t)time(NULL);
printf("getting myipaddr sessionid.%u\n",LP_sessionid);
if ( system("curl -s4 checkip.amazonaws.com > /tmp/myipaddr") == 0 )
portable_mutex_init(&LP_butxomutex);
if ( system("curl -s4 checkip.amazonaws.com > DB/myipaddr") == 0 )
{
if ( (myipaddr= OS_filestr(&filesize,"/tmp/myipaddr")) != 0 && myipaddr[0] != 0 )
if ( (myipaddr= OS_filestr(&filesize,"DB/myipaddr")) != 0 && myipaddr[0] != 0 )
{
n = strlen(myipaddr);
if ( myipaddr[n-1] == '\n' )
@ -650,7 +672,7 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
{
if ( nn_bind(pubsock,bindaddr) >= 0 )
{
timeout = 10;
timeout = 1;
nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
}
else
@ -673,7 +695,9 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
//LP_deadman_switch = (uint32_t)time(NULL);
printf("canbind.%d my command address is (%s) pullsock.%d pullport.%u\n",LP_canbind,pushaddr,LP_mypullsock,mypullport);
printf("initcoins\n");
LP_initcoins(ctx,pubsock,jobj(argjson,"coins"),passphrase);
LP_initcoins(ctx,pubsock,jobj(argjson,"coins"));
G.waiting = 1;
LP_passphrase_init(passphrase,jstr(argjson,"gui"));
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);
@ -701,11 +725,22 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
}
//if ( (retstr= basilisk_swapentry(0,0)) != 0 )
// free(retstr);
int32_t nonz;
printf("start mainloop\n");
while ( 1 )
{
//fprintf(stderr,".");
if ( LP_mainloop_iter(ctx,myipaddr,mypeer,pubsock,pushaddr,myport,passphrase) == 0 )
usleep(1000000 / MAINLOOP_PERSEC);
nonz = 0;
G.waiting = 1;
while ( G.initializing != 0 )
{
fprintf(stderr,".");
sleep(3);
}
if ( LP_mainloop_iter(ctx,myipaddr,mypeer,pubsock,pushaddr,myport) != 0 )
nonz++;
if ( nonz == 0 )
usleep(50000);
else usleep(5000);
}
}

19
iguana/exchanges/LP_network.c

@ -46,7 +46,7 @@ int32_t _LP_send(int32_t sock,void *msg,int32_t sendlen,int32_t freeflag)
}
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);
else printf("SENT.(%s)\n",(char *)msg);
if ( freeflag != 0 )
free(msg);
return(sentbytes);
@ -157,12 +157,12 @@ void queue_loop(void *ignore)
{
if ( (sentbytes= nn_send(ptr->sock,ptr->msg,ptr->msglen,0)) != ptr->msglen )
printf("%d LP_send sent %d instead of %d\n",n,sentbytes,ptr->msglen);
// else printf("%d %p qsent %u msglen.%d peerind.%d\n",n,ptr,ptr->crc32,ptr->msglen,ptr->peerind);
//else printf("%d %p qsent %u msglen.%d peerind.%d (%s)\n",n,ptr,ptr->crc32,ptr->msglen,ptr->peerind,ptr->msg);
ptr->sock = -1;
if ( ptr->peerind > 0 )
ptr->starttime = (uint32_t)time(NULL);
else flag = 1;
}
} //else printf("sock not ready to send.%d\n",ptr->msglen);
}
else if ( time(NULL) > ptr->starttime+13 )
{
@ -199,7 +199,7 @@ void queue_loop(void *ignore)
//if ( n != 0 )
// printf("LP_Q.[%d]\n",n);
if ( nonz == 0 )
usleep(500000);
usleep(50000);
}
}
@ -214,7 +214,7 @@ void _LP_queuesend(uint32_t crc32,int32_t sock0,int32_t sock1,uint8_t *msg,int32
printf("_LP_queuesend0 sent %d instead of %d\n",sentbytes,msglen);
else
{
//printf("Q sent %u\n",crc32);
//printf("Q sent %u msglen.%d (%s)\n",crc32,msglen,msg);
sock0 = -1;
}
}
@ -232,17 +232,16 @@ void _LP_queuesend(uint32_t crc32,int32_t sock0,int32_t sock1,uint8_t *msg,int32
peerind = 1;
sock0 = LP_peerindsock(&peerind);
}
portable_mutex_lock(&LP_networkmutex);
if ( sock0 >= 0 )
_LP_sendqueueadd(crc32,sock0,msg,msglen,needack * peerind);
if ( sock1 >= 0 )
_LP_sendqueueadd(crc32,sock1,msg,msglen,needack);
portable_mutex_unlock(&LP_networkmutex);
}
void LP_queuesend(uint32_t crc32,int32_t pubsock,char *base,char *rel,uint8_t *msg,int32_t msglen)
{
//struct iguana_info *coin; int32_t flag=0,socks[2];
portable_mutex_lock(&LP_networkmutex);
if ( pubsock >= 0 )
{
//socks[0] = socks[1] = -1;
@ -254,6 +253,7 @@ void LP_queuesend(uint32_t crc32,int32_t pubsock,char *base,char *rel,uint8_t *m
_LP_queuesend(crc32,pubsock,-1,msg,msglen,0);
//else _LP_queuesend(socks[0],socks[1],msg,msglen,0);
} else _LP_queuesend(crc32,-1,-1,msg,msglen,1);
portable_mutex_unlock(&LP_networkmutex);
}
// first 2 bytes == (crc32 & 0xffff) if encrypted, then nonce is next crypto_box_NONCEBYTES
@ -311,8 +311,11 @@ void LP_broadcast_message(int32_t pubsock,char *base,char *rel,bits256 destpub25
jdelete(argjson,"method2");
jaddstr(argjson,"method2",method);
jaddstr(argjson,"method",method);
//printf("CRC32.%u (%s)\n",crc32,(char *)msg);
//if ( strncmp(method,"connect",7) == 0 || strcmp(method,"reserved") == 0 )
// printf("CRC32.%u (%s)\n",crc32,msgstr);
LP_broadcast_finish(pubsock,base,rel,msg,argjson,0);
//if ( strncmp(method,"connect",7) == 0 || strcmp(method,"reserved") == 0 )
// printf("finished %u\n",crc32);
} // else printf("no valid method in (%s)\n",msgstr);
free_json(argjson);
} else printf("couldnt parse (%s)\n",msgstr);

721
iguana/exchanges/LP_ordermatch.c

@ -25,10 +25,15 @@ uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee)
{
if ( strcmp(coin->symbol,"BTC") == 0 )
{
if ( txfee == 0 && (txfee= LP_getestimatedrate(coin) * LP_AVETXSIZE) < LP_MIN_TXFEE )
txfee = LP_MIN_TXFEE;
}
else txfee = coin->txfee;
coin->rate = LP_getestimatedrate(coin);
if ( (txfee= SATOSHIDEN * coin->rate * LP_AVETXSIZE) <= LP_MIN_TXFEE )
{
coin->rate = -1.;
coin->rate = _LP_getestimatedrate(coin);
if ( (txfee= SATOSHIDEN * coin->rate * LP_AVETXSIZE) <= LP_MIN_TXFEE )
txfee = LP_MIN_TXFEE;
}
} else txfee = coin->txfee;
if ( txfee < LP_MIN_TXFEE )
txfee = LP_MIN_TXFEE;
}
@ -39,6 +44,7 @@ void LP_txfees(uint64_t *txfeep,uint64_t *desttxfeep,char *base,char *rel)
{
*txfeep = LP_txfeecalc(LP_coinfind(base),0);
*desttxfeep = LP_txfeecalc(LP_coinfind(rel),0);
printf("LP_txfees(%.8f %.8f)\n",dstr(*txfeep),dstr(*desttxfeep));
}
double LP_qprice_calc(int64_t *destsatoshisp,int64_t *satoshisp,double price,uint64_t b_satoshis,uint64_t txfee,uint64_t a_value,uint64_t maxdestsatoshis,uint64_t desttxfee)
@ -126,7 +132,7 @@ cJSON *LP_quotejson(struct LP_quoteinfo *qp)
jadd64bits(retjson,"destsatoshis",qp->destsatoshis);
if ( qp->satoshis != 0 )
{
price = (double)qp->destsatoshis / qp->satoshis;
price = (double)qp->destsatoshis / (qp->satoshis - qp->txfee);
jaddnum(retjson,"price",price);
}
}
@ -167,11 +173,11 @@ int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char *
LP_txfees(&qp->txfee,&qp->desttxfee,utxo->coin,qp->destcoin);
qp->satoshis = satoshis;//(destsatoshis / price) + 0.49;
qp->destsatoshis = destsatoshis;
if ( utxo->iambob == 0 || qp->txfee >= qp->satoshis || qp->txfee >= utxo->deposit.value || utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis) )
/*if ( qp->txfee >= qp->satoshis || qp->txfee >= utxo->deposit.value || utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis) ) //utxo->iambob == 0 ||
{
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;
@ -202,7 +208,7 @@ char *LP_quotereceived(cJSON *argjson)
{
struct LP_cacheinfo *ptr; double price; struct LP_quoteinfo Q;
LP_quoteparse(&Q,argjson);
price = (double)Q.destsatoshis / Q.satoshis;
price = (double)Q.destsatoshis / (Q.satoshis - Q.txfee);
if ( (ptr= LP_cacheadd(Q.srccoin,Q.destcoin,Q.txid,Q.vout,price,&Q)) != 0 )
{
ptr->Q = Q;
@ -215,7 +221,7 @@ char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *re
{
bits256 zero; char *msg; cJSON *reqjson = cJSON_CreateObject();
memset(zero.bytes,0,sizeof(zero));
jaddbits256(reqjson,"pubkey",LP_mypub25519);
jaddbits256(reqjson,"pubkey",G.LP_mypub25519);
jaddstr(reqjson,"base",base);
jaddstr(reqjson,"rel",rel);
jaddnum(reqjson,"price",price);
@ -225,6 +231,19 @@ char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *re
return(clonestr("{\"result\":\"success\"}"));
}
void LP_notify_pubkeys(void *ctx,int32_t pubsock)
{
bits256 zero; char *msg,secpstr[67]; cJSON *reqjson = cJSON_CreateObject();
memset(zero.bytes,0,sizeof(zero));
jaddstr(reqjson,"method","notify");
jaddstr(reqjson,"rmd160",G.LP_myrmd160str);
jaddbits256(reqjson,"pub",G.LP_mypub25519);
init_hexbytes_noT(secpstr,G.LP_pubsecp,33);
jaddstr(reqjson,"pubsecp",secpstr);
msg = jprint(reqjson,1);
LP_broadcast_message(pubsock,"","",zero,msg);
}
char *LP_postedprice(cJSON *argjson)
{
bits256 pubkey; double price; char *base,*rel;
@ -241,15 +260,15 @@ char *LP_postedprice(cJSON *argjson)
return(clonestr("{\"error\":\"missing fields in posted price\"}"));
}
int32_t LP_quote_checkmempool(struct LP_quoteinfo *qp)
int32_t LP_quote_checkmempool(struct LP_quoteinfo *qp,struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo)
{
int32_t selector,spendvini; bits256 spendtxid;
if ( (selector= LP_mempool_vinscan(&spendtxid,&spendvini,qp->srccoin,qp->coinaddr,qp->txid,qp->vout,qp->txid2,qp->vout2)) >= 0 )
if ( butxo != 0 && (selector= LP_mempool_vinscan(&spendtxid,&spendvini,qp->srccoin,qp->coinaddr,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->destaddr,qp->desttxid,qp->destvout,qp->feetxid,qp->feevout)) >= 0 )
if ( autxo != 0 && (selector= LP_mempool_vinscan(&spendtxid,&spendvini,qp->destcoin,qp->destaddr,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);
@ -257,57 +276,83 @@ int32_t LP_quote_checkmempool(struct LP_quoteinfo *qp)
return(0);
}
double LP_quote_validate(struct LP_utxoinfo **autxop,struct LP_utxoinfo **butxop,struct LP_quoteinfo *qp,int32_t iambob)
double LP_quote_validate(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,struct LP_quoteinfo *qp,int32_t iambob)
{
double qprice; uint64_t txfee,desttxfee,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) == 0 )
double qprice=0.; uint64_t txfee,desttxfee,srcvalue=0,srcvalue2=0,destvalue=0,destvalue2=0;
printf("quote %s %.8f -> %s %.8f\n",qp->srccoin,dstr(qp->satoshis),qp->destcoin,dstr(qp->destsatoshis));
if ( butxo != 0 )
{
printf("bob not eligible\n");
return(-2);
if (LP_iseligible(&srcvalue,&srcvalue2,1,qp->srccoin,qp->txid,qp->vout,qp->satoshis,qp->txid2,qp->vout2) == 0 )
{
printf("bob not eligible %s\n",jprint(LP_quotejson(qp),1));
return(-2);
}
if ( bits256_cmp(butxo->deposit.txid,qp->txid2) != 0 || butxo->deposit.vout != qp->vout2 )
{
char str[65],str2[65]; printf("%s != %s v%d != %d\n",bits256_str(str,butxo->deposit.txid),bits256_str(str2,qp->txid2),butxo->deposit.vout,qp->vout2);
return(-6);
}
if ( strcmp(butxo->coinaddr,qp->coinaddr) != 0 )
{
printf("(%s) != (%s)\n",butxo->coinaddr,qp->coinaddr);
return(-7);
}
}
if ( LP_iseligible(&destvalue,&destvalue2,0,qp->destcoin,qp->desttxid,qp->destvout,qp->destsatoshis,qp->feetxid,qp->feevout) == 0 )
if ( autxo != 0 && LP_iseligible(&destvalue,&destvalue2,0,qp->destcoin,qp->desttxid,qp->destvout,qp->destsatoshis,qp->feetxid,qp->feevout) == 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 )
if ( LP_quote_checkmempool(qp,autxo,butxo) < 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 )
//if ( iambob != 0 && (*butxop= LP_utxofind(1,qp->txid,qp->vout)) == 0 )
// return(-5);
if ( iambob == 0 && autxo != 0 )
{
//if ( (*autxop= LP_utxofind(0,qp->desttxid,qp->destvout)) == 0 )
// return(-8);
if ( bits256_cmp(autxo->fee.txid,qp->feetxid) != 0 || autxo->fee.vout != qp->feevout )
return(-9);
if ( strcmp((*autxop)->coinaddr,qp->destaddr) != 0 )
if ( strcmp(autxo->coinaddr,qp->destaddr) != 0 )
return(-10);
}
if ( destvalue < qp->desttxfee+qp->destsatoshis || srcvalue < qp->txfee+qp->satoshis )
if ( autxo != 0 && destvalue < qp->desttxfee+qp->destsatoshis )
{
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));
printf("destvalue %.8f destsatoshis %.8f is too small txfee %.8f?\n",dstr(destvalue),dstr(qp->destsatoshis),dstr(qp->desttxfee));
return(-11);
}
qprice = ((double)qp->destsatoshis / qp->satoshis);
if ( qp->satoshis < (srcvalue / LP_MINVOL) || srcvalue < qp->txfee*LP_MINSIZE_TXFEEMULT )
if ( butxo != 0 && srcvalue < qp->txfee+qp->satoshis )
{
printf("utxo payment %.8f is less than %f covered by Q %.8f or <10x txfee %.8f\n",dstr(srcvalue),1./LP_MINVOL,dstr(qp->satoshis),dstr(qp->txfee));
return(-12);
}
if ( qp->destsatoshis < (destvalue / LP_MINCLIENTVOL) || destvalue < qp->desttxfee*LP_MINSIZE_TXFEEMULT )
{
printf("destsatoshis %.8f is less than %f of value %.8f or < 10x txfee %.8f\n",dstr(qp->destsatoshis),1./LP_MINCLIENTVOL,dstr(destvalue),dstr(qp->desttxfee));
return(-13);
printf("srcvalue %.8f [%.8f] satoshis %.8f is too small txfee %.8f?\n",dstr(srcvalue),dstr(srcvalue) - dstr(qp->txfee+qp->satoshis),dstr(qp->satoshis),dstr(qp->txfee));
return(-33);
}
if ( qp->satoshis != 0 )
qprice = ((double)qp->destsatoshis / (qp->satoshis-qp->txfee));
LP_txfees(&txfee,&desttxfee,qp->srccoin,qp->destcoin);
if ( txfee < qp->txfee )
txfee = qp->txfee;
if ( desttxfee < qp->desttxfee )
desttxfee = qp->desttxfee;
printf("qprice %.8f <- %.8f/%.8f txfees.(%.8f %.8f) vs (%.8f %.8f)\n",qprice,dstr(qp->destsatoshis),dstr(qp->satoshis),dstr(qp->txfee),dstr(qp->desttxfee),dstr(txfee),dstr(desttxfee));
if ( qp->txfee < LP_REQUIRED_TXFEE*txfee || qp->desttxfee < LP_REQUIRED_TXFEE*desttxfee )
return(-14);
if ( butxo != 0 )
{
//qprice 2259.01692494 <- 10.34279604/0.00457845 txfees.(0.00042631 0.00010000) vs (0.00042791 0.00010000)
if ( qp->satoshis < (srcvalue / LP_MINVOL) || srcvalue < qp->txfee*LP_MINSIZE_TXFEEMULT )
{
printf("utxo payment %.8f is less than %f covered by Q %.8f or <10x txfee %.8f\n",dstr(srcvalue),1./LP_MINVOL,dstr(qp->satoshis),dstr(qp->txfee));
return(-12);
}
}
if ( autxo != 0 )
{
if ( qp->destsatoshis < (destvalue / LP_MINCLIENTVOL) || destvalue < qp->desttxfee*LP_MINSIZE_TXFEEMULT )
{
printf("destsatoshis %.8f is less than %f of value %.8f or < 10x txfee %.8f\n",dstr(qp->destsatoshis),1./LP_MINCLIENTVOL,dstr(destvalue),dstr(qp->desttxfee));
return(-13);
}
}
return(qprice);
}
@ -325,7 +370,7 @@ int32_t LP_arrayfind(cJSON *array,bits256 txid,int32_t vout)
double LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct LP_quoteinfo *qp)
{
cJSON *reqjson; char *msg; int32_t i,flag = 0; double price = 0.; struct LP_utxoinfo *utxo;
cJSON *reqjson; bits256 zero; 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 )
@ -343,7 +388,12 @@ double LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct L
jaddstr(reqjson,"method",method);
msg = jprint(reqjson,1);
printf("QUERY.(%s)\n",msg);
LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,qp->srchash,msg);
memset(&zero,0,sizeof(zero));
if ( 1 && strcmp(method,"request") == 0 )
{
sleep(3);
LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,zero,msg);
} else LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,qp->srchash,msg);
for (i=0; i<30; i++)
{
if ( (price= LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout)) > SMALLVAL )
@ -354,7 +404,7 @@ double LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct L
break;
}
}
usleep(100000);
usleep(250000);
}
return(price);
}
@ -391,6 +441,107 @@ int32_t LP_nanobind(void *ctx,char *pairstr)
return(pairsock);
}
int32_t LP_nearest_utxovalue(struct LP_address_utxo **utxos,int32_t n,uint64_t targetval)
{
int32_t i,mini = -1; int64_t dist; uint64_t mindist = (1LL << 60);
for (i=0; i<n; i++)
{
if ( utxos[i] != 0 )
{
dist = (utxos[i]->U.value - targetval);
if ( dist >= 0 && dist < mindist )
{
printf("(%.8f %.8f %.8f).%d ",dstr(utxos[i]->U.value),dstr(dist),dstr(mindist),mini);
mini = i;
mindist = dist;
}
}
}
return(mini);
}
uint64_t LP_basesatoshis(double relvolume,double price,uint64_t txfee,uint64_t desttxfee)
{
printf("basesatoshis %.8f (rel %.8f / price %.8f)\n",dstr(SATOSHIDEN * ((relvolume) / price) + 2*txfee),relvolume,price);
if ( relvolume > dstr(desttxfee) && price > SMALLVAL )
return(SATOSHIDEN * (relvolume / price) + 2*txfee);
else return(0);
}
struct LP_utxoinfo *LP_address_utxopair(int32_t iambob,struct LP_address_utxo **utxos,int32_t max,struct iguana_info *coin,char *coinaddr,uint64_t txfee,double relvolume,double price,uint64_t desttxfee)
{
struct LP_address *ap; uint64_t targetval,targetval2; int32_t m,mini; struct LP_address_utxo *up,*up2; struct LP_utxoinfo *utxo = 0;
if ( coin != 0 && (ap= LP_addressfind(coin,coinaddr)) != 0 )
{
if ( (m= LP_address_utxo_ptrs(iambob,utxos,max,ap)) > 1 )
{
targetval = LP_basesatoshis(relvolume,price,txfee,desttxfee);
if ( 1 )
{
int32_t i;
for (i=0; i<m; i++)
printf("%.8f ",dstr(utxos[i]->U.value));
printf("targetval %.8f vol %.8f price %.8f txfee %.8f %s\n",dstr(targetval),relvolume,price,dstr(txfee),coinaddr);
}
mini = -1;
if ( targetval != 0 && (mini= LP_nearest_utxovalue(utxos,m,targetval)) >= 0 && (double)utxos[mini]->U.value/targetval < LP_MINVOL-1 )
{
up = utxos[mini];
utxos[mini] = 0;
targetval2 = (up->U.value / 8) * 9 + 2*txfee;
if ( (mini= LP_nearest_utxovalue(utxos,m,targetval2)) >= 0 )
{
if ( up != 0 && (up2= utxos[mini]) != 0 )
{
if ( (utxo= LP_utxoadd(1,coin->symbol,up->U.txid,up->U.vout,up->U.value,up2->U.txid,up2->U.vout,up2->U.value,coinaddr,ap->pubkey,G.gui,0)) != 0 )
{
utxo->S.satoshis = targetval;
char str[65],str2[65]; printf("butxo.%p targetval %.8f, found val %.8f %s | targetval2 %.8f val2 %.8f %s\n",utxo,dstr(targetval),dstr(up->U.value),bits256_str(str,utxo->payment.txid),dstr(targetval2),dstr(up2->U.value),bits256_str(str2,utxo->deposit.txid));
return(utxo);
}
}
} else printf("cant find targetval2 %.8f\n",dstr(targetval2));
} else if ( targetval != 0 && mini >= 0 )
printf("targetval %.8f mini.%d ratio %.8f\n",dstr(targetval),mini,(double)utxos[mini]->U.value/targetval);
} else printf("no utxos pass LP_address_utxo_ptrs filter\n");
} else printf("couldnt find %s %s\n",coin->symbol,coinaddr);
return(0);
}
void LP_abutxo_set(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,struct LP_quoteinfo *qp)
{
if ( butxo != 0 )
{
memset(butxo,0,sizeof(*butxo));
butxo->pubkey = qp->srchash;
safecopy(butxo->coin,qp->srccoin,sizeof(butxo->coin));
safecopy(butxo->coinaddr,qp->coinaddr,sizeof(butxo->coinaddr));
butxo->payment.txid = qp->txid;
butxo->payment.vout = qp->vout;
//butxo->payment.value = qp->value;
butxo->iambob = 1;
butxo->deposit.txid = qp->txid2;
butxo->deposit.vout = qp->vout2;
//butxo->deposit.value = up2->U.value;
butxo->S.satoshis = qp->satoshis;
}
if ( autxo != 0 )
{
memset(autxo,0,sizeof(*autxo));
autxo->pubkey = qp->desthash;
safecopy(autxo->coin,qp->destcoin,sizeof(autxo->coin));
safecopy(autxo->coinaddr,qp->destaddr,sizeof(autxo->coinaddr));
autxo->payment.txid = qp->desttxid;
autxo->payment.vout = qp->destvout;
//autxo->payment.value = qp->value;
autxo->iambob = 0;
autxo->fee.txid = qp->feetxid;
autxo->fee.vout = qp->feevout;
//autxo->deposit.value = up2->U.value;
autxo->S.satoshis = qp->destsatoshis;
}
}
int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJSON *argjson,char *base,char *rel,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;
@ -402,12 +553,14 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ
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_mypub25519,qp->srchash) == 0 )
if ( bits256_nonz(privkey) != 0 && bits256_cmp(G.LP_mypub25519,qp->srchash) == 0 ) //qp->quotetime >= qp->timestamp-3 && qp->quotetime <= utxo->T.swappending &&
{
if ( (pair= LP_nanobind(ctx,pairstr)) >= 0 )
{
LP_requestinit(&qp->R,qp->srchash,qp->desthash,base,qp->satoshis-qp->txfee,rel,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector);
printf("call swapinit\n");
swap = LP_swapinit(1,0,privkey,&qp->R,qp);
printf("swapinit.%p\n",swap);
swap->N.pair = pair;
utxo->S.swap = swap;
swap->utxo = utxo;
@ -427,7 +580,7 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ
}
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_mypub25519,qp->srchash) == 0);
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(G.LP_mypub25519,qp->srchash) == 0);
}
if ( retval < 0 )
{
@ -435,21 +588,57 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ
nn_close(pair);
LP_availableset(utxo);
} else LP_unavailableset(utxo,utxo->S.otherpubkey);
//LP_butxo_swapfields(utxo);
return(retval);
}
char *LP_connectedalice(cJSON *argjson) // alice
{
cJSON *retjson; double bid,ask,price,qprice; int32_t 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;
cJSON *retjson; double bid,ask,price,qprice; int32_t pairsock = -1; char *pairstr; int32_t DEXselector = 0; struct LP_utxoinfo *autxo,B,*butxo; struct LP_quoteinfo Q; struct basilisk_swap *swap; struct iguana_info *coin; //uint64_t value,value2;
if ( LP_quoteparse(&Q,argjson) < 0 )
clonestr("{\"error\":\"cant parse quote\"}");
if ( bits256_cmp(Q.desthash,LP_mypub25519) != 0 )
if ( bits256_cmp(Q.desthash,G.LP_mypub25519) != 0 )
return(clonestr("{\"result\",\"update stats\"}"));
printf("CONNECTED.(%s)\n",jprint(argjson,0));
if ( (qprice= LP_quote_validate(&autxo,&butxo,&Q,0)) <= SMALLVAL )
printf("CONNECTED.(%s) numpending.%d\n",jprint(argjson,0),G.LP_pendingswaps);
/*if ( G.LP_pendingswaps > 0 )
{
printf("swap already pending\n");
return(clonestr("{\"error\":\"swap already pending\"}"));
}*/
if ( (autxo= LP_utxopairfind(0,Q.desttxid,Q.destvout,Q.feetxid,Q.feevout)) == 0 )
{
printf("cant find autxo\n");
return(clonestr("{\"error\":\"cant find autxo\"}"));
}
if ( autxo->S.swap != 0 )
return(clonestr("{\"error\":\"ignore duplicate swap\"}"));
butxo = &B;
memset(butxo,0,sizeof(*butxo));
LP_abutxo_set(0,butxo,&Q);
/*if ( (butxo= LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2)) == 0 )
{
value = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid,Q.vout);
value2 = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid2,Q.vout2);
if ( value == 0 || value2 == 0 )
{
printf("zero value %.8f or value2 %.8f\n",dstr(value),dstr(value2));
return(clonestr("{\"error\":\"spent txid or txid2 for bob?\"}"));
}
if ( (butxo= LP_utxoadd(1,Q.srccoin,Q.txid,Q.vout,value,Q.txid2,Q.vout2,value2,Q.coinaddr,Q.srchash,LP_gui,0)) == 0 )
{
printf("cant find or create butxo\n");
return(clonestr("{\"error\":\"cant find or create butxo\"}"));
}
if ( value < Q.satoshis )
{
printf("butxo value %.8f less satoshis %.8f\n",dstr(value),dstr(Q.satoshis));
return(clonestr("{\"error\":\"butxo value less than satoshis\"}"));
}
}*/
if ( (qprice= LP_quote_validate(autxo,butxo,&Q,0)) <= SMALLVAL )
{
LP_availableset(autxo);
LP_pendingswaps--;
//G.LP_pendingswaps--;
printf("quote validate error %.0f\n",qprice);
return(clonestr("{\"error\":\"quote validation error\"}"));
}
@ -457,22 +646,14 @@ char *LP_connectedalice(cJSON *argjson) // alice
{
printf("this node has no price for %s/%s (%.8f %.8f)\n",Q.destcoin,Q.srccoin,bid,ask);
LP_availableset(autxo);
LP_pendingswaps--;
//G.LP_pendingswaps--;
return(clonestr("{\"error\":\"no price set\"}"));
}
printf("%s/%s bid %.8f ask %.8f\n",Q.srccoin,Q.destcoin,bid,ask);
//if ( (price= ask) == 0. )
price = bid;
/*if ( SATOSHIDEN*qprice > (SATOSHIDEN * price) * 1.001 + 10 )
{
printf("qprice %.8f too big vs %.8f\n",qprice,price);
LP_availableset(autxo);
LP_pendingswaps--;
return(clonestr("{\"error\":\"quote price too expensive\"}"));
}*/
printf("%s/%s bid %.8f ask %.8f values %.8f %.8f\n",Q.srccoin,Q.destcoin,bid,ask,dstr(butxo->payment.value),dstr(butxo->deposit.value));
price = bid;
if ( (coin= LP_coinfind(Q.destcoin)) == 0 )
{
LP_pendingswaps--;
//G.LP_pendingswaps--;
return(clonestr("{\"error\":\"cant get alicecoin\"}"));
}
Q.privkey = LP_privkey(Q.destaddr,coin->taddr);
@ -503,7 +684,7 @@ char *LP_connectedalice(cJSON *argjson) // alice
printf("connected result.(%s)\n",jprint(retjson,0));
if ( jobj(retjson,"error") != 0 )
LP_availableset(autxo);
else LP_pendingswaps++;
else G.LP_pendingswaps++;
return(jprint(retjson,1));
}
else
@ -514,22 +695,104 @@ char *LP_connectedalice(cJSON *argjson) // alice
}
}
int32_t LP_listunspent_both(char *symbol,char *coinaddr)
{
int32_t i,v,height,n=0; uint64_t value; bits256 txid; char buf[512]; cJSON *array,*item; struct iguana_info *coin = LP_coinfind(symbol);
if ( coin != 0 && coin->inactive == 0 )
{
if ( coin->electrum != 0 || LP_address_ismine(symbol,coinaddr) <= 0 )
{
//printf("issue path electrum.%p\n",coin->electrum);
//if ( coin->electrum != 0 && (array= electrum_address_gethistory(symbol,coin->electrum,&array,coinaddr)) != 0 )
// free_json(array);
n = LP_listunspent_issue(symbol,coinaddr);
}
else
{
//printf("my coin electrum.%p\n",coin->electrum);
sprintf(buf,"[1, 99999999, [\"%s\"]]",coinaddr);
if ( (array= bitcoin_json(coin,"listunspent",buf)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
txid = jbits256(item,"txid");
v = jint(item,"vout");
value = LP_value_extract(item,0);
height = LP_txheight(coin,txid);
//char str[65]; printf("LP_listunspent_both: %s/v%d ht.%d %.8f\n",bits256_str(str,txid),v,height,dstr(value));
LP_address_utxoadd(coin,coinaddr,txid,v,value,height,-1);
}
}
}
}
} //else printf("%s coin.%p inactive.%d\n",symbol,coin,coin!=0?coin->inactive:-1);
return(n);
}
int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen)
{
char *method,*msg; cJSON *retjson; double qprice,price,bid,ask; struct LP_utxoinfo *autxo,*butxo; int32_t retval = -1; struct LP_quoteinfo Q;
char *method,*msg; uint64_t value,value2; cJSON *retjson; double qprice,price,bid,ask; struct LP_utxoinfo A,B,*autxo,*butxo; struct iguana_info *coin; struct LP_address_utxo *utxos[1000]; struct LP_quoteinfo Q; int32_t retval = -1,max=(int32_t)(sizeof(utxos)/sizeof(*utxos));
if ( (method= jstr(argjson,"method")) != 0 && (strcmp(method,"request") == 0 ||strcmp(method,"connect") == 0) )
{
printf("TRADECOMMAND.(%s)\n",jprint(argjson,0));
printf("LP_tradecommand: check received %s\n",method);
retval = 1;
if ( LP_quoteparse(&Q,argjson) == 0 && bits256_cmp(LP_mypub25519,Q.srchash) == 0 )
if ( LP_quoteparse(&Q,argjson) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) == 0 && bits256_cmp(G.LP_mypub25519,Q.desthash) != 0 )
{
if ( (price= LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin)) <= SMALLVAL || ask <= SMALLVAL )
if ( (coin= LP_coinfind(Q.srccoin)) == 0 || (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 )
autxo = &A;
butxo = &B;
memset(autxo,0,sizeof(*autxo));
memset(butxo,0,sizeof(*butxo));
LP_abutxo_set(autxo,butxo,&Q);
if ( (butxo= LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2)) == 0 )
butxo = &B;
//LP_butxo_swapfields(butxo);
if ( strcmp(method,"request") == 0 )
{
char str[65],str2[65];
if ( LP_allocated(butxo->payment.txid,butxo->payment.vout) != 0 || LP_allocated(butxo->deposit.txid,butxo->deposit.vout) != 0 || (qprice= LP_quote_validate(autxo,butxo,&Q,1)) <= SMALLVAL )
{
printf("butxo.%p replace path %p %s, %p %s, %.8f\n",butxo,LP_allocated(butxo->payment.txid,butxo->payment.vout),bits256_str(str,butxo->payment.txid),LP_allocated(butxo->deposit.txid,butxo->deposit.vout),bits256_str(str2,butxo->deposit.txid),LP_quote_validate(autxo,butxo,&Q,1));
LP_listunspent_both(Q.srccoin,Q.coinaddr);
if ( (butxo= LP_address_utxopair(1,utxos,max,LP_coinfind(Q.srccoin),Q.coinaddr,Q.txfee,dstr(Q.destsatoshis),price,Q.desttxfee)) != 0 )
{
Q.txid = butxo->payment.txid;
Q.vout = butxo->payment.vout;
Q.txid2 = butxo->deposit.txid;
Q.vout2 = butxo->deposit.vout;
printf("set butxo.%p %s/v%d %s/v%d %.8f %.8f -> bsat %.8f asat %.8f\n",butxo,bits256_str(str,butxo->payment.txid),butxo->payment.vout,bits256_str(str2,butxo->deposit.txid),butxo->deposit.vout,dstr(butxo->payment.value),dstr(butxo->deposit.value),dstr(butxo->S.satoshis),dstr(autxo->S.satoshis));
} else printf("cant find utxopair\n");
//LP_abutxo_set(0,butxo,&Q);
//LP_butxo_swapfields(butxo);
}
else
{
printf("other path %p %p %.8f\n",LP_allocated(butxo->payment.txid,butxo->payment.vout),LP_allocated(butxo->deposit.txid,butxo->deposit.vout), LP_quote_validate(autxo,butxo,&Q,1));
}
}
if ( butxo == 0 || butxo == &B )
butxo = LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2);
if ( butxo == 0 )
{
value = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid,Q.vout);
value2 = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid2,Q.vout2);
butxo = LP_utxoadd(1,Q.srccoin,Q.txid,Q.vout,value,Q.txid2,Q.vout2,value2,Q.coinaddr,Q.srchash,LP_gui,0);
}
char str[65],str2[65]; printf("butxo.%p (%s %s) TRADECOMMAND.(%s)\n",butxo,butxo!=0?bits256_str(str,butxo->payment.txid):"",butxo!=0?bits256_str(str2,butxo->deposit.txid):"",jprint(argjson,0));
if ( butxo == 0 || bits256_nonz(butxo->payment.txid) == 0 || bits256_nonz(butxo->deposit.txid) == 0 || butxo->payment.vout < 0 || butxo->deposit.vout < 0 )
{
char str[65],str2[65]; printf("couldnt find bob utxos for autxo %s/v%d %s/v%d %.8f -> %.8f\n",bits256_str(str,Q.txid),Q.vout,bits256_str(str2,Q.txid2),Q.vout2,dstr(Q.satoshis),dstr(Q.destsatoshis));
return(1);
}
if ( (qprice= LP_quote_validate(autxo,butxo,&Q,1)) <= SMALLVAL )
{
printf("quote validate error %.0f\n",qprice);
return(-4);
@ -555,148 +818,38 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
jaddbits256(retjson,"pubkey",butxo->S.otherpubkey);
jaddstr(retjson,"method","reserved");
msg = jprint(retjson,1);
printf("set swappending.%u accept qprice %.8f, min %.8f\n(%s)",butxo->T.swappending,qprice,price,msg);
LP_broadcast_message(pubsock,Q.srccoin,Q.destcoin,butxo->S.otherpubkey,msg);
butxo->T.lasttime = (uint32_t)time(NULL);
printf("set swappending.%u accept qprice %.8f, min %.8f\n(%s)\n",butxo->T.swappending,qprice,price,msg);
{
bits256 zero; char *msg2;
memset(&zero,0,sizeof(zero));
msg2 = clonestr(msg);
LP_broadcast_message(pubsock,Q.srccoin,Q.destcoin,zero,msg);
LP_broadcast_message(pubsock,Q.srccoin,Q.destcoin,butxo->S.otherpubkey,msg2);
//LP_butxo_swapfields_set(butxo);
printf("return after RESERVED\n");
return(2);
}
} 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 )
if ( butxo->S.swap == 0 && butxo->T.swappending != 0 )
{
// validate SPV alice
LP_connectstartbob(ctx,pubsock,butxo,argjson,Q.srccoin,Q.destcoin,qprice,&Q);
//LP_butxo_swapfields_set(butxo);
return(3);
}
else printf("pend.%u swap %p when connect came in (%s)\n",butxo->T.swappending,butxo->S.swap,jprint(argjson,0));
}
//LP_butxo_swapfields_set(butxo);
}
}
return(retval);
}
struct LP_utxoinfo *LP_bestutxo(double *ordermatchpricep,int64_t *bestsatoshisp,int64_t *bestdestsatoshisp,struct LP_utxoinfo *autxo,char *base,double maxprice,int32_t duration,uint64_t txfee,uint64_t desttxfee,uint64_t maxdestsatoshis)
{
int64_t satoshis,destsatoshis; uint64_t val,val2; bits256 txid,pubkey; char *obookstr; cJSON *orderbook,*asks,*item; struct LP_utxoinfo *butxo,*bestutxo = 0; int32_t i,n,j,vout,numasks; double bestmetric=0.,metric,vol,price,qprice,bestprice = 0.; struct LP_pubkeyinfo *pubp;
*ordermatchpricep = 0.;
*bestsatoshisp = *bestdestsatoshisp = 0;
if ( duration <= 0 )
duration = LP_ORDERBOOK_DURATION;
if ( maxprice <= 0. || LP_priceinfofind(base) == 0 )
return(0);
LP_txfees(&txfee,&desttxfee,base,autxo->coin);
if ( (obookstr= LP_orderbook(base,autxo->coin,duration)) != 0 )
{
if ( (orderbook= cJSON_Parse(obookstr)) != 0 )
{
if ( (asks= jarray(&numasks,orderbook,"asks")) != 0 )
{
for (i=0; i<numasks; i++)
{
item = jitem(asks,i);
price = jdouble(item,"price");
if ( LP_pricevalid(price) > 0 && price <= maxprice )
{
//price *= 1.0001;
//if ( price > maxprice )
// price = maxprice;
pubkey = jbits256(item,"pubkey");
if ( bits256_cmp(pubkey,LP_mypub25519) != 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 )
{
if ( LP_iseligible(&val,&val2,butxo->iambob,butxo->coin,butxo->payment.txid,butxo->payment.vout,butxo->S.satoshis,butxo->deposit.txid,butxo->deposit.vout) > 0 )
{
destsatoshis = ((butxo->S.satoshis - txfee) * price);
satoshis = (destsatoshis / price + 0.49) - txfee;
if ( satoshis <= 0 )
continue;
qprice = (double)destsatoshis / satoshis;
n = (int32_t)((double)destsatoshis / desttxfee);
if ( n < 10 )
n = 10;
else n = 3;
for (j=0; j<n; j++)
{
if ( (qprice= LP_qprice_calc(&destsatoshis,&satoshis,(price*(100.+j))/100.,butxo->S.satoshis,txfee,autxo->payment.value,maxdestsatoshis,desttxfee)) > price+SMALLVAL )
break;
}
//printf("j.%d/%d qprice %.8f vs price %.8f best.(%.8f %.8f)\n",j,n,qprice,price,dstr(satoshis),dstr(destsatoshis));
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;
*ordermatchpricep = price;
*bestdestsatoshisp = destsatoshis;
*bestsatoshisp = satoshis;
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
{
printf("ineligible.(%.8f %.8f)\n",price,dstr(butxo->S.satoshis));
//if ( butxo->T.spentflag == 0 )
// butxo->T.spentflag = (uint32_t)time(NULL);
}
}
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 or bestflag.%d\n",butxo,vol,butxo!=0?dstr(butxo->S.satoshis):0,butxo->T.bestflag);
}
} else printf("self trading or blacklisted peer\n");
}
else
{
if ( i == 0 )
printf("maxprice %.8f vs %.8f\n",maxprice,price);
break;
}
}
if ( bestutxo == 0 )
{
int32_t numrestraints;
for (i=numrestraints=0; i<numasks; i++)
{
item = jitem(asks,i);
pubkey = jbits256(item,"pubkey");
if ( bits256_cmp(pubkey,LP_mypub25519) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 )
{
txid = jbits256(item,"txid");
vout = jint(item,"vout");
if ( (butxo= LP_utxofind(1,txid,vout)) != 0 )
{
numrestraints++;
butxo->T.bestflag = 0;
pubp->numerrors = 0;
}
}
}
printf("no bob utxo found -> cleared %d restraints\n",numrestraints);
}
}
free_json(orderbook);
}
free(obookstr);
}
if ( bestutxo == 0 || *ordermatchpricep == 0. || *bestdestsatoshisp == 0 )
return(0);
bestutxo->T.bestflag = 1;
int32_t changed;
LP_mypriceset(&changed,autxo->coin,base,1. / *ordermatchpricep);
return(bestutxo);
}
char *LP_bestfit(char *rel,double relvolume)
{
struct LP_utxoinfo *autxo;
@ -707,35 +860,14 @@ char *LP_bestfit(char *rel,double relvolume)
return(jprint(LP_utxojson(autxo),1));
}
char *LP_ordermatch(char *base,int64_t txfee,double maxprice,double maxvolume,char *rel,bits256 txid,int32_t vout,bits256 feetxid,int32_t feevout,int64_t desttxfee,int32_t duration)
{
struct LP_quoteinfo Q; int64_t bestsatoshis=0,bestdestsatoshis = 0; double ordermatchprice = 0.; struct LP_utxoinfo *autxo,*bestutxo;
txfee = LP_txfeecalc(LP_coinfind(base),txfee);
desttxfee = LP_txfeecalc(LP_coinfind(rel),desttxfee);
if ( (autxo= LP_utxopairfind(0,txid,vout,feetxid,feevout)) == 0 )
return(clonestr("{\"error\":\"cant find alice utxopair\"}"));
if ( (bestutxo= LP_bestutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,SATOSHIDEN*maxvolume)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 )
return(clonestr("{\"error\":\"cant find ordermatch utxo\"}"));
if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestsatoshis,bestdestsatoshis) < 0 )
return(clonestr("{\"error\":\"cant set ordermatch quote\"}"));
if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,LP_mypub25519,autxo->coinaddr) < 0 )
return(clonestr("{\"error\":\"cant set ordermatch quote info\"}"));
return(jprint(LP_quotejson(&Q),1));
}
char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp,double maxprice,int32_t timeout,int32_t duration)
{
struct LP_utxoinfo *bobutxo,*aliceutxo; cJSON *bestitem=0; int32_t DEXselector=0; uint32_t expiration; double price; struct LP_pubkeyinfo *pubp;
struct LP_utxoinfo *aliceutxo; cJSON *bestitem=0; int32_t DEXselector=0; uint32_t expiration; double price; struct LP_pubkeyinfo *pubp; struct basilisk_swap *swap;
if ( (aliceutxo= LP_utxopairfind(0,qp->desttxid,qp->destvout,qp->feetxid,qp->feevout)) == 0 )
{
char str[65],str2[65]; printf("dest.(%s)/v%d fee.(%s)/v%d\n",bits256_str(str,qp->desttxid),qp->destvout,bits256_str(str2,qp->feetxid),qp->feevout);
return(clonestr("{\"error\":\"cant find alice utxopair\"}"));
}
if ( (bobutxo= LP_utxopairfind(1,qp->txid,qp->vout,qp->txid2,qp->vout2)) == 0 )
return(clonestr("{\"error\":\"cant find bob utxopair\"}"));
bobutxo->T.bestflag = (uint32_t)time(NULL);
//if ( (retstr= LP_registerall(0)) != 0 )
// free(retstr);
price = LP_query(ctx,myipaddr,mypubsock,"request",qp);
bestitem = LP_quotejson(qp);
if ( LP_pricevalid(price) > 0 )
@ -743,25 +875,29 @@ char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *q
if ( price <= maxprice )
{
price = LP_query(ctx,myipaddr,mypubsock,"connect",qp);
LP_requestinit(&qp->R,qp->srchash,qp->desthash,bobutxo->coin,qp->satoshis-qp->txfee,qp->destcoin,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector);
LP_requestinit(&qp->R,qp->srchash,qp->desthash,qp->srccoin,qp->satoshis-qp->txfee,qp->destcoin,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector);
expiration = (uint32_t)time(NULL) + timeout;
while ( time(NULL) < expiration )
{
if ( aliceutxo->S.swap != 0 )
break;
sleep(1);
sleep(3);
}
if ( aliceutxo->S.swap == 0 )
jaddnum(bestitem,"quotedprice",price);
jaddnum(bestitem,"maxprice",maxprice);
if ( (swap= aliceutxo->S.swap) == 0 )
{
if ( (pubp= LP_pubkeyadd(bobutxo->pubkey)) != 0 )
if ( (pubp= LP_pubkeyadd(qp->srchash)) != 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",qp->R.requestid);
jaddnum(bestitem,"quoteid",qp->R.quoteid);
printf("Alice r.%u qp->%u\n",qp->R.requestid,qp->R.quoteid);
}
else
{
jaddstr(bestitem,"status","connected");
jaddnum(bestitem,"requestid",swap->I.req.requestid);
jaddnum(bestitem,"quoteid",swap->I.req.quoteid);
printf("Alice r.%u qp->%u\n",swap->I.req.requestid,swap->I.req.quoteid);
}
}
else
{
@ -772,6 +908,7 @@ char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *q
}
else
{
printf("invalid price %.8f\n",price);
jaddnum(bestitem,"maxprice",maxprice);
jaddstr(bestitem,"status","no response to request");
}
@ -780,36 +917,120 @@ char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *q
return(jprint(bestitem,0));
}
char *LP_autotrade(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel,double maxprice,double relvolume,int32_t timeout,int32_t duration)
struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,int64_t *bestdestsatoshisp,struct LP_utxoinfo *autxo,char *base,double maxprice,int32_t duration,uint64_t txfee,uint64_t desttxfee,char *gui,bits256 *avoids,int32_t numavoids)
{
bits256 pubkey; char *obookstr,coinaddr[64],str[65]; cJSON *orderbook,*asks,*item; int32_t i,j,n,numasks,max = 10000; struct LP_address_utxo **utxos; double price; struct LP_pubkeyinfo *pubp; struct iguana_info *basecoin; uint64_t basesatoshis; struct LP_utxoinfo *bestutxo = 0;
*ordermatchpricep = 0.;
*bestsatoshisp = *bestdestsatoshisp = 0;
basecoin = LP_coinfind(base);
if ( duration <= 0 )
duration = LP_ORDERBOOK_DURATION;
if ( maxprice <= 0. || LP_priceinfofind(base) == 0 || basecoin == 0 )
return(0);
utxos = calloc(max,sizeof(*utxos));
LP_txfees(&txfee,&desttxfee,base,autxo->coin);
printf("LP_buyutxo maxprice %.8f relvol %.8f %s/%s %.8f %.8f\n",maxprice,dstr(autxo->S.satoshis),base,autxo->coin,dstr(txfee),dstr(desttxfee));
if ( (obookstr= LP_orderbook(base,autxo->coin,duration)) != 0 )
{
if ( (orderbook= cJSON_Parse(obookstr)) != 0 )
{
if ( (asks= jarray(&numasks,orderbook,"asks")) != 0 )
{
for (i=0; i<numasks; i++)
{
item = jitem(asks,i);
price = jdouble(item,"price");
pubkey = jbits256(item,"pubkey");
printf("[%d/%d] %s pubcmp %d price %.8f vs maxprice %.8f\n",i,numasks,jprint(item,0),bits256_cmp(pubkey,G.LP_mypub25519),price,maxprice);
if ( LP_pricevalid(price) > 0 && price <= maxprice )
{
for (j=0; j<numavoids; j++)
if ( bits256_cmp(pubkey,avoids[j]) == 0 )
break;
if ( j != numavoids )
continue;
if ( bits256_cmp(pubkey,G.LP_mypub25519) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 )
{
bitcoin_address(coinaddr,basecoin->taddr,basecoin->pubtype,pubp->rmd160,sizeof(pubp->rmd160));
n = LP_listunspent_both(base,coinaddr);
//printf("unspent.(%s) n.%d\n",coinaddr,n);
if ( n > 1 )
{
basesatoshis = LP_basesatoshis(dstr(autxo->S.satoshis),price,txfee,desttxfee);
if ( basesatoshis != 0 && (bestutxo= LP_address_utxopair(0,utxos,max,basecoin,coinaddr,txfee,dstr(basesatoshis)*price,price,desttxfee)) != 0 )
{
bestutxo->pubkey = pubp->pubkey;
safecopy(bestutxo->gui,gui,sizeof(bestutxo->gui));
*bestsatoshisp = basesatoshis;
*ordermatchpricep = price;
*bestdestsatoshisp = autxo->S.satoshis;
printf("ordermatch %.8f %.8f %.8f txfees (%.8f %.8f)\n",price,dstr(*bestsatoshisp),dstr(*bestdestsatoshisp),dstr(txfee),dstr(desttxfee));
break;
}
} else printf("no unspents %s %s %s\n",base,coinaddr,bits256_str(str,pubkey));
} else printf("self trading or blacklisted peer\n");
}
else
{
if ( i == 0 )
printf("too expensive maxprice %.8f vs %.8f\n",maxprice,price);
break;
}
}
}
free_json(orderbook);
}
free(obookstr);
}
free(utxos);
if ( *ordermatchpricep == 0. || *bestdestsatoshisp == 0 )
return(0);
int32_t changed;
LP_mypriceset(&changed,autxo->coin,base,1. / *ordermatchpricep);
return(bestutxo);
}
char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel,double maxprice,double relvolume,int32_t timeout,int32_t duration,char *gui)
{
uint64_t desttxfee,txfee; int64_t bestsatoshis=0,bestdestsatoshis=0; struct LP_utxoinfo *autxo,*butxo,*bestutxo = 0; double qprice,ordermatchprice=0.; struct LP_quoteinfo Q;
uint64_t desttxfee,txfee; int32_t numpubs = 0; int64_t bestsatoshis=0,destsatoshis,bestdestsatoshis=0; struct LP_utxoinfo *autxo,*bestutxo = 0; double qprice,ordermatchprice=0.; struct LP_quoteinfo Q; bits256 pubkeys[100];
printf("LP_autobuy %s/%s price %.8f vol %.8f\n",base,rel,maxprice,relvolume);
if ( duration <= 0 )
duration = LP_ORDERBOOK_DURATION;
if ( timeout <= 0 )
timeout = LP_AUTOTRADE_TIMEOUT;
if ( maxprice <= 0. || relvolume <= 0. || LP_priceinfofind(base) == 0 || LP_priceinfofind(rel) == 0 )
return(clonestr("{\"error\":\"invalid parameter\"}"));
if ( (autxo= LP_utxo_bestfit(rel,SATOSHIDEN * relvolume)) == 0 )
return(clonestr("{\"error\":\"cant find utxo that is big enough\"}"));
if ( strcmp("BTC",rel) == 0 )
maxprice *= 1.01;
else maxprice *= 1.001;
memset(pubkeys,0,sizeof(pubkeys));
LP_txfees(&txfee,&desttxfee,base,rel);
if ( (bestutxo= LP_bestutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,SATOSHIDEN*relvolume)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 )
{
printf("bestutxo.%p ordermatchprice %.8f bestdestsatoshis %.8f\n",bestutxo,ordermatchprice,dstr(bestdestsatoshis));
return(clonestr("{\"error\":\"cant find ordermatch utxo\"}"));
}
if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestsatoshis,bestdestsatoshis) < 0 )
return(clonestr("{\"error\":\"cant set ordermatch quote\"}"));
if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,LP_mypub25519,autxo->coinaddr) < 0 )
return(clonestr("{\"error\":\"cant set ordermatch quote info\"}"));
if ( (qprice= LP_quote_validate(&autxo,&butxo,&Q,0)) <= SMALLVAL )
destsatoshis = SATOSHIDEN * relvolume + 2*desttxfee;
if ( (autxo= LP_utxo_bestfit(rel,destsatoshis)) == 0 )
return(clonestr("{\"error\":\"cant find utxo that is big enough\"}"));
if ( destsatoshis < autxo->S.satoshis )
autxo->S.satoshis = destsatoshis;
while ( 1 )
{
printf("quote validate error %.0f\n",qprice);
return(clonestr("{\"error\":\"quote validation error\"}"));
if ( (bestutxo= LP_buyutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,gui,pubkeys,numpubs)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 )
{
printf("bestutxo.%p ordermatchprice %.8f bestdestsatoshis %.8f\n",bestutxo,ordermatchprice,dstr(bestdestsatoshis));
return(clonestr("{\"error\":\"cant find ordermatch utxo\"}"));
}
pubkeys[numpubs++] = bestutxo->pubkey;
if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestsatoshis,bestdestsatoshis) < 0 )
return(clonestr("{\"error\":\"cant set ordermatch quote\"}"));
if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,G.LP_mypub25519,autxo->coinaddr) < 0 )
return(clonestr("{\"error\":\"cant set ordermatch quote info\"}"));
if ( (qprice= LP_quote_validate(autxo,0,&Q,0)) <= SMALLVAL )
{
printf("continue searching, quote validate error %.0f\n",qprice);
continue;
}
break;
}
printf("do quote.(%s)\n",jprint(LP_quotejson(&Q),1));
//printf("do quote.(%s)\n",jprint(LP_quotejson(&Q),1));
return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration));
}

41
iguana/exchanges/LP_peers.c

@ -35,9 +35,9 @@ cJSON *LP_peerjson(struct LP_peerinfo *peer)
jaddnum(item,"port",peer->port);
if ( strcmp(peer->ipaddr,LP_myipaddr) == 0 )
{
jaddnum(item,"session",LP_sessionid);
if ( LP_mypeer != 0 )
jaddnum(item,"numutxos",LP_mypeer->numutxos);
jaddnum(item,"session",G.LP_sessionid);
//if ( LP_mypeer != 0 )
// jaddnum(item,"numutxos",LP_mypeer->numutxos);
} else jaddnum(item,"session",peer->sessionid);
//jaddnum(item,"profit",peer->profitmargin);
return(item);
@ -58,8 +58,6 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char
{
uint32_t ipbits; int32_t pushsock,subsock,timeout; char checkip[64],pushaddr[64],subaddr[64]; struct LP_peerinfo *peer = 0;
printf("addpeer (%s:%u)\n",ipaddr,port);
if ( port > 10000 )
return(0);
#ifdef LP_STRICTPEERS
if ( strncmp("5.9.253",ipaddr,strlen("5.9.253")) != 0 )
return(0);
@ -81,7 +79,7 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char
{
peer = calloc(1,sizeof(*peer));
if ( strcmp(peer->ipaddr,LP_myipaddr) == 0 )
peer->sessionid = LP_sessionid;
peer->sessionid = G.LP_sessionid;
else peer->sessionid = sessionid;
peer->pushsock = peer->subsock = pushsock = subsock = -1;
strcpy(peer->ipaddr,ipaddr);
@ -219,9 +217,9 @@ int32_t LP_peersparse(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipa
void LP_peersquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *myipaddr,uint16_t myport)
{
char *retstr; struct LP_peerinfo *peer,*tmp; uint32_t now,flag = 0;
char *retstr; struct LP_peerinfo *peer,*tmp; bits256 zero; uint32_t now,flag = 0;
peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport);
if ( (retstr= issue_LP_getpeers(destipaddr,destport,myipaddr,myport,mypeer!=0?mypeer->numpeers:0,mypeer!=0?mypeer->numutxos:0)) != 0 )
if ( (retstr= issue_LP_getpeers(destipaddr,destport,myipaddr,myport,mypeer!=0?mypeer->numpeers:0)) != 0 )
{
//printf("got.(%s)\n",retstr);
now = (uint32_t)time(NULL);
@ -235,7 +233,8 @@ void LP_peersquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr
{
printf("{%s:%u}.%d ",peer->ipaddr,peer->port,peer->lasttime - now);
flag++;
if ( (retstr= issue_LP_notify(destipaddr,destport,peer->ipaddr,peer->port,peer->numpeers,0,peer->sessionid)) != 0 )
memset(&zero,0,sizeof(zero));
if ( (retstr= issue_LP_notify(destipaddr,destport,peer->ipaddr,peer->port,peer->numpeers,peer->sessionid,0,zero)) != 0 )
free(retstr);
}
}
@ -254,3 +253,27 @@ int32_t LP_numpeers()
}
return(numpeers);
}
uint16_t LP_randpeer(char *destip)
{
struct LP_peerinfo *peer,*tmp; uint16_t port = 0; int32_t n,r,numpeers = 0;
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
numpeers++;
}
if ( numpeers > 0 )
{
r = rand() % numpeers;
n = 0;
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
if ( n++ == r )
{
strcpy(destip,peer->ipaddr);
port = peer->port;
break;
}
}
}
return(port);
}

22
iguana/exchanges/LP_portfolio.c

@ -57,13 +57,13 @@ uint64_t LP_balance(uint64_t *valuep,int32_t iambob,char *symbol,char *coinaddr)
for (i=0; i<n; i++)
{
item = jitem(array,i);
value = LP_value_extract(item);
value = LP_value_extract(item,1);
valuesum += value;
}
}
free_json(array);
}
if ( (array= LP_inventory(symbol,iambob)) != 0 )
if ( (array= LP_inventory(symbol)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 && is_cJSON_Array(array) != 0 )
{
@ -89,11 +89,11 @@ char *LP_portfolio()
{
HASH_ITER(hh,LP_coins,coin,tmp)
{
if ( coin->inactive != 0 )
if ( coin->inactive != 0 )//|| (coin->electrum != 0 && coin->obooktime == 0) )
continue;
if ( iter == 0 )
{
LP_privkey_init(-1,coin,LP_mypriv25519,LP_mypub25519);
LP_privkey_init(-1,coin,G.LP_mypriv25519,G.LP_mypub25519);
coin->balanceA = LP_balance(&coin->valuesumA,0,coin->symbol,coin->smartaddr);
coin->balanceB = LP_balance(&coin->valuesumB,1,coin->symbol,coin->smartaddr);
if ( strcmp(coin->symbol,"KMD") != 0 )
@ -184,12 +184,16 @@ char *LP_portfolio_goal(char *symbol,double goal)
coin->goal = kmdbtc * 0.5;
if ( (coin= LP_coinfind("BTC")) != 0 && coin->inactive == 0 )
coin->goal = kmdbtc * 0.5;
if ( coin->goal != 0 )
coin->obooktime = (uint32_t)time(NULL);
return(LP_portfolio());
}
else if ( (coin= LP_coinfind(symbol)) != 0 && coin->inactive == 0 )
{
coin->goal = goal;
printf("set %s goal %f\n",coin->symbol,goal);
if ( coin->goal != 0 )
coin->obooktime = (uint32_t)time(NULL);
return(LP_portfolio());
} else return(clonestr("{\"error\":\"cant set goal for inactive coin\"}"));
}
@ -415,7 +419,7 @@ void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp)
}
}
int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,struct iguana_info *buy,struct iguana_info *sell,double relvolume,int32_t setbaserel)
int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,struct iguana_info *buy,struct iguana_info *sell,double relvolume,int32_t setbaserel,char *gui)
{
char *retstr2; double bid,ask,maxprice; uint32_t requestid,quoteid,iter,i; cJSON *retjson2;
requestid = quoteid = 0;
@ -427,7 +431,7 @@ int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,str
strcpy(LP_portfolio_rel,"");
LP_portfolio_relvolume = 0.;
}
printf("pending.%d base buy.%s, rel sell.%s relvolume %f maxprice %.8f (%.8f %.8f)\n",LP_pendingswaps,buy->symbol,sell->symbol,sell->relvolume,maxprice,bid,ask);
printf("pending.%d base buy.%s, rel sell.%s relvolume %f maxprice %.8f (%.8f %.8f)\n",G.LP_pendingswaps,buy->symbol,sell->symbol,sell->relvolume,maxprice,bid,ask);
if ( LP_pricevalid(maxprice) > 0 )
{
relvolume = sell->relvolume;
@ -437,7 +441,7 @@ int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,str
break;
if ( LP_utxo_bestfit(sell->symbol,SATOSHIDEN * relvolume) != 0 )
{
if ( (retstr2= LP_autotrade(ctx,"127.0.0.1",-1,buy->symbol,sell->symbol,maxprice,relvolume,60,24*3600)) != 0 )
if ( (retstr2= LP_autobuy(ctx,"127.0.0.1",-1,buy->symbol,sell->symbol,maxprice,relvolume,60,24*3600,gui)) != 0 )
{
if ( (retjson2= cJSON_Parse(retstr2)) != 0 )
{
@ -546,7 +550,7 @@ void prices_loop(void *ignore)
{
if ( (buycoin= jstr(retjson,"buycoin")) != 0 && (buy= LP_coinfind(buycoin)) != 0 && (sellcoin= jstr(retjson,"sellcoin")) != 0 && (sell= LP_coinfind(sellcoin)) != 0 && buy->inactive == 0 && sell->inactive == 0 )
{
if ( LP_portfolio_trade(ctx,&requestid,&quoteid,buy,sell,sell->relvolume,1) < 0 )
if ( LP_portfolio_trade(ctx,&requestid,&quoteid,buy,sell,sell->relvolume,1,"portfolio") < 0 )
{
array = jarray(&m,retjson,"portfolio");
if ( array != 0 && (n= LP_portfolio_order(trades,(int32_t)(sizeof(trades)/sizeof(*trades)),array)) > 0 )
@ -557,7 +561,7 @@ void prices_loop(void *ignore)
{
buy = LP_coinfind(trades[i].buycoin);
sell = LP_coinfind(trades[i].sellcoin);
if ( buy != 0 && sell != 0 && LP_portfolio_trade(ctx,&requestid,&quoteid,buy,sell,sell->relvolume,0) == 0 )
if ( buy != 0 && sell != 0 && LP_portfolio_trade(ctx,&requestid,&quoteid,buy,sell,sell->relvolume,0,"portfolio") == 0 )
break;
}
}

348
iguana/exchanges/LP_prices.c

@ -18,7 +18,7 @@
// marketmaker
//
struct LP_orderbookentry { bits256 txid,txid2,pubkey; double price; uint64_t basesatoshis; int32_t vout,vout2,age; };
struct LP_orderbookentry { bits256 pubkey; double price; uint64_t minsatoshis,maxsatoshis; uint32_t timestamp; int32_t numutxos; char coinaddr[64]; };
#define LP_MAXPRICEINFOS 256
struct LP_priceinfo
@ -52,73 +52,9 @@ struct LP_pubkeyinfo
bits256 pubkey;
double matrix[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS];
uint32_t timestamp,istrusted,numerrors;
uint8_t rmd160[20];
uint8_t rmd160[20],pubsecp[33];
} *LP_pubkeyinfos;
struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr)
{
struct LP_address *ap;
HASH_FIND(hh,coin->addresses,coinaddr,strlen(coinaddr),ap);
return(ap);
}
struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr)
{
struct LP_address *ap;
ap = calloc(1,sizeof(*ap));
safecopy(ap->coinaddr,coinaddr,sizeof(ap->coinaddr));
HASH_ADD_KEYPTR(hh,coin->addresses,ap->coinaddr,strlen(ap->coinaddr),ap);
return(ap);
}
struct LP_address *_LP_address(struct iguana_info *coin,char *coinaddr)
{
struct LP_address *ap;
if ( (ap= _LP_addressfind(coin,coinaddr)) == 0 )
ap = _LP_addressadd(coin,coinaddr);
return(ap);
}
/*void LP_address_utxoadd(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value)
{
struct LP_address *ap; struct LP_address_utxo *up;
portable_mutex_lock(&coin->txmutex);
if ( (ap= _LP_address(coin,coinaddr)) != 0 )
{
up = calloc(1,sizeof(*up));
up->U.txid = txid;
up->U.vout = vout;
up->U.value = value;
DL_APPEND(ap->utxos,up);
}
portable_mutex_unlock(&coin->txmutex);
}
void LP_address_monitor(struct LP_pubkeyinfo *pubp)
{
struct iguana_info *coin,*tmp; char coinaddr[64]; cJSON *retjson; struct LP_address *ap;
return;
HASH_ITER(hh,LP_coins,coin,tmp)
{
bitcoin_address(coinaddr,coin->taddr,coin->pubtype,pubp->rmd160,sizeof(pubp->rmd160));
portable_mutex_lock(&coin->txmutex);
if ( (ap= _LP_address(coin,coinaddr)) != 0 )
{
ap->monitor = (uint32_t)time(NULL);
}
portable_mutex_unlock(&coin->txmutex);
if ( coin->electrum != 0 )
{
if ( (retjson= electrum_address_subscribe(coin->symbol,coin->electrum,&retjson,coinaddr)) != 0 )
{
printf("%s MONITOR.(%s) -> %s\n",coin->symbol,coinaddr,jprint(retjson,0));
free_json(retjson);
}
}
}
}*/
int32_t LP_pricevalid(double price)
{
if ( price > SMALLVAL && isnan(price) == 0 && price < SATOSHIDEN )
@ -190,6 +126,52 @@ struct LP_cacheinfo *LP_cachefind(char *base,char *rel,bits256 txid,int32_t vout
return(ptr);
}
struct LP_pubkeyinfo *LP_pubkey_rmd160find(uint8_t rmd160[20])
{
struct LP_pubkeyinfo *pubp=0,*tmp;
portable_mutex_lock(&LP_pubkeymutex);
HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp)
{
if ( memcmp(rmd160,pubp->rmd160,sizeof(pubp->rmd160)) == 0 )
break;
pubp = 0;
}
portable_mutex_unlock(&LP_pubkeymutex);
return(pubp);
}
struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr)
{
uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkeyinfo *pubp;
HASH_FIND(hh,coin->addresses,coinaddr,strlen(coinaddr),ap);
if ( ap != 0 && bits256_nonz(ap->pubkey) == 0 )
{
bitcoin_addr2rmd160(coin->taddr,&addrtype,rmd160,coinaddr);
if ( (pubp= LP_pubkey_rmd160find(rmd160)) != 0 )
{
ap->pubkey = pubp->pubkey;
memcpy(ap->pubsecp,pubp->pubsecp,sizeof(ap->pubsecp));
}
}
return(ap);
}
struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr)
{
uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkeyinfo *pubp;
ap = calloc(1,sizeof(*ap));
safecopy(ap->coinaddr,coinaddr,sizeof(ap->coinaddr));
bitcoin_addr2rmd160(coin->taddr,&addrtype,rmd160,coinaddr);
if ( (pubp= LP_pubkey_rmd160find(rmd160)) != 0 )
{
ap->pubkey = pubp->pubkey;
memcpy(ap->pubsecp,pubp->pubsecp,sizeof(ap->pubsecp));
}
//printf("LP_ADDRESS %s ADD.(%s)\n",coin->symbol,coinaddr);
HASH_ADD_KEYPTR(hh,coin->addresses,ap->coinaddr,strlen(ap->coinaddr),ap);
return(ap);
}
struct LP_pubkeyinfo *LP_pubkeyfind(bits256 pubkey)
{
struct LP_pubkeyinfo *pubp=0;
@ -207,8 +189,11 @@ struct LP_pubkeyinfo *LP_pubkeyadd(bits256 pubkey)
portable_mutex_lock(&LP_pubkeymutex);
pubp = calloc(1,sizeof(*pubp));
pubp->pubkey = pubkey;
if ( bits256_cmp(LP_mypub25519,pubkey) == 0 )
memcpy(pubp->rmd160,LP_myrmd160,sizeof(pubp->rmd160));
if ( bits256_cmp(G.LP_mypub25519,pubkey) == 0 )
{
memcpy(pubp->rmd160,G.LP_myrmd160,sizeof(pubp->rmd160));
memcpy(pubp->pubsecp,G.LP_pubsecp,sizeof(pubp->pubsecp));
}
HASH_ADD_KEYPTR(hh,LP_pubkeyinfos,&pubp->pubkey,sizeof(pubp->pubkey),pubp);
portable_mutex_unlock(&LP_pubkeymutex);
if ( (pubp= LP_pubkeyfind(pubkey)) == 0 )
@ -236,9 +221,29 @@ char *LP_pubkey_trustset(bits256 pubkey,uint32_t trustval)
return(clonestr("{\"error\":\"pubkey not found\"}"));
}
uint64_t LP_unspents_metric(struct iguana_info *coin,char *coinaddr)
{
cJSON *array,*item; int32_t i,n; uint64_t metric=0,total;
LP_listunspent_both(coin->symbol,coinaddr);
if ( (array= LP_address_utxos(coin,coinaddr,1)) != 0 )
{
total = 0;
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
total += j64bits(item,"value");
}
}
metric = _LP_unspents_metric(total,n);
}
return(metric);
}
cJSON *LP_pubkeyjson(struct LP_pubkeyinfo *pubp)
{
int32_t baseid,relid; char *base,hexstr[41]; double price; cJSON *item,*array,*obj;
int32_t baseid,relid,i,j; char *base,hexstr[67],hexstr2[67]; double price; cJSON *item,*array,*obj;
obj = cJSON_CreateObject();
array = cJSON_CreateArray();
for (baseid=0; baseid<LP_numpriceinfos; baseid++)
@ -258,8 +263,25 @@ cJSON *LP_pubkeyjson(struct LP_pubkeyinfo *pubp)
}
}
jaddbits256(obj,"pubkey",pubp->pubkey);
init_hexbytes_noT(hexstr,pubp->rmd160,sizeof(pubp->rmd160));
jaddstr(obj,"rmd160",hexstr);
for (i=0; i<sizeof(pubp->rmd160); i++)
{
if ( pubp->rmd160[i] != 0 )
{
init_hexbytes_noT(hexstr,pubp->rmd160,sizeof(pubp->rmd160));
jaddstr(obj,"rmd160",hexstr);
for (j=0; i<sizeof(pubp->pubsecp); i++)
{
if ( pubp->pubsecp[i] != 0 )
{
init_hexbytes_noT(hexstr2,pubp->pubsecp,sizeof(pubp->pubsecp));
jaddstr(obj,"pubsecp",hexstr2);
//printf("nonz rmd160 (%s %s)\n",hexstr,hexstr2);
break;
}
}
break;
}
}
jaddnum(obj,"timestamp",pubp->timestamp);
jadd(obj,"asks",array);
if ( pubp->istrusted != 0 )
@ -277,26 +299,38 @@ char *LP_prices()
return(jprint(array,1));
}
void LP_prices_parse(cJSON *obj)
void LP_prices_parse(struct LP_peerinfo *peer,cJSON *obj)
{
static uint8_t zeroes[20];
struct LP_pubkeyinfo *pubp; struct LP_priceinfo *basepp,*relpp; uint32_t timestamp; bits256 pubkey; cJSON *asks,*item; uint8_t rmd160[20]; int32_t i,n,relid; char *base,*rel,*hexstr; double askprice;
struct LP_pubkeyinfo *pubp; struct LP_priceinfo *basepp,*relpp; uint32_t timestamp; bits256 pubkey; cJSON *asks,*item; uint8_t rmd160[20]; int32_t i,n,relid,mismatch; char *base,*rel,*hexstr,*pubsecpstr; double askprice; uint32_t now;
now = (uint32_t)time(NULL);
pubkey = jbits256(obj,"pubkey");
if ( bits256_nonz(pubkey) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 )
{
if ( (hexstr= jstr(obj,"rmd160")) != 0 && strlen(hexstr) == 2*sizeof(rmd160) )
{
decode_hex(rmd160,sizeof(rmd160),hexstr);
if ( memcmp(zeroes,rmd160,sizeof(rmd160)) != 0 && memcmp(pubp->rmd160,rmd160,sizeof(rmd160)) != 0 )
if ( memcmp(pubp->rmd160,rmd160,sizeof(rmd160)) != 0 )
mismatch = 1;
else mismatch = 0;
if ( bits256_cmp(pubkey,G.LP_mypub25519) == 0 && mismatch == 0 )
peer->needping = 0;
if ( mismatch != 0 && memcmp(zeroes,rmd160,sizeof(rmd160)) != 0 )
{
for (i=0; i<20; i++)
printf("%02x",pubp->rmd160[i]);
char str[65]; printf(" -> rmd160.(%s) for %s\n",hexstr,bits256_str(str,pubkey));
memcpy(pubp->rmd160,rmd160,sizeof(pubp->rmd160));
//LP_address_monitor(pubp);
if ( (pubsecpstr= jstr(obj,"pubsecp")) != 0 && is_hexstr(pubsecpstr,0) == 66 )
{
decode_hex(pubp->pubsecp,sizeof(pubp->pubsecp),pubsecpstr);
char str[65]; printf(" -> rmd160.(%s) for %s (%s)\n",hexstr,bits256_str(str,pubkey),pubsecpstr);
}
}
}
if ( (timestamp= juint(obj,"timestamp")) > pubp->timestamp && (asks= jarray(&n,obj,"asks")) != 0 )
timestamp = juint(obj,"timestamp");
if ( timestamp > now )
timestamp = now;
if ( timestamp > pubp->timestamp && (asks= jarray(&n,obj,"asks")) != 0 )
{
pubp->timestamp = timestamp;
for (i=0; i<n; i++)
@ -309,7 +343,7 @@ void LP_prices_parse(cJSON *obj)
{
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);
//char str[65]; printf("gotprice %s %s/%s (%d/%d) %.8f\n",bits256_str(str,pubkey),base,rel,basepp->ind,relid,askprice);
pubp->matrix[basepp->ind][relid] = askprice;
if ( (relpp= LP_priceinfofind(rel)) != 0 )
{
@ -323,22 +357,27 @@ void LP_prices_parse(cJSON *obj)
}
}
void LP_peer_pricesquery(char *destipaddr,uint16_t destport)
void LP_peer_pricesquery(struct LP_peerinfo *peer)
{
char *retstr; cJSON *array; int32_t i,n;
if ( (retstr= issue_LP_getprices(destipaddr,destport)) != 0 )
peer->needping = (uint32_t)time(NULL);
if ( (retstr= issue_LP_getprices(peer->ipaddr,peer->port)) != 0 )
{
if ( (array= cJSON_Parse(retstr)) != 0 )
{
if ( is_cJSON_Array(array) && (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
LP_prices_parse(jitem(array,i));
LP_prices_parse(peer,jitem(array,i));
}
free_json(array);
}
free(retstr);
}
if ( peer->needping != 0 )
{
//printf("%s needs ping\n",peer->ipaddr);
}
}
double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,int32_t vout)
@ -353,9 +392,9 @@ double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,i
ptr->price = (double)ptr->Q.destsatoshis / ptr->Q.satoshis;
if ( LP_pricevalid(ptr->price) <= 0 )
ptr->price = 0.;
//printf("LP_pricecache: set %s/%s ptr->price %.8f\n",base,rel,ptr->price);
printf("LP_pricecache: set %s/%s ptr->price %.8f\n",base,rel,ptr->price);
}
//printf("found %s/%s %.8f\n",base,rel,ptr->price);
printf(">>>>>>>>>> found %s/%s %.8f\n",base,rel,ptr->price);
return(ptr->price);
}
//char str[65]; printf("cachemiss %s/%s %s/v%d\n",base,rel,bits256_str(str,txid),vout);
@ -447,7 +486,7 @@ int32_t LP_mypriceset(int32_t *changedp,char *base,char *rel,double price)
basepp->myprices[relpp->ind] = price; // ask
//printf("LP_mypriceset base.%s rel.%s <- price %.8f\n",base,rel,price);
//relpp->myprices[basepp->ind] = (1. / price); // bid
if ( (pubp= LP_pubkeyadd(LP_mypub25519)) != 0 )
if ( (pubp= LP_pubkeyadd(G.LP_mypub25519)) != 0 )
{
pubp->matrix[basepp->ind][relpp->ind] = price;
//pubp->matrix[relpp->ind][basepp->ind] = (1. / price);
@ -577,101 +616,129 @@ static int _cmp_orderbook(const void *a,const void *b)
{
#undef ptr_a
#undef ptr_b
#define ptr_a ((struct LP_orderbookentry *)a)->basesatoshis
#define ptr_b ((struct LP_orderbookentry *)b)->basesatoshis
#define ptr_a ((struct LP_orderbookentry *)a)->maxsatoshis
#define ptr_b ((struct LP_orderbookentry *)b)->maxsatoshis
if ( ptr_b > ptr_a )
return(-1);
else if ( ptr_b < ptr_a )
return(1);
}
// printf("%.8f vs %.8f -> %d\n",ptr_a,ptr_b,retval);
// printf("%.8f vs %.8f -> %d\n",ptr_a,ptr_b,retval);
return(retval);
#undef ptr_a
#undef ptr_b
}
cJSON *LP_orderbookjson(struct LP_orderbookentry *op)
static int _revcmp_orderbook(const void *a,const void *b)
{
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 )
retval = 1;
else if ( ptr_b < ptr_a )
retval = -1;
else
{
#undef ptr_a
#undef ptr_b
#define ptr_a ((struct LP_orderbookentry *)a)->maxsatoshis
#define ptr_b ((struct LP_orderbookentry *)b)->maxsatoshis
if ( ptr_b > ptr_a )
return(-1);
else if ( ptr_b < ptr_a )
return(1);
}
// printf("%.8f vs %.8f -> %d\n",ptr_a,ptr_b,retval);
return(retval);
#undef ptr_a
#undef ptr_b
}
cJSON *LP_orderbookjson(char *symbol,struct LP_orderbookentry *op)
{
cJSON *item = cJSON_CreateObject();
if ( LP_pricevalid(op->price) > 0 )
{
jaddstr(item,"coin",symbol);
jaddstr(item,"address",op->coinaddr);
jaddnum(item,"price",op->price);
jaddnum(item,"volume",dstr(op->basesatoshis));
jaddbits256(item,"txid",op->txid);
jaddnum(item,"vout",op->vout);
jaddnum(item,"numutxos",op->numutxos);
jaddnum(item,"minvolume",dstr(op->minsatoshis));
jaddnum(item,"maxvolume",dstr(op->maxsatoshis));
jaddbits256(item,"pubkey",op->pubkey);
jaddnum(item,"age",op->age);
jaddnum(item,"age",time(NULL)-op->timestamp);
}
return(item);
}
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,int32_t age)
struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,double price,int32_t numutxos,uint64_t minsatoshis,uint64_t maxsatoshis,bits256 pubkey,uint32_t timestamp)
{
struct LP_orderbookentry *op;
if ( (op= calloc(1,sizeof(*op))) != 0 )
{
op->txid = txid;
op->vout = vout;
op->txid2 = txid2;
op->vout2 = vout2;
safecopy(op->coinaddr,address,sizeof(op->coinaddr));
op->price = price;
op->basesatoshis = basesatoshis;
op->numutxos = numutxos;
op->minsatoshis = minsatoshis;
op->maxsatoshis = maxsatoshis;
op->pubkey = pubkey;
op->age = age;
op->timestamp = timestamp;
}
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_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *rel,struct LP_orderbookentry *(**arrayp),int32_t num,int32_t cachednum,int32_t duration)
{
struct LP_utxoinfo *utxo,*tmp; struct LP_pubkeyinfo *pubp=0; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; uint32_t oldest; double price; int32_t baseid,relid; uint64_t basesatoshis,val,val2;
char coinaddr[64]; uint8_t zeroes[20]; struct LP_pubkeyinfo *pubp=0,*tmp; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; struct LP_address *ap; struct iguana_info *basecoin; uint32_t oldest; double price; int32_t baseid,relid,n; uint64_t minsatoshis,maxsatoshis;
if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 )
baseid = basepp->ind;
else return(num);
if ( (basecoin= LP_coinfind(base)) == 0 )
return(-1);
now = (uint32_t)time(NULL);
oldest = now - duration;
HASH_ITER(hh,LP_utxoinfos[1],utxo,tmp)
memset(zeroes,0,sizeof(zeroes));
HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp)
{
if ( pubp == 0 || bits256_cmp(pubp->pubkey,utxo->pubkey) != 0 )
pubp = LP_pubkeyfind(utxo->pubkey);
if ( pubp != 0 && pubp->numerrors >= LP_MAXPUBKEY_ERRORS )
if ( memcmp(zeroes,pubp->rmd160,sizeof(pubp->rmd160)) == 0 )
{
//printf("skip pubp since no rmd160\n");
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 && pubp->timestamp > oldest && pubp->timestamp <= now )
}
bitcoin_address(coinaddr,basecoin->taddr,basecoin->pubtype,pubp->rmd160,sizeof(pubp->rmd160));
minsatoshis = maxsatoshis = n = 0;
ap = 0;
if ( (price= pubp->matrix[baseid][relid]) > SMALLVAL )
{
if ( LP_orderbookfind(*arrayp,cachednum,utxo->payment.txid,utxo->payment.vout) < 0 )
if ( (ap= LP_addressfind(basecoin,coinaddr)) != 0 )
{
if ( LP_iseligible(&val,&val2,utxo->iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,utxo->deposit.txid,utxo->deposit.vout) == 0 )
continue;
n = LP_address_minmax(&minsatoshis,&maxsatoshis,ap);
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,now - pubp->timestamp)) != 0 )
{
*arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1));
(*arrayp)[num++] = op;
if ( LP_ismine(utxo) > 0 && utxo->T.lasttime == 0 )
LP_utxo_clientpublish(utxo);
minsatoshis *= price;
maxsatoshis *= price;
}
//printf("%s/%s %s n.%d ap->n.%d %.8f\n",base,rel,coinaddr,n,ap->n,dstr(ap->total));
}
if ( (op= LP_orderbookentry(coinaddr,base,rel,polarity > 0 ? price : 1./price,n,minsatoshis,maxsatoshis,pubp->pubkey,pubp->timestamp)) != 0 )
{
*arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1));
(*arrayp)[num++] = op;
}
}
//printf("pubp.(%s) %.8f %p\n",coinaddr,price,ap);
}
return(num);
}
char *LP_orderbook(char *base,char *rel,int32_t duration)
{
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;
uint32_t now,i; struct LP_priceinfo *basepp=0,*relpp=0; struct LP_orderbookentry **bids = 0,**asks = 0; cJSON *retjson,*array; struct iguana_info *basecoin,*relcoin; int32_t n,numbids=0,numasks=0,cachenumbids,cachenumasks,baseid,relid;
basecoin = LP_coinfind(base);
relcoin = LP_coinfind(rel);
if ( basecoin == 0 || relcoin == 0 )
return(clonestr("{\"error\":\"base or rel not added\"}"));
if ( (basepp= LP_priceinfofind(base)) == 0 || (relpp= LP_priceinfofind(rel)) == 0 )
return(clonestr("{\"error\":\"base or rel not added\"}"));
if ( duration <= 0 )
@ -679,6 +746,8 @@ char *LP_orderbook(char *base,char *rel,int32_t duration)
baseid = basepp->ind;
relid = relpp->ind;
now = (uint32_t)time(NULL);
basecoin->obooktime = now;
relcoin->obooktime = now;
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,duration);
@ -686,7 +755,7 @@ char *LP_orderbook(char *base,char *rel,int32_t duration)
retjson = cJSON_CreateObject();
array = cJSON_CreateArray();
if ( numbids > 1 )
qsort(bids,numbids,sizeof(*bids),_cmp_orderbook);
qsort(bids,numbids,sizeof(*bids),_revcmp_orderbook);
if ( numasks > 1 )
{
//for (i=0; i<numasks; i++)
@ -697,21 +766,29 @@ char *LP_orderbook(char *base,char *rel,int32_t duration)
// printf("%.8f ",asks[i]->price);
//printf("sorted asks.%d\n",numasks);
}
for (i=0; i<numbids; i++)
for (i=n=0; i<numbids; i++)
{
jaddi(array,LP_orderbookjson(bids[i]));
jaddi(array,LP_orderbookjson(rel,bids[i]));
if ( bids[i]->numutxos == 0 )//|| relcoin->electrum == 0 )
LP_address(relcoin,bids[i]->coinaddr), n++;
free(bids[i]);
bids[i] = 0;
}
if ( n > 0 && relcoin->lastmonitor > 3600 )
relcoin->lastmonitor -= 3600;
jadd(retjson,"bids",array);
jaddnum(retjson,"numbids",numbids);
array = cJSON_CreateArray();
for (i=0; i<numasks; i++)
for (i=n=0; i<numasks; i++)
{
jaddi(array,LP_orderbookjson(asks[i]));
jaddi(array,LP_orderbookjson(base,asks[i]));
if ( asks[i]->numutxos == 0 )//|| basecoin->electrum == 0 )
LP_address(basecoin,asks[i]->coinaddr), n++;
free(asks[i]);
asks[i] = 0;
}
if ( n > 0 && basecoin->lastmonitor > 3600 )
basecoin->lastmonitor -= 3600;
jadd(retjson,"asks",array);
jaddnum(retjson,"numasks",numasks);
jaddstr(retjson,"base",base);
@ -738,7 +815,7 @@ char *LP_pricestr(char *base,char *rel,double origprice)
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"method","postprice");
jaddbits256(retjson,"pubkey",LP_mypub25519);
jaddbits256(retjson,"pubkey",G.LP_mypub25519);
jaddstr(retjson,"base",base);
jaddstr(retjson,"rel",rel);
jaddnum(retjson,"price",price);
@ -915,9 +992,10 @@ void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price)
}
if ( (pubp= LP_pubkeyadd(pubkey)) != 0 )
{
if ( (rand() % 100) == 0 && fabs(pubp->matrix[basepp->ind][relpp->ind] - price) > SMALLVAL )
printf("PRICEFEED UPDATE.(%-6s/%6s) %12.8f %s %12.8f\n",base,rel,price,bits256_str(str,pubkey),1./price);
if ( fabs(pubp->matrix[basepp->ind][relpp->ind] - price) > SMALLVAL )
{
if ( (rand() % 5000) == 0 )
printf("PRICEFEED UPDATE.(%-6s/%6s) %12.8f %s %12.8f\n",base,rel,price,bits256_str(str,pubkey),1./price);
pubp->matrix[basepp->ind][relpp->ind] = price;
dxblend(&basepp->relvals[relpp->ind],price,0.9);
dxblend(&relpp->relvals[basepp->ind],1. / price,0.9);

723
iguana/exchanges/LP_remember.c

File diff suppressed because it is too large

459
iguana/exchanges/LP_rpc.c

@ -48,48 +48,37 @@ char *LP_isitme(char *destip,uint16_t destport)
} else return(0);
}
char *issue_LP_getpeers(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers,int32_t numutxos)
char *issue_LP_getpeers(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers)
{
char url[512],*retstr;
sprintf(url,"http://%s:%u/api/stats/getpeers?ipaddr=%s&port=%u&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,numpeers,numutxos);
sprintf(url,"http://%s:%u/api/stats/getpeers?ipaddr=%s&port=%u&numpeers=%d",destip,destport,ipaddr,port,numpeers);
retstr = LP_issue_curl("getpeers",destip,port,url);
//printf("%s -> getpeers.(%s)\n",destip,retstr);
return(retstr);
}
char *issue_LP_numutxos(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers,int32_t numutxos)
char *issue_LP_uitem(char *destip,uint16_t destport,char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t height,uint64_t value)
{
char url[512],*retstr;
sprintf(url,"http://%s:%u/api/stats/numutxos?ipaddr=%s&port=%u&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,numpeers,numutxos);
retstr = LP_issue_curl("numutxos",destip,port,url);
//printf("%s -> getpeers.(%s)\n",destip,retstr);
char url[512],*retstr,str[65];
if ( (retstr= LP_isitme(destip,destport)) != 0 )
return(retstr);
sprintf(url,"http://%s:%u/api/stats/uitem?coin=%s&coinaddr=%s&txid=%s&vout=%d&ht=%d&value=%llu",destip,destport,symbol,coinaddr,bits256_str(str,txid),vout,height,(long long)value);
retstr = LP_issue_curl("uitem",destip,destport,url);
//printf("uitem.(%s)\n",retstr);
return(retstr);
}
char *issue_LP_getutxos(char *destip,uint16_t destport,char *coin,int32_t lastn,char *ipaddr,uint16_t port,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&numpeers=%d&numutxos=%d",destip,destport,coin,lastn,ipaddr,port,numpeers,numutxos);
return(LP_issue_curl("getutxos",destip,destport,url));
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
}
char *issue_LP_clientgetutxos(char *destip,uint16_t destport,char *coin,int32_t lastn)
char *issue_LP_notify(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers,uint32_t sessionid,char *rmd160str,bits256 pub)
{
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);
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,int32_t numpeers,int32_t numutxos,uint32_t sessionid)
{
char url[512],*retstr;
char url[512],*retstr,str[65];
if ( (retstr= LP_isitme(destip,destport)) != 0 )
return(retstr);
sprintf(url,"http://%s:%u/api/stats/notify?ipaddr=%s&port=%u&numpeers=%d&numutxos=%d&session=%u",destip,destport,ipaddr,port,numpeers,numutxos,sessionid);
sprintf(url,"http://%s:%u/api/stats/notify?ipaddr=%s&port=%u&numpeers=%d&session=%u",destip,destport,ipaddr,port,numpeers,sessionid);
if ( rmd160str != 0 && bits256_nonz(pub) != 0 )
{
sprintf(url+strlen(url),"&rmd160=%s&pub=%s",rmd160str,bits256_str(str,pub));
//printf("SEND (%s)\n",url);
}
return(LP_issue_curl("notify",destip,destport,url));
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
}
@ -103,9 +92,19 @@ char *issue_LP_getprices(char *destip,uint16_t destport)
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
}
char *issue_LP_listunspent(char *destip,uint16_t destport,char *symbol,char *coinaddr)
{
char url[512];
sprintf(url,"http://%s:%u/api/stats/listunspent?coin=%s&address=%s",destip,destport,symbol,coinaddr);
//printf("listunspent.(%s)\n",url);
return(LP_issue_curl("listunspent",destip,destport,url));
}
char *LP_apicall(struct iguana_info *coin,char *method,char *params)
{
cJSON *retjson; char *retstr;
if ( coin == 0 )
return(0);
if ( coin->electrum != 0 )
{
if ( (retjson= electrum_submit(coin->symbol,coin->electrum,&retjson,method,params,LP_HTTP_TIMEOUT)) != 0 )
@ -125,6 +124,8 @@ cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params)
if ( coin != 0 )
{
//printf("issue.(%s, %s, %s, %s, %s)\n",coin->symbol,coin->serverport,coin->userpass,method,params);
if ( coin->electrum != 0 && (strcmp(method,"getblock") == 0 || strcmp(method,"paxprice") == 0 || strcmp(method,"getrawmempool") == 0) )
return(cJSON_Parse("{\"error\":\"illegal electrum call\"}"));
if ( coin->inactive == 0 || strcmp(method,"importprivkey") == 0 || strcmp(method,"validateaddress") == 0 )
{
if ( coin->electrum == 0 )
@ -141,6 +142,11 @@ cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params)
{
if ( (retjson= electrum_submit(coin->symbol,coin->electrum,&retjson,method,params,LP_HTTP_TIMEOUT)) != 0 )
{
if ( jobj(retjson,"error") != 0 )
{
free_json(retjson);
retjson = 0;
}
//printf("electrum %s.%s -> (%s)\n",method,params,jprint(retjson,0));
/*if ( (resultjson= jobj(retjson,"result")) != 0 )
{
@ -195,9 +201,10 @@ cJSON *LP_assethbla(char *assetid)
int32_t LP_getheight(struct iguana_info *coin)
{
cJSON *retjson; char *method = "getinfo"; int32_t height = coin->height;
cJSON *retjson; char *method = "getinfo"; int32_t height;
if ( coin == 0 )
return(-1);
height = coin->height;
if ( coin->electrum == 0 && time(NULL) > coin->heighttime+60 )
{
if ( strcmp(coin->symbol,"BTC") == 0 )
@ -214,7 +221,10 @@ int32_t LP_getheight(struct iguana_info *coin)
cJSON *LP_getmempool(char *symbol,char *coinaddr)
{
cJSON *array; struct iguana_info *coin = LP_coinfind(symbol);
cJSON *array; struct iguana_info *coin;
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
coin = LP_coinfind(symbol);
if ( coin == 0 || (coin->electrum != 0 && coinaddr == 0) )
return(cJSON_Parse("{\"error\":\"no native coin\"}"));
if ( coin->electrum == 0 )
@ -233,10 +243,14 @@ cJSON *LP_paxprice(char *fiat)
cJSON *LP_gettx(char *symbol,bits256 txid)
{
char buf[128],str[65],*hexstr; int32_t len; bits256 checktxid; cJSON *retjson; struct iguana_info *coin; struct iguana_msgtx msgtx; uint8_t *extraspace,*serialized;
struct iguana_info *coin; char buf[512],str[65]; cJSON *retjson;
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
coin = LP_coinfind(symbol);
if ( coin == 0 )
return(cJSON_Parse("{\"error\":\"no coin\"}"));
if ( bits256_nonz(txid) == 0 )
return(cJSON_Parse("{\"error\":\"null txid\"}"));
if ( coin->electrum == 0 )
{
sprintf(buf,"[\"%s\", 1]",bits256_str(str,txid));
@ -244,38 +258,41 @@ cJSON *LP_gettx(char *symbol,bits256 txid)
}
else
{
sprintf(buf,"[\"%s\"]",bits256_str(str,txid));
if ( (retjson= bitcoin_json(coin,"blockchain.transaction.get",buf)) != 0 )
{
hexstr = jprint(retjson,1);
if ( hexstr[0] == '"' && hexstr[strlen(hexstr)-1] == '"' )
hexstr[strlen(hexstr)-1] = 0;
if ( (len= is_hexstr(hexstr+1,0)) > 2 )
{
memset(&msgtx,0,sizeof(msgtx));
len = (int32_t)strlen(hexstr+1) >> 1;
serialized = malloc(len);
decode_hex(serialized,len,hexstr+1);
//printf("DATA.(%s)\n",hexstr+1);
extraspace = calloc(1,100000);
retjson = bitcoin_data2json(coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->height,&checktxid,&msgtx,extraspace,100000,serialized,len,0,0);
free(serialized);
free(extraspace);
//printf("TX.(%s) match.%d\n",jprint(retjson,0),bits256_cmp(txid,checktxid));
return(retjson);
} else printf("non-hex tx.(%s)\n",hexstr);
return(cJSON_Parse("{\"error\":\"non hex transaction\"}"));
} else printf("failed blockcjhain.transaction.get\n");
if ( (retjson= electrum_transaction(symbol,coin->electrum,&retjson,txid)) != 0 )
return(retjson);
else printf("failed blockchain.transaction.get %s %s\n",coin->symbol,buf);
return(cJSON_Parse("{\"error\":\"no transaction bytes\"}"));
}
}
cJSON *LP_gettxout(char *symbol,bits256 txid,int32_t vout)
cJSON *LP_gettxout_json(bits256 txid,int32_t vout,int32_t height,char *coinaddr,uint64_t value)
{
char buf[128],str[65],coinaddr[64],*hexstr; uint64_t value; uint8_t *serialized; cJSON *sobj,*addresses,*item,*array,*hexobj,*retjson=0; int32_t i,n,v,len; bits256 t; struct iguana_info *coin;
coin = LP_coinfind(symbol);
if ( coin == 0 )
cJSON *retjson,*addresses,*sobj;
retjson = cJSON_CreateObject();
jaddnum(retjson,"value",dstr(value));
jaddnum(retjson,"height",height);
jaddbits256(retjson,"txid",txid);
jaddnum(retjson,"vout",vout);
addresses = cJSON_CreateArray();
jaddistr(addresses,coinaddr);
sobj = cJSON_CreateObject();
jaddnum(sobj,"reqSigs",1);
jaddstr(sobj,"type","pubkey");
jadd(sobj,"addresses",addresses);
jadd(retjson,"scriptPubKey",sobj);
printf("GETTXOUT.(%s)\n",jprint(retjson,0));
return(retjson);
}
cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout)
{
char buf[128],str[65]; cJSON *item,*array,*vouts,*txobj,*retjson=0; int32_t i,v,n; bits256 t; struct iguana_info *coin; struct LP_transaction *tx; struct LP_address_utxo *up;
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
if ( (coin= LP_coinfind(symbol)) == 0 )
return(cJSON_Parse("{\"error\":\"no coin\"}"));
if ( bits256_nonz(txid) == 0 )
return(cJSON_Parse("{\"error\":\"null txid\"}"));
if ( coin->electrum == 0 )
{
sprintf(buf,"[\"%s\", %d, true]",bits256_str(str,txid),vout);
@ -283,87 +300,56 @@ cJSON *LP_gettxout(char *symbol,bits256 txid,int32_t vout)
}
else
{
sprintf(buf,"[\"%s\"]",bits256_str(str,txid));
if ( (hexobj= bitcoin_json(coin,"blockchain.transaction.get",buf)) != 0 )
if ( (tx= LP_transactionfind(coin,txid)) != 0 && vout < tx->numvouts )
{
hexstr = jprint(hexobj,1);
if ( hexstr[0] == '"' && hexstr[strlen(hexstr)-1] == '"' )
hexstr[strlen(hexstr)-1] = 0;
if ( (len= is_hexstr(hexstr+1,0)) > 2 )
if ( tx->outpoints[vout].spendheight > 0 )
return(0);
return(LP_gettxout_json(txid,vout,tx->height,tx->outpoints[vout].coinaddr,tx->outpoints[vout].value));
}
if ( coinaddr[0] == 0 )
{
if ( (txobj= electrum_transaction(symbol,coin->electrum,&txobj,txid)) != 0 )
{
len = (int32_t)strlen(hexstr+1) >> 1;
serialized = malloc(len);
decode_hex(serialized,len,hexstr+1);
LP_swap_coinaddr(coin,coinaddr,&value,serialized,len,vout);
//printf("HEX.(%s) len.%d %s %.8f\n",hexstr+1,len,coinaddr,dstr(value));
if ( (array= electrum_address_listunspent(coin->symbol,0,&array,coinaddr)) != 0 )
if ( (vouts= jarray(&n,txobj,"vout")) != 0 && n > 0 )
LP_destaddr(coinaddr,jitem(vouts,vout));
free_json(txobj);
}
}
if ( coinaddr[0] != 0 )
{
if ( (up= LP_address_utxofind(coin,coinaddr,txid,vout)) != 0 )
{
if ( up->spendheight > 0 )
return(0);
return(LP_gettxout_json(txid,vout,up->U.height,coinaddr,up->U.value));
}
if ( (array= electrum_address_listunspent(coin->symbol,0,&array,coinaddr)) != 0 )
{
//printf("array.(%s)\n",jprint(array,0));
if ( array != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{
//printf("array.(%s)\n",jprint(array,0));
if ( array != 0 && (n= cJSON_GetArraySize(array)) > 0 )
for (i=0; i<n; i++)
{
for (i=0; i<n; i++)
item = jitem(array,i);
t = jbits256(item,"tx_hash");
v = jint(item,"tx_pos");
if ( v == vout && bits256_cmp(t,txid) == 0 )
{
item = jitem(array,i);
t = jbits256(item,"tx_hash");
v = jint(item,"tx_pos");
if ( v == vout && bits256_cmp(t,txid) == 0 )
{
retjson = cJSON_CreateObject();
/*{
"bestblock": "002f7bbe3973b735f535d472501962e86ce8dbc76c73ac5a310a905931b907fa",
"confirmations": 7,
"value": 2013.10431750,
"scriptPubKey": {
"asm": "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828 OP_CHECKSIG",
"hex": "2103b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828ac",
"reqSigs": 1,
"type": "pubkey",
"addresses": [
"RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc"
]
},
"version": 1,
"coinbase": false
}*/
if ( value != j64bits(item,"value") )
printf("LP_gettxout: value %llu != %llu\n",(long long)value,(long long)j64bits(item,"value"));
jaddnum(retjson,"value",dstr(value));
jaddbits256(retjson,"txid",t);
jaddnum(retjson,"vout",v);
addresses = cJSON_CreateArray();
jaddistr(addresses,coinaddr);
sobj = cJSON_CreateObject();
jaddnum(sobj,"reqSigs",1);
jaddstr(sobj,"type","pubkey");
jadd(sobj,"addresses",addresses);
jadd(retjson,"scriptPubKey",sobj);
printf("GETTXOUT.(%s)\n",jprint(retjson,0));
break;
}
retjson = LP_gettxout_json(txid,vout,jint(item,"height"),coinaddr,j64bits(item,"value"));
break;
}
}
free_json(array);
}
free_json(array);
if ( retjson != 0 )
return(retjson);
}
return(retjson);
}
printf("couldnt find %s/v%d\n",bits256_str(str,txid),vout);
return(cJSON_Parse("{\"error\":\"couldnt get tx\"}"));
}
}
cJSON *LP_listunspent(char *symbol,char *coinaddr)
{
char buf[128]; cJSON *retjson; struct iguana_info *coin = LP_coinfind(symbol);
//printf("LP_listunspent.(%s %s)\n",symbol,coinaddr);
if ( coin == 0 || coin->inactive != 0 )
return(cJSON_Parse("{\"error\":\"no coin\"}"));
if ( coin->electrum == 0 )
{
sprintf(buf,"[0, 99999999, [\"%s\"]]",coinaddr);
return(bitcoin_json(coin,"listunspent",buf));
} else return(electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr));
}
/*cJSON *LP_listtransactions(char *symbol,char *coinaddr,int32_t count,int32_t skip)
{
char buf[128]; struct iguana_info *coin = LP_coinfind(symbol);
@ -377,7 +363,10 @@ cJSON *LP_listunspent(char *symbol,char *coinaddr)
cJSON *LP_validateaddress(char *symbol,char *address)
{
char buf[512],coinaddr[64],checkaddr[64],script[128]; int32_t i; uint8_t rmd160[20],addrtype; cJSON *retjson; struct iguana_info *coin = LP_coinfind(symbol);
char buf[512],coinaddr[64],checkaddr[64],script[128]; int32_t i; uint8_t rmd160[20],addrtype; cJSON *retjson; struct iguana_info *coin;
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
coin = LP_coinfind(symbol);
if ( coin == 0 )
return(cJSON_Parse("{\"error\":\"no coin\"}"));
if ( coin != 0 && coin->electrum != 0 )
@ -396,9 +385,8 @@ cJSON *LP_validateaddress(char *symbol,char *address)
strcat(script,"88ac");
jaddstr(retjson,"scriptPubKey",script);
}
bitcoin_address(coinaddr,coin->taddr,coin->pubtype,LP_myrmd160,20);
if ( strcmp(address,coinaddr) == 0 )
jadd(retjson,"ismine",cJSON_CreateTrue());
bitcoin_address(coinaddr,coin->taddr,coin->pubtype,G.LP_myrmd160,20);
jadd(retjson,"ismine",strcmp(address,coin->smartaddr) == 0 ? cJSON_CreateTrue() : cJSON_CreateFalse());
jadd(retjson,"iswatchonly",cJSON_CreateFalse());
jadd(retjson,"isscript",addrtype == coin->p2shtype ? cJSON_CreateTrue() : cJSON_CreateFalse());
return(retjson);
@ -410,10 +398,94 @@ cJSON *LP_validateaddress(char *symbol,char *address)
}
}
int32_t LP_address_ismine(char *symbol,char *address)
{
int32_t doneflag = 0; cJSON *retjson;
if ( symbol == 0 || symbol[0] == 0 )
return(0);
if ( (retjson= LP_validateaddress(symbol,address)) != 0 )
{
if ( jobj(retjson,"ismine") != 0 && is_cJSON_True(jobj(retjson,"ismine")) != 0 )
{
doneflag = 1;
//printf("%s ismine (%s)\n",address,jprint(retjson,0));
}
//printf("%s\n",jprint(retjson,0));
free_json(retjson);
}
return(doneflag);
}
cJSON *LP_listunspent(char *symbol,char *coinaddr)
{
char buf[128]; cJSON *retjson; struct iguana_info *coin;
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
coin = LP_coinfind(symbol);
//printf("LP_listunspent.(%s %s)\n",symbol,coinaddr);
if ( coin == 0 || coin->inactive != 0 )
return(cJSON_Parse("{\"error\":\"no coin\"}"));
if ( coin->electrum == 0 )
{
if ( LP_address_ismine(symbol,coinaddr) > 0 )
{
sprintf(buf,"[0, 99999999, [\"%s\"]]",coinaddr);
return(bitcoin_json(coin,"listunspent",buf));
} else return(LP_address_utxos(coin,coinaddr,0));
} else return(electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr));
}
int32_t LP_listunspent_issue(char *symbol,char *coinaddr)
{
struct iguana_info *coin; int32_t n = 0; cJSON *retjson=0; char *retstr=0,destip[64]; uint16_t destport;
if ( symbol == 0 || symbol[0] == 0 )
return(0);
if ( (coin= LP_coinfind(symbol)) != 0 )
{
if ( coin->electrum != 0 )
{
if ( (retjson= electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr)) != 0 )
{
n = cJSON_GetArraySize(retjson);
//printf("LP_listunspent_issue.%s %s.%d %s\n",symbol,coinaddr,n,jprint(retjson,0));
}
}
else
{
if ( strcmp(coin->smartaddr,coinaddr) == 0 )
{
retjson = LP_listunspent(symbol,coinaddr);
//printf("SELF_LISTUNSPENT.(%s %s)\n",symbol,coinaddr);
}
else if ( (destport= LP_randpeer(destip)) > 0 )
{
retstr = issue_LP_listunspent(destip,destport,symbol,coinaddr);
retjson = cJSON_Parse(retstr);
} else printf("LP_listunspent_issue couldnt get a random peer?\n");
if ( retjson != 0 )
{
n = cJSON_GetArraySize(retjson);
if ( electrum_process_array(coin,0,coinaddr,retjson) != 0 )
{
//LP_postutxos(symbol,coinaddr); // might be good to not saturate
}
}
}
//printf("issue listunspent %s (%s)\n",coinaddr,jprint(retjson,0));
if ( retjson != 0 )
free_json(retjson);
if ( retstr != 0 )
free(retstr);
}
return(n);
}
cJSON *LP_importprivkey(char *symbol,char *wifstr,char *label,int32_t flag)
{
static void *ctx;
char buf[512],address[64]; cJSON *retjson; struct iguana_info *coin; int32_t doneflag = 0;
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
coin = LP_coinfind(symbol);
if ( coin == 0 )
return(cJSON_Parse("{\"error\":\"no coin\"}"));
@ -443,16 +515,19 @@ cJSON *LP_importprivkey(char *symbol,char *wifstr,char *label,int32_t flag)
int32_t LP_importaddress(char *symbol,char *address)
{
char buf[1024],*retstr; cJSON *validatejson,*retjson; int32_t isvalid=0,doneflag = 0; struct iguana_info *coin = LP_coinfind(symbol);
char buf[1024],*retstr; cJSON *validatejson; int32_t isvalid=0,doneflag = 0; struct iguana_info *coin;
if ( symbol == 0 || symbol[0] == 0 )
return(-2);
coin = LP_coinfind(symbol);
if ( coin == 0 )
return(-2);
if ( coin->electrum != 0 )
{
if ( (retjson= electrum_address_subscribe(symbol,coin->electrum,&retjson,address)) != 0 )
/*if ( (retjson= electrum_address_subscribe(symbol,coin->electrum,&retjson,address)) != 0 )
{
printf("importaddress.(%s) -> %s\n",address,jprint(retjson,0));
free_json(retjson);
}
}*/
return(0);
}
else
@ -480,37 +555,54 @@ int32_t LP_importaddress(char *symbol,char *address)
}
}
double LP_getestimatedrate(struct iguana_info *coin)
double _LP_getestimatedrate(struct iguana_info *coin)
{
char buf[512],*retstr; double rate = 0.00000020;
if ( coin == 0 )
return(0.0001);
if ( (strcmp(coin->symbol,"BTC") == 0 || coin->txfee == 0) )
char buf[512],*retstr; cJSON *errjson; double rate = 0.00000020;
if ( coin->rate < 0. || time(NULL) > coin->ratetime+30 )
{
if ( coin->rate == 0. || time(NULL) > coin->ratetime+600 )
sprintf(buf,"[%d]",strcmp(coin->symbol,"BTC") == 0 ? 6 : 2);
if ( (retstr= LP_apicall(coin,coin->electrum==0?"estimatefee" : "blockchain.estimatefee",buf)) != 0 )
{
sprintf(buf,"[%d]",3);
if ( (retstr= LP_apicall(coin,coin->electrum==0?"estimatefee" : "blockchain.estimatefee",buf)) != 0 )
if ( retstr[0] == '{' && (errjson= cJSON_Parse(retstr)) != 0 )
{
if ( retstr[0] != '-' )
{
rate = atof(retstr) / 1024.;
if ( rate < 0.00000020 )
rate = 0.00000020;
coin->rate = rate;
coin->ratetime = (uint32_t)time(NULL);
printf("estimated rate.(%s) %s -> %.8f\n",coin->symbol,retstr,rate);
}
free(retstr);
if ( jobj(errjson,"error") != 0 )
rate = 0.;
free_json(errjson);
}
} else rate = coin->rate;
} else return((double)coin->txfee / LP_AVETXSIZE);
return(SATOSHIDEN * rate);
else if ( retstr[0] != '-' )
{
rate = atof(retstr) / 1024.;
if ( rate < 0.00000020 )
rate = 0.00000020;
rate *= 1.1;
if ( coin->electrum != 0 )
rate *= 1.667;
if ( fabs(rate - coin->rate) > SMALLVAL )
printf("t%u estimated rate.(%s) (%s) -> %.8f %.8f\n",coin->ratetime,coin->symbol,retstr,rate,coin->rate);
coin->rate = rate;
coin->ratetime = (uint32_t)time(NULL);
}
free(retstr);
}
} else rate = coin->rate;
return(rate);
}
double LP_getestimatedrate(struct iguana_info *coin)
{
double rate = 0.00000020;
if ( coin == 0 )
return(rate);
if ( (rate= _LP_getestimatedrate(coin)) <= 0. )
rate = dstr(coin->txfee) / LP_AVETXSIZE;
return(rate);
}
char *LP_sendrawtransaction(char *symbol,char *signedtx)
{
cJSON *array; char *paramstr,*tmpstr,*retstr=0; int32_t n; cJSON *retjson; struct iguana_info *coin;
cJSON *array,*errobj; char *paramstr,*tmpstr,*retstr=0; int32_t n,alreadyflag = 0; cJSON *retjson; struct iguana_info *coin;
if ( symbol == 0 || symbol[0] == 0 )
return(0);
coin = LP_coinfind(symbol);
if ( coin == 0 )
return(0);
@ -528,14 +620,27 @@ char *LP_sendrawtransaction(char *symbol,char *signedtx)
if ( (retjson= electrum_sendrawtransaction(symbol,coin->electrum,&retjson,signedtx)) != 0 )
{
retstr = jprint(retjson,1);
printf("electrum sendrawtx.(%s) -> %s\n",signedtx,retstr);
n = (int32_t)strlen(retstr);
if ( retstr[0] == '"' && retstr[n-1] == '"' )
//electrum sendrawtx (the transaction was rejected by network rules.\n\ntransaction already in block chain)
if ( strstr(retstr,"already in block") != 0 )
alreadyflag = 1;
//printf("electrum sendrawtx.(%s) -> %s already.%d\n",signedtx,retstr,alreadyflag);
if ( alreadyflag != 0 )
{
errobj = cJSON_CreateObject();
jaddstr(errobj,"error","rejected");
jaddnum(errobj,"code",-27);
retstr = jprint(errobj,1);
}
else
{
retstr[n-1] = 0;
tmpstr = clonestr(retstr+1);
free(retstr);
retstr = tmpstr;
n = (int32_t)strlen(retstr);
if ( retstr[0] == '"' && retstr[n-1] == '"' )
{
retstr[n-1] = 0;
tmpstr = clonestr(retstr+1);
free(retstr);
retstr = tmpstr;
}
}
}
}
@ -544,7 +649,10 @@ char *LP_sendrawtransaction(char *symbol,char *signedtx)
char *LP_signrawtx(char *symbol,bits256 *signedtxidp,int32_t *completedp,cJSON *vins,char *rawtx,cJSON *privkeys,struct vin_info *V)
{
cJSON *array,*json,*retjson; int32_t len; uint8_t *data; char str[65],*paramstr,*retstr,*hexstr,*signedtx=0; struct iguana_msgtx msgtx; struct iguana_info *coin = LP_coinfind(symbol);
cJSON *array,*json,*retjson; int32_t len; uint8_t *data; char str[65],*paramstr,*retstr,*hexstr,*signedtx=0; struct iguana_msgtx msgtx; struct iguana_info *coin;
if ( symbol == 0 || symbol[0] == 0 )
return(0);
coin = LP_coinfind(symbol);
memset(signedtxidp,0,sizeof(*signedtxidp));
*completedp = 0;
if ( coin == 0 )
@ -594,9 +702,10 @@ char *LP_signrawtx(char *symbol,bits256 *signedtxidp,int32_t *completedp,cJSON *
signedtx = calloc(1,len+1);
strcpy(signedtx,hexstr);
*completedp = is_cJSON_True(jobj(json,"complete"));
data = malloc(len >> 1);
decode_hex(data,len>>1,hexstr);
*signedtxidp = bits256_doublesha256(0,data,len >> 1);
len >>= 1;
data = malloc(len);
decode_hex(data,len,hexstr);
*signedtxidp = bits256_doublesha256(0,data,len);
}
//else
printf("%s signrawtransaction.(%s) params.(%s)\n",coin->symbol,retstr,paramstr);
@ -610,7 +719,10 @@ char *LP_signrawtx(char *symbol,bits256 *signedtxidp,int32_t *completedp,cJSON *
cJSON *LP_getblock(char *symbol,bits256 txid)
{
char buf[128],str[65]; struct iguana_info *coin = LP_coinfind(symbol);
char buf[128],str[65]; struct iguana_info *coin;
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
coin = LP_coinfind(symbol);
if ( coin == 0 || coin->electrum != 0 )
return(cJSON_Parse("{\"error\":\"no native coin\"}"));
sprintf(buf,"[\"%s\"]",bits256_str(str,txid));
@ -621,6 +733,8 @@ cJSON *LP_getblock(char *symbol,bits256 txid)
uint64_t LP_txfee(char *symbol)
{
uint64_t txfee = 0;
if ( symbol == 0 || symbol[0] == 0 )
return(LP_MIN_TXFEE);
if ( strcmp(symbol,"BTC") != 0 )
txfee = LP_MIN_TXFEE;
return(txfee);
@ -628,7 +742,10 @@ uint64_t LP_txfee(char *symbol)
char *LP_blockhashstr(char *symbol,int32_t height)
{
cJSON *array; char *paramstr,*retstr; struct iguana_info *coin = LP_coinfind(symbol);
cJSON *array; char *paramstr,*retstr; struct iguana_info *coin;
if ( symbol == 0 || symbol[0] == 0 )
return(0);
coin = LP_coinfind(symbol);
if ( coin == 0 || coin->electrum != 0 )
return(0);
array = cJSON_CreateArray();
@ -641,7 +758,10 @@ char *LP_blockhashstr(char *symbol,int32_t height)
cJSON *LP_getblockhashstr(char *symbol,char *blockhashstr)
{
char buf[128]; struct iguana_info *coin = LP_coinfind(symbol);
char buf[128]; struct iguana_info *coin;
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
coin = LP_coinfind(symbol);
if ( coin == 0 || coin->electrum != 0 )
return(cJSON_Parse("{\"error\":\"no native coin daemon\"}"));
sprintf(buf,"[\"%s\"]",blockhashstr);
@ -650,7 +770,10 @@ cJSON *LP_getblockhashstr(char *symbol,char *blockhashstr)
cJSON *LP_blockjson(int32_t *heightp,char *symbol,char *blockhashstr,int32_t height)
{
cJSON *json = 0; int32_t flag = 0; struct iguana_info *coin = LP_coinfind(symbol);
cJSON *json = 0; int32_t flag = 0; struct iguana_info *coin;
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
coin = LP_coinfind(symbol);
if ( coin == 0 || coin->electrum != 0 )
{
printf("unexpected electrum path for %s\n",symbol);

111
iguana/exchanges/LP_scan.c

@ -21,42 +21,31 @@
int32_t LP_blockinit(struct iguana_info *coin,int32_t height)
{
int32_t i,j,iter,numtx,checkht=-1; cJSON *blockobj,*txs; bits256 txid; struct LP_transaction *tx;
int32_t i,iter,numtx,checkht=-1; cJSON *blockobj,*txs,*txobj; bits256 txid; struct LP_transaction *tx;
if ( (blockobj= LP_blockjson(&checkht,coin->symbol,0,height)) != 0 && checkht == height )
{
if ( (txs= jarray(&numtx,blockobj,"tx")) != 0 )
{
for (iter=0; iter<2; iter++)
for (i=0; i<numtx; i++)
{
txid = jbits256i(txs,i);
if ( (tx= LP_transactionfind(coin,txid)) != 0 )
txobj = 0;
for (i=0; i<numtx; i++)
{
if ( tx->height == 0 )
tx->height = height;
else if ( tx->height != height )
txid = jbits256i(txs,i);
if ( (tx= LP_transactionfind(coin,txid)) != 0 )
{
printf("LP_blockinit: tx->height %d != %d\n",tx->height,height);
tx->height = height;
}
if ( iter == 1 )
for (j=0; j<10; j++)
if ( tx->height == 0 )
tx->height = height;
else if ( tx->height != height )
{
if (LP_transactioninit(coin,txid,iter) == 0 )
break;
printf("transaction ht.%d init error.%d, pause\n",height,j);
sleep(1);
printf("LP_blockinit: tx->height %d != %d\n",tx->height,height);
tx->height = height;
}
}
else
{
for (j=0; j<10; j++)
{
if (LP_transactioninit(coin,txid,iter) == 0 )
break;
printf("transaction ht.%d init error.%d, pause\n",height,j);
sleep(1);
}
if ( iter == 1 )
txobj = LP_transactioninit(coin,txid,iter,0);
} else txobj = LP_transactioninit(coin,txid,iter,0);
if ( txobj != 0 )
free_json(txobj), txobj = 0;
}
}
}
@ -184,6 +173,7 @@ cJSON *LP_snapshot(struct iguana_info *coin,int32_t height)
}
}
portable_mutex_lock(&coin->txmutex);
portable_mutex_lock(&coin->addrmutex);
HASH_ITER(hh,coin->addresses,ap,atmp)
{
ap->balance = 0;
@ -220,6 +210,7 @@ cJSON *LP_snapshot(struct iguana_info *coin,int32_t height)
}
}
HASH_SORT(coin->addresses,sort_balance);
portable_mutex_unlock(&coin->addrmutex);
portable_mutex_unlock(&coin->txmutex);
printf("%s balance %.8f at height.%d\n",coin->symbol,dstr(balance),height);
array = cJSON_CreateArray();
@ -421,7 +412,7 @@ int32_t LP_spendsearch(bits256 *spendtxidp,int32_t *indp,char *symbol,bits256 se
int32_t LP_mempoolscan(char *symbol,bits256 searchtxid)
{
int32_t i,n; cJSON *array; bits256 txid; struct iguana_info *coin; struct LP_transaction *tx;
int32_t i,n; cJSON *array,*txobj; bits256 txid; struct iguana_info *coin; struct LP_transaction *tx;
if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 || coin->electrum != 0 )
return(-1);
if ( (array= LP_getmempool(symbol,0)) != 0 )
@ -433,8 +424,10 @@ int32_t LP_mempoolscan(char *symbol,bits256 searchtxid)
txid = jbits256i(array,i);
if ( (tx= LP_transactionfind(coin,txid)) == 0 )
{
LP_transactioninit(coin,txid,0);
LP_transactioninit(coin,txid,1);
txobj = LP_transactioninit(coin,txid,0,0);
txobj = LP_transactioninit(coin,txid,1,txobj);
if ( txobj != 0 )
free_json(txobj);
}
if ( bits256_cmp(txid,searchtxid) == 0 )
{
@ -448,49 +441,65 @@ int32_t LP_mempoolscan(char *symbol,bits256 searchtxid)
return(-1);
}
int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t duration)
int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t duration)
{
struct iguana_info *coin; struct LP_transaction *tx; cJSON *array,*item; uint32_t expiration,i,n;
struct iguana_info *coin; cJSON *array,*item; uint32_t expiration,i,n; int32_t numconfirms = -1;
if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 )
{
printf("LP_waitmempool missing coin.%p or inactive\n",coin);
return(-1);
}
expiration = (uint32_t)time(NULL) + duration;
while ( 1 )
{
if ( coin->electrum == 0 )
{
if ( LP_mempoolscan(symbol,txid) >= 0 )
return(0);
}
if ( LP_gettx_presence(symbol,txid) != 0 )
numconfirms = 0;
else
{
if ( (tx= LP_transactionfind(coin,txid)) != 0 && tx->height >= 0 )
if ( coin->electrum == 0 )
{
char str[65]; printf("LP_waitmempool found %s %s\n",symbol,bits256_str(str,txid));
return(tx->height);
if ( LP_mempoolscan(symbol,txid) >= 0 )
numconfirms = 0;
}
if ( (array= electrum_address_getmempool(symbol,coin->electrum,&array,coinaddr)) != 0 )
else
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
if ( (array= electrum_address_getmempool(symbol,coin->electrum,&array,coinaddr)) != 0 )
{
for (i=0; i<n; i++)
char str[65]; printf("check %s mempool.(%s)\n",bits256_str(str,txid),jprint(array,0));
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
item = jitem(array,i);
if ( bits256_cmp(txid,jbits256(item,"tx_hash")) == 0 )
for (i=0; i<n; i++)
{
free(array);
char str[65]; printf("found %s %s in mempool\n",symbol,bits256_str(str,txid));
return(0);
item = jitem(array,i);
if ( bits256_cmp(txid,jbits256(item,"tx_hash")) == 0 )
{
char str[65]; printf("found %s %s in mempool\n",symbol,bits256_str(str,txid));
numconfirms = 0;
break;
}
}
}
free(array);
}
LP_listunspent_issue(coin->symbol,coinaddr);
struct LP_address_utxo *up;
if ( (up= LP_address_utxofind(coin,coinaddr,txid,vout)) != 0 )
{
char str[65]; printf("address_utxofind found confirmed %s %s %s ht.%d vs %d\n",symbol,coinaddr,bits256_str(str,txid),up->U.height,coin->height);
if ( coin->electrum != 0 && (array= electrum_address_gethistory(symbol,coin->electrum,&array,coinaddr)) != 0 )
free_json(array);
if ( coin->height >= up->U.height )
numconfirms = (coin->height - up->U.height + 1);
}
free(array);
}
}
if ( time(NULL) < expiration )
if ( time(NULL) > expiration || numconfirms >= 0 )
break;
usleep(500000);
sleep(10);
}
return(-1);
//if ( numconfirms <= 0 )
// numconfirms = LP_numconfirms(symbol,coinaddr,txid,vout,1); // no, no recursion occurs!
return(numconfirms);
}
int32_t LP_mempool_vinscan(bits256 *spendtxidp,int32_t *spendvinp,char *symbol,char *coinaddr,bits256 searchtxid,int32_t searchvout,bits256 searchtxid2,int32_t searchvout2)

311
iguana/exchanges/LP_socket.c

@ -26,7 +26,7 @@
#include <WinSock2.h>
#endif
#define ELECTRUM_TIMEOUT 3
#define ELECTRUM_TIMEOUT 5
int32_t LP_socket(int32_t bindflag,char *hostname,uint16_t port)
{
@ -198,7 +198,7 @@ int32_t LP_socketsend(int32_t sock,uint8_t *serialized,int32_t len)
flags = MSG_NOSIGNAL;
#endif
remains = len;
while ( remains > 0 )
while ( sock >= 0 && remains > 0 )
{
if ( (numsent= (int32_t)send(sock,serialized,remains,flags)) < 0 )
{
@ -225,7 +225,7 @@ int32_t LP_socketsend(int32_t sock,uint8_t *serialized,int32_t len)
int32_t LP_socketrecv(int32_t sock,uint8_t *recvbuf,int32_t maxlen)
{
int32_t recvlen = -1;
while ( 1 )
while ( sock >= 0 )
{
if ( (recvlen= (int32_t)recv(sock,recvbuf,maxlen,0)) < 0 )
{
@ -243,6 +243,7 @@ int32_t LP_socketrecv(int32_t sock,uint8_t *recvbuf,int32_t maxlen)
struct electrum_info
{
queue_t sendQ,pendingQ;
struct electrum_info *prev;
int32_t bufsize,sock,*heightp;
struct iguana_info *coin;
uint32_t stratumid,lasttime,pending,*heighttimep;
@ -252,16 +253,6 @@ struct electrum_info
} *Electrums[8192];
int32_t Num_electrums;
// purge timedout
/*
if ( (retjson= electrum_address_listunspent(symbol,ep,&retjson,addr)) != 0 )
you can call it like the above, where symbol is the coin, ep is the electrum server info pointer, the 0 is a callback ptr where 0 means to block till it is done
all the API calls have the same three args
if the callback ptr is &retjson, then on completion it will put the cJSON *ptr into it, so to spawn a bunch of calls you need to call with symbol,ep,&retjsons[i],...
default timeout is set to 2 seconds, not sure if that is enough, on each receive from any server, requests that are timeout are purged (and if a callback set, will just return and "error" timeout JSON
a null value for ep will make it choose a random server for that coin
*/
struct electrum_info *electrum_server(char *symbol,struct electrum_info *ep)
{
struct electrum_info *rbuf[128],*recent_ep; uint32_t recent,mostrecent = 0; int32_t i,n = 0;
@ -304,41 +295,67 @@ struct electrum_info *electrum_server(char *symbol,struct electrum_info *ep)
return(ep);
}
void electrum_process_array(struct iguana_info *coin,cJSON *array)
int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep,char *coinaddr,cJSON *array)
{
int32_t i,v,n; char str[65]; uint64_t value; bits256 txid; cJSON *item; struct LP_transaction *tx;
int32_t i,v,n,ht,flag = 0; char str[65]; uint64_t value; bits256 txid; cJSON *item,*retjson,*txobj; struct LP_transaction *tx;
if ( array != 0 && coin != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{
//printf("PROCESS %s/%s %s num.%d\n",coin->symbol,ep!=0?ep->symbol:"nanolistunspent",coinaddr,n);
for (i=0; i<n; i++)
{
item = jitem(array,i);
txid = jbits256(item,"tx_hash");
if ( coin->electrum == 0 )
{
txid = jbits256(item,"txid");
v = jint(item,"vout");
value = LP_value_extract(item,0);
ht = LP_txheight(coin,txid);
if ( (retjson= LP_gettxout(coin->symbol,coinaddr,txid,v)) != 0 )
free_json(retjson);
else
{
//printf("external unspent has no gettxout\n");
flag += LP_address_utxoadd(coin,coinaddr,txid,v,value,0,1);
}
}
else
{
txid = jbits256(item,"tx_hash");
v = jint(item,"tx_pos");
value = j64bits(item,"value");
ht = jint(item,"height");
}
if ( bits256_nonz(txid) == 0 )
continue;
if ( (tx= LP_transactionfind(coin,txid)) == 0 )
{
LP_transactioninit(coin,txid,0);
LP_transactioninit(coin,txid,1);
txobj = LP_transactioninit(coin,txid,0,0);
LP_transactioninit(coin,txid,1,txobj);
free_json(txobj);
tx = LP_transactionfind(coin,txid);
}
if ( tx != 0 )
{
if (tx->height <= 0 )
{
tx->height = jint(item,"height");
printf(">>>>>>>>>> set %s <- height %d\n",bits256_str(str,txid),tx->height);
tx->height = ht;
//printf("%s %s >>>>>>>>>> set %s <- height %d\n",coin->symbol,coinaddr,bits256_str(str,txid),tx->height);
}
if ( jobj(item,"tx_pos") != 0 && jobj(item,"value") != 0 && (v= jint(item,"tx_pos")) >= 0 && v < tx->numvouts )
if ( v >= 0 && v < tx->numvouts )
{
value = j64bits(item,"value");
if ( tx->outpoints[v].value == 0 && value != tx->outpoints[v].value )
{
printf(">>>>>>>>>> set %s/v%d <- %.8f vs %.8f\n",bits256_str(str,txid),v,dstr(value),dstr(tx->outpoints[v].value));
printf("%s %s >>>>>>>>>> set %s/v%d <- %.8f vs %.8f\n",coin->symbol,coinaddr,bits256_str(str,txid),v,dstr(value),dstr(tx->outpoints[v].value));
tx->outpoints[v].value = value;
}
}
printf("v.%d numvouts.%d %.8f (%s)\n",jint(item,"tx_pos"),tx->numvouts,dstr(tx->outpoints[jint(item,"tx_pos")].value),jprint(item,0));
}
if ( value != 0 || tx->height > 0 )
flag += LP_address_utxoadd(coin,coinaddr,txid,v,value,tx->height,-1);
//printf("v.%d numvouts.%d %.8f (%s)\n",v,tx->numvouts,dstr(tx->outpoints[jint(item,"tx_pos")].value),jprint(item,0));
} //else printf("cant find tx\n");
}
}
return(flag);
}
cJSON *electrum_submit(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *method,char *params,int32_t timeout)
@ -347,31 +364,33 @@ cJSON *electrum_submit(char *symbol,struct electrum_info *ep,cJSON **retjsonp,ch
char stratumreq[16384]; uint32_t expiration; struct stritem *sitem;
if ( ep == 0 )
ep = electrum_server(symbol,0);
if ( ep != 0 && retjsonp != 0 )
while ( ep != 0 )
{
*retjsonp = 0;
if ( strcmp(method,"getrawmempool") == 0 )
{
*retjsonp = cJSON_Parse("{\"error\":\"unsupported method\"}");
return(*retjsonp);
}
sprintf(stratumreq,"{ \"jsonrpc\":\"2.0\", \"id\": %u, \"method\":\"%s\", \"params\": %s }\n",ep->stratumid,method,params);
ep->buf[0] = 0;
sitem = (struct stritem *)queueitem(stratumreq);
sitem->expiration = timeout;
sitem->DL.type = ep->stratumid++;
sitem->retptrp = (void **)retjsonp;
queue_enqueue("sendQ",&ep->sendQ,&sitem->DL);
expiration = (uint32_t)time(NULL) + timeout + 1;
while ( *retjsonp == 0 && time(NULL) <= expiration )
usleep(10000);
if ( *retjsonp == 0 )
if ( ep != 0 && ep->sock >= 0 && retjsonp != 0 )
{
printf("unexpected timeout with null retjson: %s %s\n",method,params);
*retjsonp = cJSON_Parse("{\"error\":\"timeout\"}");
}
return(*retjsonp);
} else printf("couldnt find electrum server for (%s %s) or no retjsonp.%p\n",method,params,retjsonp);
*retjsonp = 0;
sprintf(stratumreq,"{ \"jsonrpc\":\"2.0\", \"id\": %u, \"method\":\"%s\", \"params\": %s }\n",ep->stratumid,method,params);
memset(ep->buf,0,ep->bufsize);
sitem = (struct stritem *)queueitem(stratumreq);
sitem->expiration = timeout;
sitem->DL.type = ep->stratumid++;
sitem->retptrp = (void **)retjsonp;
queue_enqueue("sendQ",&ep->sendQ,&sitem->DL);
expiration = (uint32_t)time(NULL) + timeout + 1;
while ( *retjsonp == 0 && time(NULL) <= expiration )
usleep(10000);
if ( ep->prev == 0 )
{
if ( *retjsonp == 0 )
{
//printf("unexpected %s timeout with null retjson: %s %s\n",ep->symbol,method,params);
*retjsonp = cJSON_Parse("{\"error\":\"timeout\"}");
}
return(*retjsonp);
}
} else printf("couldnt find electrum server for (%s %s) or no retjsonp.%p\n",method,params,retjsonp);
ep = ep->prev;
}
return(0);
}
@ -413,8 +432,6 @@ cJSON *electrum_hasharg(char *symbol,struct electrum_info *ep,cJSON **retjsonp,c
return(electrum_submit(symbol,ep,retjsonp,method,params,timeout));
}
//" "--blockchain.numblocks.subscribe", "--blockchain.address.get_proof", "--blockchain.utxo.get_address",
cJSON *electrum_version(char *symbol,struct electrum_info *ep,cJSON **retjsonp) { return(electrum_noargs(symbol,ep,retjsonp,"server.version",ELECTRUM_TIMEOUT)); }
cJSON *electrum_banner(char *symbol,struct electrum_info *ep,cJSON **retjsonp) { return(electrum_noargs(symbol,ep,retjsonp,"server.banner",ELECTRUM_TIMEOUT)); }
cJSON *electrum_donation(char *symbol,struct electrum_info *ep,cJSON **retjsonp) { return(electrum_noargs(symbol,ep,retjsonp,"server.donation_address",ELECTRUM_TIMEOUT)); }
@ -440,10 +457,34 @@ cJSON *electrum_address_subscribe(char *symbol,struct electrum_info *ep,cJSON **
cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr)
{
cJSON *retjson; struct iguana_info *coin = LP_coinfind(symbol);
struct LP_transaction *tx; cJSON *retjson,*txobj,*item; int32_t i,n,height; bits256 txid; struct iguana_info *coin = LP_coinfind(symbol);
retjson = electrum_strarg(symbol,ep,retjsonp,"blockchain.address.get_history",addr,ELECTRUM_TIMEOUT);
printf("history.(%s)\n",jprint(retjson,0));
electrum_process_array(coin,retjson);
//printf("history.(%s)\n",jprint(retjson,0));
if ( retjson != 0 && (n= cJSON_GetArraySize(retjson)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(retjson,i);
txid = jbits256(item,"tx_hash");
height = jint(item,"height");
if ( (tx= LP_transactionfind(coin,txid)) == 0 )
{
//char str[65]; printf("history txinit %s ht.%d\n",bits256_str(str,txid),height);
txobj = LP_transactioninit(coin,txid,0,0);
txobj = LP_transactioninit(coin,txid,1,txobj);
if ( txobj != 0 )
free_json(txobj);
if ( height > 0 )
{
if ( (tx= LP_transactionfind(coin,txid)) != 0 )
{
tx->height = height;
LP_address_utxoadd(coin,addr,txid,0,0,height,-1);
}
}
}
}
}
return(retjson);
}
@ -451,25 +492,26 @@ cJSON *electrum_address_getmempool(char *symbol,struct electrum_info *ep,cJSON *
{
cJSON *retjson; struct iguana_info *coin = LP_coinfind(symbol);
retjson = electrum_strarg(symbol,ep,retjsonp,"blockchain.address.get_mempool",addr,ELECTRUM_TIMEOUT);
printf("MEMPOOL.(%s)\n",jprint(retjson,0));
electrum_process_array(coin,retjson);
//printf("MEMPOOL.(%s)\n",jprint(retjson,0));
electrum_process_array(coin,ep,addr,retjson);
return(retjson);
}
cJSON *electrum_address_listunspent(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr)
{
cJSON *retjson=0; struct iguana_info *coin = LP_coinfind(symbol);
//printf("electrum listunspent last.(%s lag %d)\n",coin->lastunspent,(int32_t)(time(NULL) - coin->unspenttime));
//if ( strcmp(coin->lastunspent,addr) != 0 || time(NULL) > coin->unspenttime+10 )
//printf("electrum.%s/%s listunspent last.(%s lag %d)\n",ep->symbol,coin->symbol,coin->lastunspent,(int32_t)(time(NULL) - coin->unspenttime));
if ( 1 || strcmp(coin->lastunspent,addr) != 0 || time(NULL) > coin->unspenttime+30 )
{
if ( (retjson= electrum_strarg(symbol,ep,retjsonp,"blockchain.address.listunspent",addr,ELECTRUM_TIMEOUT)) != 0 )
{
printf("LISTUNSPENT.(%s)\n",jprint(retjson,0));
electrum_process_array(coin,retjson);
strcpy(coin->lastunspent,addr);
//printf("LISTUNSPENT.(%s)\n",jprint(retjson,0));
if ( electrum_process_array(coin,ep,addr,retjson) != 0 )
LP_postutxos(coin->symbol,addr);
safecopy(coin->lastunspent,addr,sizeof(coin->lastunspent));
coin->unspenttime = (uint32_t)time(NULL);
}
}
} else retjson = LP_address_utxos(coin,addr,1);
return(retjson);
}
@ -485,18 +527,94 @@ cJSON *electrum_estimatefee(char *symbol,struct electrum_info *ep,cJSON **retjso
cJSON *electrum_getheader(char *symbol,struct electrum_info *ep,cJSON **retjsonp,int32_t n) { return(electrum_intarg(symbol,ep,retjsonp,"blockchain.block.get_header",n,ELECTRUM_TIMEOUT)); }
cJSON *electrum_getchunk(char *symbol,struct electrum_info *ep,cJSON **retjsonp,int32_t n) { return(electrum_intarg(symbol,ep,retjsonp,"blockchain.block.get_chunk",n,ELECTRUM_TIMEOUT)); }
cJSON *LP_transaction_fromdata(struct iguana_info *coin,bits256 txid,uint8_t *serialized,int32_t len)
{
uint8_t *extraspace; cJSON *txobj; char str[65],str2[65]; struct iguana_msgtx msgtx; bits256 checktxid;
extraspace = calloc(1,1000000);
memset(&msgtx,0,sizeof(msgtx));
txobj = bitcoin_data2json(coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->height,&checktxid,&msgtx,extraspace,1000000,serialized,len,0,0);
//printf("TX.(%s) match.%d\n",jprint(txobj,0),bits256_cmp(txid,checktxid));
free(extraspace);
if ( bits256_cmp(txid,checktxid) != 0 )
{
printf("LP_transaction_fromdata mismatched txid %s vs %s\n",bits256_str(str,txid),bits256_str(str2,checktxid));
free_json(txobj);
txobj = 0;
}
return(txobj);
}
cJSON *electrum_transaction(char *symbol,struct electrum_info *ep,cJSON **retjsonp,bits256 txid)
{
char str[65]; printf("%s TRANSACTION.(%s)\n",symbol,bits256_str(str,txid));
if ( bits256_nonz(txid) != 0 )
return(electrum_hasharg(symbol,ep,retjsonp,"blockchain.transaction.get",txid,ELECTRUM_TIMEOUT));
else return(cJSON_Parse("{\"error\":\"null txid\"}"));
char *hexstr,str[65]; int32_t len; cJSON *hexjson,*txobj=0; struct iguana_info *coin; uint8_t *serialized; struct LP_transaction *tx;
//printf("electrum_transaction %s %s\n",symbol,bits256_str(str,txid));
if ( bits256_nonz(txid) != 0 && (coin= LP_coinfind(symbol)) != 0 )
{
if ( (tx= LP_transactionfind(coin,txid)) != 0 && tx->serialized != 0 )
{
//char str[65]; printf("%s cache hit -> TRANSACTION.(%s)\n",symbol,bits256_str(str,txid));
if ( (txobj= LP_transaction_fromdata(coin,txid,tx->serialized,tx->len)) != 0 )
{
*retjsonp = txobj;
return(txobj);
}
}
hexjson = electrum_hasharg(symbol,ep,&hexjson,"blockchain.transaction.get",txid,ELECTRUM_TIMEOUT);
hexstr = jprint(hexjson,0);
if ( strlen(hexstr) > 60000 )
{
static uint32_t counter;
if ( counter++ < 3 )
printf("rawtransaction too big %d\n",(int32_t)strlen(hexstr));
free(hexstr);
free_json(hexjson);
*retjsonp = cJSON_Parse("{\"error\":\"transaction too big\"}");
return(*retjsonp);
}
if ( hexstr[0] == '"' && hexstr[strlen(hexstr)-1] == '"' )
hexstr[strlen(hexstr)-1] = 0;
if ( (len= is_hexstr(hexstr+1,0)) > 2 )
{
len = (int32_t)strlen(hexstr+1) >> 1;
serialized = malloc(len);
decode_hex(serialized,len,hexstr+1);
free(hexstr);
//printf("DATA.(%s) from (%s)\n",hexstr+1,jprint(hexjson,0));
txobj = LP_transaction_fromdata(coin,txid,serialized,len);
if ( (tx= LP_transactionfind(coin,txid)) == 0 || tx->serialized == 0 )
{
txobj = LP_transactioninit(coin,txid,0,txobj);
LP_transactioninit(coin,txid,1,txobj);
tx = LP_transactionfind(coin,txid);
}
if ( tx != 0 )
{
tx->serialized = serialized;
tx->len = len;
}
else
{
printf("unexpected couldnt find tx %s %s\n",coin->symbol,bits256_str(str,txid));
free(serialized);
}
*retjsonp = txobj;
free_json(hexjson);
//printf("return from electrum_transaction\n");
return(*retjsonp);
} else printf("non-hex tx.(%s)\n",jprint(hexjson,0));
free(hexstr);
free_json(hexjson);
}
*retjsonp = 0;
return(*retjsonp);
}
cJSON *electrum_getmerkle(char *symbol,struct electrum_info *ep,cJSON **retjsonp,bits256 txid,int32_t height)
{
char params[128],str[65];
sprintf(params,"[\"%s\", %d]",bits256_str(str,txid),height);
if ( bits256_nonz(txid) == 0 )
return(cJSON_Parse("{\"error\":\"null txid\"}"));
return(electrum_submit(symbol,ep,retjsonp,"blockchain.transaction.get_merkle",params,ELECTRUM_TIMEOUT));
}
@ -567,7 +685,7 @@ void electrum_test()
struct electrum_info *LP_electrum_info(int32_t *alreadyp,char *symbol,char *ipaddr,uint16_t port,int32_t bufsize)
{
struct electrum_info *ep=0; int32_t i; struct stritem *sitem; char name[512],*str = "init string";
struct electrum_info *ep=0; int32_t i,sock; struct stritem *sitem; char name[512],*str = "init string";
*alreadyp = 0;
portable_mutex_lock(&LP_electrummutex);
for (i=0; i<Num_electrums; i++)
@ -585,8 +703,13 @@ struct electrum_info *LP_electrum_info(int32_t *alreadyp,char *symbol,char *ipad
portable_mutex_unlock(&LP_electrummutex);
if ( ep == 0 )
{
if ( (sock= LP_socket(0,ipaddr,port)) < 0 )
{
printf("error connecting to %s:%u\n",ipaddr,port);
return(0);
}
ep = calloc(1,sizeof(*ep) + bufsize);
ep->sock = LP_socket(0,ipaddr,port);
ep->sock = sock;
safecopy(ep->symbol,symbol,sizeof(ep->symbol));
safecopy(ep->ipaddr,ipaddr,sizeof(ep->ipaddr));
ep->port = port;
@ -608,12 +731,12 @@ struct electrum_info *LP_electrum_info(int32_t *alreadyp,char *symbol,char *ipad
int32_t LP_recvfunc(struct electrum_info *ep,char *str,int32_t len)
{
cJSON *strjson,*errjson,*resultjson,*paramsjson; char *method; int32_t i,n,height; uint32_t idnum=0; struct stritem *stritem; struct queueitem *item = 0;
cJSON *strjson,*errjson,*resultjson,*paramsjson; char *method; int32_t i,n,height; uint32_t idnum=0; struct stritem *stritem; struct iguana_info *coin; struct queueitem *tmp,*item = 0;
ep->lasttime = (uint32_t)time(NULL);
if ( (strjson= cJSON_Parse(str)) != 0 )
{
resultjson = jobj(strjson,"result");
printf("strjson.(%s)\n",jprint(strjson,0));
//printf("strjson.(%s)\n",jprint(strjson,0));
if ( (method= jstr(strjson,"method")) != 0 )
{
if ( strcmp(method,"blockchain.headers.subscribe") == 0 )
@ -625,11 +748,11 @@ int32_t LP_recvfunc(struct electrum_info *ep,char *str,int32_t len)
resultjson = jitem(paramsjson,i);
}
}
else if ( strcmp(method,"blockchain.address.subscribe") == 0 )
/*else if ( strcmp(method,"blockchain.address.subscribe") == 0 ) never is called
{
printf("recv addr subscribe.(%s)\n",jprint(resultjson,0));
electrum_process_array(ep->coin,resultjson);
}
}*/
}
if ( resultjson != 0 )
{
@ -637,18 +760,18 @@ int32_t LP_recvfunc(struct electrum_info *ep,char *str,int32_t len)
{
*(ep->heightp) = height;
*(ep->heighttimep) = (uint32_t)time(NULL);
printf("ELECTRUM >>>>>>>>> set height.%d\n",height);
if ( (coin= LP_coinfind(ep->symbol)) != 0 )
coin->updaterate = (uint32_t)time(NULL);
//printf("%s ELECTRUM >>>>>>>>> set height.%d\n",ep->symbol,height);
}
}
idnum = juint(strjson,"id");
portable_mutex_lock(&ep->pendingQ.mutex);
if ( ep->pendingQ.list != 0 )
{
DL_FOREACH(ep->pendingQ.list,item)
DL_FOREACH_SAFE(ep->pendingQ.list,item,tmp)
{
stritem = (struct stritem *)item;
if ( *stritem->retptrp != 0 )
continue;
if ( item->type == idnum )
{
//printf("matched idnum.%d result.%p\n",idnum,resultjson);
@ -660,13 +783,16 @@ int32_t LP_recvfunc(struct electrum_info *ep,char *str,int32_t len)
}
if ( stritem->expiration < ep->lasttime )
{
//DL_DELETE(ep->pendingQ.list,item);
printf("expired (%s)\n",stritem->str);
errjson = cJSON_CreateObject();
jaddnum(errjson,"id",item->type);
jaddstr(errjson,"error","timeout");
*((cJSON **)stritem->retptrp) = errjson;
//free(item);
DL_DELETE(ep->pendingQ.list,item);
if ( 0 )
{
printf("expired %s (%s)\n",ep->symbol,stritem->str);
errjson = cJSON_CreateObject();
jaddnum(errjson,"id",item->type);
jaddstr(errjson,"error","timeout");
*((cJSON **)stritem->retptrp) = errjson;
}
free(item);
}
}
}
@ -708,7 +834,7 @@ void LP_dedicatedloop(void *arg)
if ( ep->pendingQ.list != 0 )
{
printf("list %p\n",ep->pendingQ.list);
DL_FOREACH(ep->pendingQ.list,item)
DL_FOREACH_SAFE(ep->pendingQ.list,item,tmp)
{
printf("item.%p\n",item);
if ( item->type == 0xffffffff )
@ -721,7 +847,7 @@ void LP_dedicatedloop(void *arg)
}
DL_APPEND(ep->pendingQ.list,&sitem->DL);
portable_mutex_unlock(&ep->pendingQ.mutex);*/
//printf("%p SEND.(%s) to %s:%u\n",sitem,sitem->str,ep->ipaddr,ep->port);
//printf("%p SENT.(%s) to %s:%u\n",sitem,sitem->str,ep->ipaddr,ep->port);
queue_enqueue("pendingQ",&ep->pendingQ,&sitem->DL);
flag++;
}
@ -740,7 +866,12 @@ void LP_dedicatedloop(void *arg)
usleep(100000);
}
}
printf("close %s:%u\n",ep->ipaddr,ep->port);
if ( coin->electrum == ep )
{
coin->electrum = ep->prev;
printf("set %s electrum to %p\n",coin->symbol,coin->electrum);
} else printf("backup electrum server closing\n");
printf(">>>>>>>>>> electrum close %s:%u\n",ep->ipaddr,ep->port);
if ( Num_electrums > 0 )
{
portable_mutex_lock(&LP_electrummutex);
@ -755,7 +886,8 @@ void LP_dedicatedloop(void *arg)
}
portable_mutex_unlock(&LP_electrummutex);
}
free(ep);
ep->sock = -1;
//free(ep);
}
cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port)
@ -763,7 +895,11 @@ cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port)
struct electrum_info *ep; int32_t already; cJSON *retjson = cJSON_CreateObject();
jaddstr(retjson,"ipaddr",ipaddr);
jaddnum(retjson,"port",port);
ep = LP_electrum_info(&already,coin->symbol,ipaddr,port,IGUANA_MAXPACKETSIZE * 10);
if ( (ep= LP_electrum_info(&already,coin->symbol,ipaddr,port,IGUANA_MAXPACKETSIZE * 10)) == 0 )
{
jaddstr(retjson,"error","couldnt connect to electrum server");
return(retjson);
}
if ( already == 0 )
{
if ( ep != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_dedicatedloop,(void *)ep) != 0 )
@ -775,6 +911,7 @@ cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port)
{
printf("launched.(%s:%u)\n",ep->ipaddr,ep->port);
jaddstr(retjson,"result","success");
ep->prev = coin->electrum;
coin->electrum = ep;
}
}

608
iguana/exchanges/LP_statemachine.c

@ -1473,6 +1473,407 @@ if ( (array= LP_tradecandidates(base)) != 0 )
printf("metrics, best %f\n",bestmetric);
*/
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,int32_t maxentries)
{
char *retstr; struct LP_peerinfo *peer; uint32_t now; int32_t retval = -1;
printf("deprecated LP_utxosquery\n");
return(-1);
peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport);
if ( coin == 0 )
coin = "";
//printf("utxo query.(%s)\n",destipaddr);
if ( IAMLP != 0 )
retstr = issue_LP_getutxos(destipaddr,destport,coin,lastn,myipaddr,myport,mypeer != 0 ? mypeer->numpeers : 0,maxentries);
else retstr = issue_LP_clientgetutxos(destipaddr,destport,coin,maxentries);
if ( retstr != 0 )
{
now = (uint32_t)time(NULL);
retval = LP_utxosparse(destipaddr,destport,retstr,now);
//printf("got.(%s)\n",retstr);
free(retstr);
}
return(retval);
}
char *issue_LP_numutxos(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers,int32_t numutxos)
{
char url[512],*retstr;
printf("deprecated issue_LP_numutxos\n");
return(0);
sprintf(url,"http://%s:%u/api/stats/numutxos?ipaddr=%s&port=%u&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,numpeers,numutxos);
retstr = LP_issue_curl("numutxos",destip,port,url);
//printf("%s -> getpeers.(%s)\n",destip,retstr);
return(retstr);
}
char *issue_LP_getutxos(char *destip,uint16_t destport,char *coin,int32_t lastn,char *ipaddr,uint16_t port,int32_t numpeers,int32_t numutxos)
{
char url[512];
printf("deprecated issue_LP_getutxos\n");
return(0);
sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=%s&port=%u&numpeers=%d&numutxos=%d",destip,destport,coin,lastn,ipaddr,port,numpeers,numutxos);
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];//,*retstr;
printf("deprecated issue_LP_clientgetutxos\n");
return(0);
sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=127.0.0.1&port=0",destip,destport,coin,lastn);
return(LP_issue_curl("clientgetutxos",destip,destport,url));
//retstr = issue_curlt(url,LP_HTTP_TIMEOUT);
//printf("%s clientgetutxos.(%s)\n",url,retstr);
//return(retstr);
}
void LP_address_monitor(struct LP_pubkeyinfo *pubp)
{
struct iguana_info *coin,*tmp; char coinaddr[64]; cJSON *retjson; struct LP_address *ap;
return;
HASH_ITER(hh,LP_coins,coin,tmp)
{
bitcoin_address(coinaddr,coin->taddr,coin->pubtype,pubp->rmd160,sizeof(pubp->rmd160));
portable_mutex_lock(&coin->addrmutex);
if ( (ap= _LP_address(coin,coinaddr)) != 0 )
{
ap->monitor = (uint32_t)time(NULL);
}
portable_mutex_unlock(&coin->addrmutex);
if ( coin->electrum != 0 )
{
if ( (retjson= electrum_address_subscribe(coin->symbol,coin->electrum,&retjson,coinaddr)) != 0 )
{
printf("%s MONITOR.(%s) -> %s\n",coin->symbol,coinaddr,jprint(retjson,0));
free_json(retjson);
}
}
}
}
/*else if ( strcmp(method,"ordermatch") == 0 )
{
if ( price > SMALLVAL )
return(LP_ordermatch(base,j64bits(argjson,"txfee"),price,jdouble(argjson,"relvolume"),rel,jbits256(argjson,"txid"),jint(argjson,"vout"),jbits256(argjson,"feetxid"),jint(argjson,"feevout"),j64bits(argjson,"desttxfee"),jint(argjson,"duration")));
else return(clonestr("{\"error\":\"no price set\"}"));
}
else if ( strcmp(method,"trade") == 0 )
{
struct LP_quoteinfo Q;
if ( price > SMALLVAL || jobj(argjson,"quote") != 0 )
{
LP_quoteparse(&Q,jobj(argjson,"quote"));
return(LP_trade(ctx,myipaddr,pubsock,&Q,price,jint(argjson,"timeout"),jint(argjson,"duration")));
} else return(clonestr("{\"error\":\"no price set or no quote object\"}"));
}
else if ( strcmp(method,"autotrade") == 0 )
{
if ( price > SMALLVAL )
{
return(LP_autotrade(ctx,myipaddr,pubsock,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration")));
} else return(clonestr("{\"error\":\"no price set\"}"));
}*/
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_mypub25519));
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);
}
/*struct LP_utxoinfo *_LP_butxo_find(struct LP_utxoinfo *butxo)
{
int32_t i; struct LP_utxoinfo *utxo=0; uint32_t now = (uint32_t)time(NULL);
//portable_mutex_lock(&LP_butxomutex);
for (i=0; i<sizeof(BUTXOS)/sizeof(*BUTXOS); i++)
{
utxo = &BUTXOS[i];
if ( butxo->payment.vout == utxo->payment.vout && butxo->deposit.vout == utxo->deposit.vout && bits256_nonz(butxo->payment.txid) != 0 && bits256_nonz(butxo->deposit.txid) != 0 && bits256_cmp(butxo->payment.txid,utxo->payment.txid) == 0 && bits256_cmp(butxo->deposit.txid,utxo->deposit.txid) == 0 )
break;
if ( utxo->S.swap == 0 && now > utxo->T.swappending )
memset(utxo,0,sizeof(*utxo));
utxo = 0;
}
//portable_mutex_unlock(&LP_butxomutex);
return(utxo);
}
struct LP_utxoinfo *LP_butxo_add(struct LP_utxoinfo *butxo)
{
static struct LP_utxoinfo zeroes;
int32_t i; struct LP_utxoinfo *utxo=0;
portable_mutex_lock(&LP_butxomutex);
if ( (utxo= _LP_butxo_find(butxo)) == 0 )
{
for (i=0; i<sizeof(BUTXOS)/sizeof(*BUTXOS); i++)
{
utxo = &BUTXOS[i];
if ( memcmp(&zeroes,utxo,sizeof(*utxo)) == 0 )
{
*utxo = *butxo;
break;
}
utxo = 0;
}
}
portable_mutex_unlock(&LP_butxomutex);
return(utxo);
}
void LP_butxo_swapfields_copy(struct LP_utxoinfo *destutxo,struct LP_utxoinfo *srcutxo)
{
destutxo->S = srcutxo->S;
destutxo->T = srcutxo->T;
}
void LP_butxo_swapfields(struct LP_utxoinfo *butxo)
{
struct LP_utxoinfo *getutxo=0;
portable_mutex_lock(&LP_butxomutex);
if ( (getutxo= _LP_butxo_find(butxo)) != 0 )
LP_butxo_swapfields_copy(butxo,getutxo);
portable_mutex_unlock(&LP_butxomutex);
}
void LP_butxo_swapfields_set(struct LP_utxoinfo *butxo)
{
struct LP_utxoinfo *setutxo;
if ( (setutxo= LP_butxo_add(butxo)) != 0 )
{
LP_butxo_swapfields_copy(setutxo,butxo);
}
}*/
/*struct LP_utxoinfo BUTXOS[100];
int32_t LP_butxo_findeither(bits256 txid,int32_t vout)
{
struct LP_utxoinfo *utxo; int32_t i,retval = 0;
portable_mutex_lock(&LP_butxomutex);
for (i=0; i<sizeof(BUTXOS)/sizeof(*BUTXOS); i++)
{
utxo = &BUTXOS[i];
if ( (vout == utxo->payment.vout && bits256_cmp(txid,utxo->payment.txid)) == 0 || (vout == utxo->deposit.vout && bits256_cmp(txid,utxo->deposit.txid) == 0) )
{
retval = 1;
break;
}
}
portable_mutex_unlock(&LP_butxomutex);
return(retval);
}*/
struct LP_utxoinfo *LP_utxoaddjson(int32_t iambob,int32_t pubsock,cJSON *argjson)
{
struct LP_utxoinfo *utxo;
if ( jobj(argjson,"iambob") == 0 || iambob != jint(argjson,"iambob") )
{
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"),jstr(argjson,"gui"),juint(argjson,"session"));
if ( LP_ismine(utxo) > 0 && utxo->T.lasttime == 0 )
{
utxo->T.lasttime = (uint32_t)time(NULL);
printf("set lasttime!\n");
}
portable_mutex_unlock(&LP_UTXOmutex);
return(utxo);
}
int32_t LP_utxosparse(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; bits256 txid; struct LP_utxoinfo *utxo;
//printf("parse.(%s)\n",retstr);
if ( (array= cJSON_Parse(retstr)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( (argipaddr= jstr(item,"ipaddr")) != 0 && (argport= juint(item,"port")) != 0 )
{
if ( (pushport= juint(item,"push")) == 0 )
pushport = argport + 1;
if ( (subport= juint(item,"sub")) == 0 )
subport = argport + 2;
argipbits = (uint32_t)calc_ipbits(argipaddr);
if ( (peer= LP_peerfind(argipbits,argport)) == 0 )
peer = LP_addpeer(0,-1,argipaddr,argport,pushport,subport,jint(item,"numpeers"),jint(item,"numutxos"),juint(item,"session"));
}
if ( jobj(item,"txid") != 0 )
{
txid = jbits256(item,"txid");
//printf("parse.(%s)\n",jprint(item,0));
if ( (utxo= LP_utxoaddjson(1,-1,item)) != 0 )
utxo->T.lasttime = now;
}
}
if ( (destpeer= LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport)) != 0 )
{
destpeer->numutxos = n;
}
}
free_json(array);
}
return(n);
}
void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector)
{
//cJSON *argjson; struct _LP_utxoinfo u; char *msg;
if ( utxo == 0 )
return;
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_utxos(int32_t iambob,struct LP_peerinfo *mypeer,char *symbol,int32_t lastn)
{
int32_t i,n,m; uint64_t val,val2; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray();
printf("deprecated! LP_utxos\n");
//n = mypeer != 0 ? mypeer->numutxos : 0;
if ( lastn <= 0 )
lastn = LP_PROPAGATION_SLACK * 2;
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 ( (symbol == 0 || symbol[0] == 0 || strcmp(symbol,utxo->coin) == 0) && utxo->T.spentflag == 0 )
{
u = (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) == 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));
}
}
if ( (n= cJSON_GetArraySize(utxosjson)) > lastn )
{
m = n - lastn;
for (i=0; i<m; i++)
cJSON_DeleteItemFromArray(utxosjson,0);
}
return(jprint(utxosjson,1));
}
void LP_utxo_clientpublish(struct LP_utxoinfo *utxo)
{
bits256 zero; char *msg;
if ( 0 && LP_isunspent(utxo) > 0 )
{
memset(zero.bytes,0,sizeof(zero));
msg = jprint(LP_utxojson(utxo),1);
LP_broadcast_message(LP_mypubsock,utxo->coin,"",zero,msg);
}
}
void LP_utxo_spentcheck(int32_t pubsock,struct LP_utxoinfo *utxo)
{
struct _LP_utxoinfo u; struct iguana_info *coin; char str[65]; uint32_t now = (uint32_t)time(NULL);
if ( IAMLP != 0 && (coin= LP_coinfind(utxo->coin)) != 0 && coin->inactive != 0 )
return;
//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(0,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(0,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);
}
}
}
int32_t LP_peer_utxosquery(struct LP_peerinfo *mypeer,uint16_t myport,int32_t pubsock,struct LP_peerinfo *peer,uint32_t now,int32_t interval,int32_t maxentries)
{
int32_t lastn,n = -1;
if ( peer->lastutxos < now-interval )
{
//lastn = peer->numutxos - mypeer->numutxos + LP_PROPAGATION_SLACK;
//if ( lastn < LP_PROPAGATION_SLACK * 2 )
lastn = LP_PROPAGATION_SLACK * 2;
if ( mypeer == 0 || strcmp(peer->ipaddr,mypeer->ipaddr) != 0 )
{
peer->lastutxos = now;
//printf("query utxos from %s\n",peer->ipaddr);
n = LP_utxosquery(mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,maxentries);
}
} //else printf("LP_peer_utxosquery skip.(%s) %u\n",peer->ipaddr,peer->lastutxos);
return(n);
}
/*if ( time(NULL) > coin->lastmonitor+60 )
{
//portable_mutex_lock(&coin->addrmutex);
HASH_ITER(hh,coin->addresses,ap,atmp)
{
if ( coin->electrum == 0 )
{
LP_listunspent_issue(coin->symbol,ap->coinaddr);
DL_FOREACH_SAFE(ap->utxos,up,utmp)
{
if ( up->spendheight <= 0 )
{
if ( LP_txvalue(0,coin->symbol,up->U.txid,up->U.vout) == 0 )
up->spendheight = 1;
}
}
}
}
//portable_mutex_unlock(&coin->addrmutex);
coin->lastmonitor = (uint32_t)time(NULL);
}*/
/*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;
@ -1600,4 +2001,211 @@ if ( (array= LP_tradecandidates(base)) != 0 )
}
}*/
/*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);
}*/
//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 ( polarity > 0 )
// minsatoshis = utxo->S.satoshis;
//else minsatoshis = utxo->S.satoshis * price;
/*if ( LP_orderbookfind(*arrayp,cachednum,utxo->payment.txid,utxo->payment.vout) < 0 )
{
if ( LP_iseligible(&val,&val2,utxo->iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,utxo->deposit.txid,utxo->deposit.vout) == 0 )
continue;
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,now - pubp->timestamp)) != 0 )
{
*arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1));
(*arrayp)[num++] = op;
if ( LP_ismine(utxo) > 0 && utxo->T.lasttime == 0 )
LP_utxo_clientpublish(utxo);
}
}*/
#ifdef oldway
struct LP_utxoinfo *LP_bestutxo(double *ordermatchpricep,int64_t *bestsatoshisp,int64_t *bestdestsatoshisp,struct LP_utxoinfo *autxo,char *base,double maxprice,int32_t duration,uint64_t txfee,uint64_t desttxfee,uint64_t maxdestsatoshis)
{
int64_t satoshis,destsatoshis; uint64_t val,val2; bits256 txid,pubkey; char *obookstr; cJSON *orderbook,*asks,*item; struct LP_utxoinfo *butxo,*bestutxo = 0; int32_t i,n,j,vout,numasks; double bestmetric=0.,metric,vol,price,qprice,bestprice = 0.; struct LP_pubkeyinfo *pubp;
*ordermatchpricep = 0.;
*bestsatoshisp = *bestdestsatoshisp = 0;
if ( duration <= 0 )
duration = LP_ORDERBOOK_DURATION;
if ( maxprice <= 0. || LP_priceinfofind(base) == 0 )
return(0);
LP_txfees(&txfee,&desttxfee,base,autxo->coin);
if ( (obookstr= LP_orderbook(base,autxo->coin,duration)) != 0 )
{
if ( (orderbook= cJSON_Parse(obookstr)) != 0 )
{
if ( (asks= jarray(&numasks,orderbook,"asks")) != 0 )
{
for (i=0; i<numasks; i++)
{
item = jitem(asks,i);
price = jdouble(item,"price");
if ( LP_pricevalid(price) > 0 && price <= maxprice )
{
//price *= 1.0001;
//if ( price > maxprice )
// price = maxprice;
pubkey = jbits256(item,"pubkey");
if ( bits256_cmp(pubkey,LP_mypub25519) != 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;
printf("maxdest %.8f metric %f vol %f add pings numutxos.%d min %.8f max %.8f\n",dstr(maxdestsatoshis),metric,vol,jint(item,"numutxos"),jdouble(item,"minvolume"),jdouble(item,"maxvolume"));
// check utxos > 1 for pubkey, SPV validate recv'ed
/*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 )
{
printf("got butxo? %p\n",butxo);
if ( LP_iseligible(&val,&val2,butxo->iambob,butxo->coin,butxo->payment.txid,butxo->payment.vout,butxo->S.satoshis,butxo->deposit.txid,butxo->deposit.vout) > 0 )
{
destsatoshis = ((butxo->S.satoshis - txfee) * price);
satoshis = (destsatoshis / price + 0.49) - txfee;
if ( satoshis <= 0 )
continue;
qprice = (double)destsatoshis / satoshis;
n = (int32_t)((double)destsatoshis / desttxfee);
if ( n < 10 )
n = 10;
else n = 3;
for (j=0; j<n; j++)
{
if ( (qprice= LP_qprice_calc(&destsatoshis,&satoshis,(price*(100.+j))/100.,butxo->S.satoshis,txfee,autxo->payment.value,maxdestsatoshis,desttxfee)) > price+SMALLVAL )
break;
}
//printf("j.%d/%d qprice %.8f vs price %.8f best.(%.8f %.8f)\n",j,n,qprice,price,dstr(satoshis),dstr(destsatoshis));
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;
*ordermatchpricep = price;
*bestdestsatoshisp = destsatoshis;
*bestsatoshisp = satoshis;
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
{
printf("ineligible.(%.8f %.8f)\n",price,dstr(butxo->S.satoshis));
//if ( butxo->T.spentflag == 0 )
// butxo->T.spentflag = (uint32_t)time(NULL);
}
}
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 or bestflag.%d\n",butxo,vol,butxo!=0?dstr(butxo->S.satoshis):0,butxo->T.bestflag);
}*/
} else printf("self trading or blacklisted peer\n");
}
else
{
if ( i == 0 )
printf("maxprice %.8f vs %.8f\n",maxprice,price);
break;
}
}
if ( bestutxo == 0 )
{
int32_t numrestraints;
for (i=numrestraints=0; i<numasks; i++)
{
item = jitem(asks,i);
pubkey = jbits256(item,"pubkey");
if ( bits256_cmp(pubkey,LP_mypub25519) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 )
{
txid = jbits256(item,"txid");
vout = jint(item,"vout");
if ( (butxo= LP_utxofind(1,txid,vout)) != 0 )
{
numrestraints++;
butxo->T.bestflag = 0;
pubp->numerrors = 0;
}
}
}
printf("no bob utxo found -> cleared %d restraints\n",numrestraints);
}
}
free_json(orderbook);
}
free(obookstr);
}
printf("bestutxo.%p %.8f %.8f\n",bestutxo,*ordermatchpricep,dstr(*bestdestsatoshisp));
if ( bestutxo == 0 || *ordermatchpricep == 0. || *bestdestsatoshisp == 0 )
return(0);
bestutxo->T.bestflag = 1;
int32_t changed;
LP_mypriceset(&changed,autxo->coin,base,1. / *ordermatchpricep);
return(bestutxo);
}
char *LP_ordermatch(char *base,int64_t txfee,double maxprice,double maxvolume,char *rel,bits256 txid,int32_t vout,bits256 feetxid,int32_t feevout,int64_t desttxfee,int32_t duration)
{
struct LP_quoteinfo Q; int64_t bestsatoshis=0,bestdestsatoshis = 0; double ordermatchprice = 0.; struct LP_utxoinfo *autxo,*bestutxo;
txfee = LP_txfeecalc(LP_coinfind(base),txfee);
desttxfee = LP_txfeecalc(LP_coinfind(rel),desttxfee);
if ( (autxo= LP_utxopairfind(0,txid,vout,feetxid,feevout)) == 0 )
return(clonestr("{\"error\":\"cant find alice utxopair\"}"));
if ( (bestutxo= LP_bestutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,SATOSHIDEN*maxvolume)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 )
return(clonestr("{\"error\":\"cant find ordermatch utxo\"}"));
if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestsatoshis,bestdestsatoshis) < 0 )
return(clonestr("{\"error\":\"cant set ordermatch quote\"}"));
if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,LP_mypub25519,autxo->coinaddr) < 0 )
return(clonestr("{\"error\":\"cant set ordermatch quote info\"}"));
return(jprint(LP_quotejson(&Q),1));
}
char *LP_autotrade(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel,double maxprice,double relvolume,int32_t timeout,int32_t duration)
{
uint64_t desttxfee,txfee; int64_t bestsatoshis=0,bestdestsatoshis=0; struct LP_utxoinfo *autxo,*butxo,*bestutxo = 0; double qprice,ordermatchprice=0.; struct LP_quoteinfo Q;
if ( duration <= 0 )
duration = LP_ORDERBOOK_DURATION;
if ( timeout <= 0 )
timeout = LP_AUTOTRADE_TIMEOUT;
if ( maxprice <= 0. || relvolume <= 0. || LP_priceinfofind(base) == 0 || LP_priceinfofind(rel) == 0 )
return(clonestr("{\"error\":\"invalid parameter\"}"));
if ( (autxo= LP_utxo_bestfit(rel,SATOSHIDEN * relvolume)) == 0 )
return(clonestr("{\"error\":\"cant find utxo that is big enough\"}"));
LP_txfees(&txfee,&desttxfee,base,rel);
if ( (bestutxo= LP_bestutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,SATOSHIDEN*relvolume)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 )
{
printf("bestutxo.%p ordermatchprice %.8f bestdestsatoshis %.8f\n",bestutxo,ordermatchprice,dstr(bestdestsatoshis));
return(clonestr("{\"error\":\"cant find ordermatch utxo\"}"));
}
if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestsatoshis,bestdestsatoshis) < 0 )
return(clonestr("{\"error\":\"cant set ordermatch quote\"}"));
if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,LP_mypub25519,autxo->coinaddr) < 0 )
return(clonestr("{\"error\":\"cant set ordermatch quote info\"}"));
if ( (qprice= LP_quote_validate(&autxo,&butxo,&Q,0)) <= SMALLVAL )
{
printf("quote validate error %.0f\n",qprice);
return(clonestr("{\"error\":\"quote validation error\"}"));
}
printf("do quote.(%s)\n",jprint(LP_quotejson(&Q),1));
return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration));
}
#endif

52
iguana/exchanges/LP_swap.c

@ -121,7 +121,11 @@ void basilisk_swap_finished(struct basilisk_swap *swap)
{
int32_t i;
if ( swap->utxo != 0 && swap->sentflag == 0 )
{
LP_availableset(swap->utxo);
swap->utxo = 0;
//LP_butxo_swapfields_set(swap->utxo);
}
swap->I.finished = (uint32_t)time(NULL);
// save to permanent storage
basilisk_rawtx_purge(&swap->bobdeposit);
@ -408,10 +412,10 @@ int32_t LP_waitfor(int32_t pairsock,struct basilisk_swap *swap,int32_t timeout,i
pfd.events = NN_POLLIN;
if ( nn_poll(&pfd,1,1) > 0 )
{
//printf("start wait\n");
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);
@ -560,7 +564,7 @@ int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct ba
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));
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 )
@ -613,8 +617,11 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3
rawtx->I.actualtxid = LP_broadcast_tx(rawtx->name,rawtx->coin->symbol,rawtx->txbytes,rawtx->I.datalen);
if ( bits256_cmp(rawtx->I.actualtxid,rawtx->I.signedtxid) != 0 )
{
//printf("%s rawtxsend.[%d] %s vs %s\n",rawtx->name,rawtx->I.datalen,bits256_str(str,rawtx->I.signedtxid),bits256_str(str2,rawtx->I.actualtxid));
rawtx->I.actualtxid = rawtx->I.signedtxid;
char str[65],str2[65];
printf("%s rawtxsend.[%d] %s vs %s\n",rawtx->name,rawtx->I.datalen,bits256_str(str,rawtx->I.signedtxid),bits256_str(str2,rawtx->I.actualtxid));
if ( bits256_nonz(rawtx->I.signedtxid) != 0 )
rawtx->I.actualtxid = rawtx->I.signedtxid;
else rawtx->I.signedtxid = rawtx->I.actualtxid;
}
if ( bits256_nonz(rawtx->I.actualtxid) != 0 && msgbits != 0 )
{
@ -635,7 +642,7 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3
if ( suppress_swapsend == 0 )
{
retval = LP_swapsend(pairsock,swap,msgbits,sendbuf,sendlen,nextbits,rawtx->I.crcs);
if ( LP_waitmempool(rawtx->coin->symbol,rawtx->I.destaddr,rawtx->I.signedtxid,LP_SWAPSTEP_TIMEOUT*10) < 0 )
if ( LP_waitmempool(rawtx->coin->symbol,rawtx->I.destaddr,rawtx->I.signedtxid,0,LP_SWAPSTEP_TIMEOUT*10) < 0 )
{
char str[65]; printf("failed to find %s %s %s in the mempool?\n",rawtx->name,rawtx->I.destaddr,bits256_str(str,rawtx->I.actualtxid));
retval = -1;
@ -720,7 +727,7 @@ void LP_bobloop(void *_swap)
printf("error waiting for alicefee\n");
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(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT*10,LP_verify_alicepayment) < 0 )
else if ( LP_waitfor(swap->N.pair,swap,1800,LP_verify_alicepayment) < 0 )
printf("error waiting for alicepayment\n");
else
{
@ -731,9 +738,9 @@ void LP_bobloop(void *_swap)
if ( strcmp(swap->alicecoin.symbol,"BTC") == 0 )
m = 0;
else m = 1;
while ( (n= LP_numconfirms(swap->alicecoin.symbol,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,1)) < m ) // sync with alice
while ( (n= LP_numconfirms(swap->alicecoin.symbol,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,1)) < m ) // sync with alice
{
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));
char str[65];printf("%d waiting for alicepayment %s to be confirmed.%d %s %s\n",n,swap->alicepayment.I.destaddr,1,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid));
sleep(3);
}
if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x8000,data,maxlen,&swap->bobpayment,0x4000,0) == 0 )
@ -749,7 +756,7 @@ void LP_bobloop(void *_swap)
}
}
basilisk_swap_finished(swap);
free(swap);
//free(swap);
} else printf("swap timed out\n");
}
@ -775,7 +782,7 @@ void LP_aliceloop(void *_swap)
LP_swapsfp_update(&swap->I.req);
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(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT*10,LP_verify_bobdeposit) < 0 )
else if ( LP_waitfor(swap->N.pair,swap,1800,LP_verify_bobdeposit) < 0 )
printf("error waiting for bobdeposit\n");
else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0) == 0 )
printf("error sending alicepayment\n");
@ -784,26 +791,26 @@ void LP_aliceloop(void *_swap)
if ( strcmp(swap->alicecoin.symbol,"BTC") == 0 )
m = 0;
else m = 1;
while ( (n= LP_numconfirms(swap->alicecoin.symbol,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,1)) < m )
while ( (n= LP_numconfirms(swap->alicecoin.symbol,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,1)) < m )
{
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));
char str[65];printf("%d waiting for alicepayment %s to be confirmed.%d %s %s\n",n,swap->alicepayment.I.destaddr,1,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid));
sleep(10);
}
swap->sentflag = 1;
if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT*10,LP_verify_bobpayment) < 0 )
if ( LP_waitfor(swap->N.pair,swap,1800,LP_verify_bobpayment) < 0 )
printf("error waiting for bobpayment\n");
else
{
while ( (n= LP_numconfirms(swap->bobcoin.symbol,swap->bobpayment.I.destaddr,swap->bobpayment.I.signedtxid,1)) < swap->I.bobconfirms )
while ( (n= LP_numconfirms(swap->bobcoin.symbol,swap->bobpayment.I.destaddr,swap->bobpayment.I.signedtxid,0,1)) < 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));
char str[65];printf("%d waiting for bobpayment %s to be confirmed.%d %s %s\n",n,swap->bobpayment.I.destaddr,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->alicecoin.symbol,swap->alicespend.I.destaddr,swap->alicespend.I.signedtxid,1)) < swap->I.aliceconfirms )
while ( (n= LP_numconfirms(swap->alicecoin.symbol,swap->alicespend.I.destaddr,swap->alicespend.I.signedtxid,0,1)) < swap->I.aliceconfirms )
{
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));
char str[65];printf("%d waiting for alicespend %s to be confirmed.%d %s %s\n",n,swap->alicespend.I.destaddr,swap->I.aliceconfirms,swap->bobcoin.symbol,bits256_str(str,swap->alicespend.I.signedtxid));
sleep(LP_SWAPSTEP_TIMEOUT);
}
if ( swap->N.pair >= 0 )
@ -812,8 +819,6 @@ void LP_aliceloop(void *_swap)
}
}
}
basilisk_swap_finished(swap);
free(swap);
}
free(data);
if ( swap->N.pair >= 0 )
@ -821,6 +826,10 @@ void LP_aliceloop(void *_swap)
nn_close(swap->N.pair);
swap->N.pair = -1;
}
basilisk_swap_finished(swap);
printf("finish swap.%p\n",swap);
//free(swap);
G.LP_pendingswaps--;
}
bits256 instantdex_derivekeypair(void *ctx,bits256 *newprivp,uint8_t pubkey[33],bits256 privkey,bits256 orderhash)
@ -1062,6 +1071,9 @@ struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256
swap->ctx = bitcoin_ctx();
vcalc_sha256(0,swap->I.orderhash.bytes,(uint8_t *)rp,sizeof(*rp));
swap->I.req = *rp;
G.LP_skipstatus[G.LP_numskips] = ((uint64_t)rp->requestid << 32) | rp->quoteid;
if ( G.LP_numskips < sizeof(G.LP_skipstatus)/sizeof(*G.LP_skipstatus) )
G.LP_numskips++;
printf("basilisk_thread_start request.%u iambob.%d (%s/%s) quoteid.%u\n",rp->requestid,iambob,rp->src,rp->dest,rp->quoteid);
bitcoin_pubkey33(swap->ctx,pubkey33,privkey);
pubkey25519 = curve25519(privkey,curve25519_basepoint9());

108
iguana/exchanges/LP_transaction.c

@ -19,19 +19,40 @@
// marketmaker
//
int32_t LP_gettx_presence(char *symbol,bits256 expectedtxid)
{
cJSON *txobj; bits256 txid; int32_t flag = 0;
if ( (txobj= LP_gettx(symbol,expectedtxid)) != 0 )
{
txid = jbits256(txobj,"txid");
if ( jobj(txobj,"error") == 0 && bits256_cmp(txid,expectedtxid) == 0 )
{
//char str[65]; printf("%s already in gettx (%s)\n",bits256_str(str,txid),jprint(txobj,0));
flag = 1;
}
free_json(txobj);
}
return(flag);
}
bits256 LP_broadcast(char *txname,char *symbol,char *txbytes,bits256 expectedtxid)
{
char *retstr; bits256 txid; cJSON *retjson,*errorobj; int32_t i,sentflag = 0;
memset(&txid,0,sizeof(txid));
for (i=0; i<1; i++)
for (i=0; i<2; i++)
{
if ( (retstr= LP_sendrawtransaction(symbol,txbytes)) != 0 )
if ( sentflag == 0 && LP_gettx_presence(symbol,expectedtxid) != 0 )
sentflag = 1;
if ( sentflag == 0 && (retstr= LP_sendrawtransaction(symbol,txbytes)) != 0 )
{
if ( is_hexstr(retstr,0) == 64 )
{
decode_hex(txid.bytes,32,retstr);
if ( bits256_cmp(txid,expectedtxid) == 0 || (bits256_nonz(expectedtxid) == 0 && bits256_nonz(txid) != 0) )
{
sentflag = 1;
expectedtxid = txid;
}
}
else if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
@ -50,7 +71,10 @@ bits256 LP_broadcast(char *txname,char *symbol,char *txbytes,bits256 expectedtxi
}
if ( sentflag != 0 )
break;
sleep(3);
}
if ( sentflag != 0 )
return(expectedtxid);
return(txid);
}
@ -396,7 +420,7 @@ int64_t iguana_lockval(int32_t finalized,int64_t locktime)
int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,struct iguana_msgtx *msgtx,char **signedtxp,bits256 *signedtxidp,struct vin_info *V,int32_t numinputs,char *rawtx,cJSON *vins,cJSON *privkeysjson)
{
uint8_t *serialized,*serialized2,*serialized3,*serialized4,*extraspace,pubkeys[64][33]; int32_t finalized,i,len,n,z,plen,maxsize,complete = 0,extralen = 65536; char *privkeystr,*signedtx = 0; bits256 privkeys[64],privkey,txid; cJSON *item; cJSON *txobj = 0;
uint8_t *serialized,*serialized2,*serialized3,*serialized4,*extraspace,pubkeys[64][33]; int32_t finalized,i,len,n,z,plen,maxsize,complete = 0,extralen = 100000; char *privkeystr,*signedtx = 0; bits256 privkeys[64],privkey,txid; cJSON *item; cJSON *txobj = 0;
maxsize = 1000000;
memset(privkey.bytes,0,sizeof(privkey));
if ( rawtx != 0 && rawtx[0] != 0 && (len= (int32_t)strlen(rawtx)>>1) < maxsize )
@ -417,7 +441,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_
{
//printf("numinputs.%d msgtx.%d\n",numinputs,msgtx->tx_in);
memset(msgtx,0,sizeof(*msgtx));
if ( iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,0,0,serialized,maxsize,msgtx,&txid,"",extraspace,65536,vins,V->suppress_pubkeys) > 0 && numinputs == msgtx->tx_in )
if ( iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,0,0,serialized,maxsize,msgtx,&txid,"",extraspace,extralen,vins,V->suppress_pubkeys) > 0 && numinputs == msgtx->tx_in )
{
memset(pubkeys,0,sizeof(pubkeys));
memset(privkeys,0,sizeof(privkeys));
@ -526,7 +550,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_
char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privkey,bits256 *privkey2p,uint8_t *redeemscript,int32_t redeemlen,uint8_t *userdata,int32_t userdatalen,bits256 utxotxid,int32_t vout,char *destaddr,uint8_t *pubkey33,int32_t finalseqid,uint32_t expiration,int64_t *destamountp,uint64_t satoshis,char *changeaddr,char *vinaddr,int32_t suppress_pubkeys)
{
char *rawtxbytes=0,*signedtx=0,tmpaddr[64],hexstr[999],wifstr[128],txdestaddr[64],_destaddr[64]; uint8_t spendscript[512],addrtype,rmd160[20]; cJSON *txobj,*vins,*item,*privkeys; int32_t completed,spendlen,ignore_cltverr=1; struct vin_info V[2]; uint32_t timestamp,locktime = 0,sequenceid = 0xffffffff * finalseqid; bits256 txid; uint64_t value,change = 0; struct iguana_msgtx msgtx;
char *rawtxbytes=0,*signedtx=0,str[65],tmpaddr[64],hexstr[999],wifstr[128],_destaddr[64]; uint8_t spendscript[512],addrtype,rmd160[20]; cJSON *txobj,*vins,*obj,*vouts,*item,*privkeys; int32_t completed,spendlen,n,ignore_cltverr=1; struct vin_info V[2]; uint32_t timestamp,locktime = 0,sequenceid = 0xffffffff * finalseqid; bits256 txid; uint64_t value=0,change = 0; struct iguana_msgtx msgtx; struct iguana_info *coin;
*destamountp = 0;
memset(signedtxidp,0,sizeof(*signedtxidp));
if ( finalseqid == 0 )
@ -534,15 +558,28 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch
//printf("bobtxspend.%s redeem.[%d]\n",symbol,redeemlen);
if ( redeemlen < 0 )
return(0);
value = 0;
#ifndef BASILISK_DISABLESENDTX
if ( (value= LP_txvalue(txdestaddr,symbol,utxotxid,vout)) == 0 )
if ( (coin= LP_coinfind(symbol)) != 0 )
{
char str[65];
printf("basilisk_swap_bobtxspend.%s %s utxo.(%s) already spent or doesnt exist\n",name,symbol,bits256_str(str,utxotxid));
return(0);
if ( (txobj= LP_gettx(symbol,utxotxid)) != 0 )
{
if ( (vouts= jarray(&n,txobj,"vout")) != 0 && vout < n )
{
obj = jitem(vouts,vout);
value = LP_value_extract(obj,1);
//printf("value in vout.%d %.8f (%s)\n",vout,dstr(value),jprint(txobj,0));
}
free_json(txobj);
//if ( value != 0 )
// gettxout
}
if ( value == 0 )
{
printf("basilisk_swap_bobtxspend.%s %s utxo.(%s) already spent or doesnt exist\n",name,symbol,bits256_str(str,utxotxid));
return(0);
}
}
#else
value = satoshis;
#endif
if ( satoshis != 0 )
{
@ -795,33 +832,13 @@ char *basilisk_swap_Aspend(char *name,char *symbol,uint64_t Atxfee,uint8_t wifta
return(signedtx);
}
int32_t LP_swap_txdestaddr(char *destaddr,bits256 txid,int32_t vout,cJSON *txobj)
{
int32_t n,m,retval = -1; cJSON *vouts,*item,*addresses,*skey; char *addr;
if ( (vouts= jarray(&n,txobj,"vout")) != 0 && vout < n )
{
item = jitem(vouts,vout);
if ( (skey= jobj(item,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 )
{
item = jitem(addresses,0);
if ( (addr= jstr(item,0)) != 0 )
{
safecopy(destaddr,addr,64);
retval = 0;
}
//printf("item.(%s) -> dest.(%s)\n",jprint(item,0),destaddr);
}
}
return(retval);
}
int32_t LP_swap_getcoinaddr(char *symbol,char *coinaddr,bits256 txid,int32_t vout)
{
cJSON *retjson;
coinaddr[0] = 0;
if ( (retjson= LP_gettx(symbol,txid)) != 0 )
{
LP_swap_txdestaddr(coinaddr,txid,vout,retjson);
LP_txdestaddr(coinaddr,txid,vout,retjson);
free_json(retjson);
}
return(coinaddr[0] != 0);
@ -1073,7 +1090,7 @@ int32_t basilisk_bobdeposit_refund(struct basilisk_swap *swap,int32_t delay)
void LP_swap_coinaddr(struct iguana_info *coin,char *coinaddr,uint64_t *valuep,uint8_t *data,int32_t datalen,int32_t v)
{
cJSON *txobj,*vouts,*vout,*addresses,*item,*skey; uint8_t extraspace[32768]; bits256 signedtxid; struct iguana_msgtx msgtx; char *addr; int32_t n,m,suppress_pubkeys = 0;
cJSON *txobj,*vouts,*vout; uint8_t extraspace[32768]; bits256 signedtxid; struct iguana_msgtx msgtx; int32_t n,suppress_pubkeys = 0;
if ( valuep != 0 )
*valuep = 0;
if ( (txobj= bitcoin_data2json(coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->longestchain,&signedtxid,&msgtx,extraspace,sizeof(extraspace),data,datalen,0,suppress_pubkeys)) != 0 )
@ -1083,9 +1100,9 @@ void LP_swap_coinaddr(struct iguana_info *coin,char *coinaddr,uint64_t *valuep,u
{
vout = jitem(vouts,v);
if ( valuep != 0 )
*valuep = LP_value_extract(vout);
*valuep = LP_value_extract(vout,1);
//printf("VOUT.(%s)\n",jprint(vout,0));
if ( (skey= jobj(vout,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 )
/*if ( (skey= jobj(vout,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 )
{
item = jitem(addresses,0);
//printf("item.(%s)\n",jprint(item,0));
@ -1094,7 +1111,8 @@ void LP_swap_coinaddr(struct iguana_info *coin,char *coinaddr,uint64_t *valuep,u
safecopy(coinaddr,addr,64);
//printf("extracted.(%s)\n",coinaddr);
}
}
}*/
LP_destaddr(coinaddr,vout);
}
free_json(txobj);
}
@ -1302,22 +1320,24 @@ int32_t LP_verify_bobdeposit(struct basilisk_swap *swap,uint8_t *data,int32_t da
if ( LP_rawtx_spendscript(swap,swap->bobcoin.longestchain,&swap->bobdeposit,0,data,datalen,0) == 0 )
{
swap->aliceclaim.utxovout = 0;
swap->aliceclaim.utxotxid = swap->bobdeposit.I.signedtxid = LP_broadcast_tx(swap->bobdeposit.name,swap->bobcoin.symbol,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen);
swap->bobdeposit.I.signedtxid = LP_broadcast_tx(swap->bobdeposit.name,swap->bobcoin.symbol,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen);
if ( bits256_nonz(swap->bobdeposit.I.signedtxid) != 0 )
swap->depositunconf = 1;
else swap->bobdeposit.I.signedtxid = swap->bobdeposit.I.actualtxid;
len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen);
swap->aliceclaim.utxotxid = swap->bobdeposit.I.signedtxid;
memcpy(swap->I.userdata_aliceclaim,userdata,len);
swap->I.userdata_aliceclaimlen = len;
bitcoin_address(swap->bobdeposit.p2shaddr,swap->bobcoin.taddr,swap->bobcoin.p2shtype,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen);
strcpy(swap->bobdeposit.I.destaddr,swap->bobdeposit.p2shaddr);
basilisk_dontforget_update(swap,&swap->bobdeposit);
//LP_importaddress(swap->bobcoin.symbol,swap->bobdeposit.I.destaddr);
/*for (i=0; i<swap->bobdeposit.I.datalen; i++)
int32_t i; char str[65]; for (i=0; i<swap->bobdeposit.I.datalen; i++)
printf("%02x",swap->bobdeposit.txbytes[i]);
printf(" <- bobdeposit.%d %s\n",swap->bobdeposit.I.datalen,bits256_str(str,swap->bobdeposit.I.signedtxid));
for (i=0; i<swap->bobdeposit.I.redeemlen; i++)
printf("%02x",swap->bobdeposit.redeemscript[i]);
printf(" <- bobdeposit redeem %d %s suppress.%d\n",i,swap->bobdeposit.I.destaddr,swap->aliceclaim.I.suppress_pubkeys);*/
printf(" <- bobdeposit redeem %d %s suppress.%d\n",i,swap->bobdeposit.I.destaddr,swap->aliceclaim.I.suppress_pubkeys);
memcpy(swap->aliceclaim.redeemscript,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen);
swap->aliceclaim.I.redeemlen = swap->bobdeposit.I.redeemlen;
memcpy(swap->aliceclaim.I.pubkey33,swap->persistent_pubkey33,33);
@ -1325,14 +1345,14 @@ int32_t LP_verify_bobdeposit(struct basilisk_swap *swap,uint8_t *data,int32_t da
retval = 0;
if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.wiftaddr,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->aliceclaim,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,1,swap->changermd160,swap->bobdeposit.I.destaddr)) == 0 )
{
/*for (i=0; i<swap->bobdeposit.I.datalen; i++)
int32_t i; for (i=0; i<swap->bobdeposit.I.datalen; i++)
printf("%02x",swap->bobdeposit.txbytes[i]);
printf(" <- bobdeposit\n");
for (i=0; i<swap->aliceclaim.I.datalen; i++)
printf("%02x",swap->aliceclaim.txbytes[i]);
printf(" <- aliceclaim\n");*/
printf(" <- aliceclaim\n");
//basilisk_txlog(swap,&swap->aliceclaim,swap->I.putduration+swap->I.callduration);
return(LP_waitmempool(swap->bobcoin.symbol,swap->bobdeposit.I.destaddr,swap->bobdeposit.I.signedtxid,10));
return(LP_waitmempool(swap->bobcoin.symbol,swap->bobdeposit.I.destaddr,swap->bobdeposit.I.signedtxid,0,60));
} else printf("error signing aliceclaim suppress.%d vin.(%s)\n",swap->aliceclaim.I.suppress_pubkeys,swap->bobdeposit.I.destaddr);
}
printf("error with bobdeposit\n");
@ -1350,7 +1370,7 @@ int32_t LP_verify_alicepayment(struct basilisk_swap *swap,uint8_t *data,int32_t
if ( bits256_nonz(swap->alicepayment.I.signedtxid) != 0 )
swap->aliceunconf = 1;
basilisk_dontforget_update(swap,&swap->alicepayment);
return(LP_waitmempool(swap->alicecoin.symbol,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,10));
return(LP_waitmempool(swap->alicecoin.symbol,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,60));
//printf("import alicepayment address.(%s)\n",swap->alicepayment.p2shaddr);
//LP_importaddress(swap->alicecoin.symbol,swap->alicepayment.p2shaddr);
return(0);
@ -1397,7 +1417,7 @@ int32_t LP_verify_bobpayment(struct basilisk_swap *swap,uint8_t *data,int32_t da
printf("%02x",swap->alicespend.txbytes[i]);
printf(" <- alicespend\n\n");*/
swap->I.alicespent = 1;
return(LP_waitmempool(swap->bobcoin.symbol,swap->bobpayment.I.destaddr,swap->bobpayment.I.signedtxid,10));
return(LP_waitmempool(swap->bobcoin.symbol,swap->bobpayment.I.destaddr,swap->bobpayment.I.signedtxid,0,60));
} else printf("error signing aliceclaim suppress.%d vin.(%s)\n",swap->alicespend.I.suppress_pubkeys,swap->bobpayment.I.destaddr);
}
printf("error validating bobpayment\n");

534
iguana/exchanges/LP_utxo.c

@ -18,17 +18,383 @@
// marketmaker
//
uint64_t LP_value_extract(cJSON *obj)
// listunspent: valid for local node, mostly valid for electrum
// full node + electrum for external listunspent, gettxout to validate
// pruned node + electrum for external listunspent, gettxout to validate
// full node, network for external listunspent, gettxout to validate
// pruned node, network for external listunspent, gettxout to validate
// electrum only, network for gettxout
// handle spurious errors
// handle invalid data
//REJECT KMD ccee27b53b52ca61bbc9fdc7de5feb0a12c14d4d92639414d372f002cc3d092f/v0 value.468169379 vs 468169380 ({"bestblock":"080400d4216c02d100004fd2f4f3505ddb507b643785e02703d3412feba39fb1","confirmations":2356,"value":4.68169380,"scriptPubKey":{"asm":"0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842 OP_CHECKSIG","hex":"210224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842ac","reqSigs":1,"type":"pubkey","addresses":["RFssbc211PJdVy1bvcvAG5X2N4ovPAoy5o"]},"version":1,"coinbase":true})
uint64_t LP_value_extract(cJSON *obj,int32_t addinterest)
{
double val = 0.; uint64_t value;
double val = 0.; uint64_t value = 0;
if ( (val= jdouble(obj,"amount")) < SMALLVAL )
val = jdouble(obj,"value");
if ( val > SMALLVAL )
value = (val * SATOSHIDEN + 0.0000000049);
else value = 0;
value = (val + 0.0000000049) * SATOSHIDEN;
if ( value != 0 )
{
if ( addinterest != 0 && jobj(obj,"interest") != 0 )
value += (jdouble(obj,"interest") * SATOSHIDEN);
}
return(value);
}
int32_t LP_destaddr(char *destaddr,cJSON *item)
{
int32_t m,retval = -1; cJSON *addresses,*skey; char *addr;
if ( (skey= jobj(item,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 )
{
item = jitem(addresses,0);
if ( (addr= jstr(item,0)) != 0 )
{
safecopy(destaddr,addr,64);
retval = 0;
}
//printf("item.(%s) -> dest.(%s)\n",jprint(item,0),destaddr);
}
return(retval);
}
int32_t LP_txdestaddr(char *destaddr,bits256 txid,int32_t vout,cJSON *txobj)
{
int32_t n,retval = -1; cJSON *vouts;
if ( (vouts= jarray(&n,txobj,"vout")) != 0 && vout < n )
retval = LP_destaddr(destaddr,jitem(vouts,vout));
return(retval);
}
struct LP_address *_LP_address(struct iguana_info *coin,char *coinaddr)
{
struct LP_address *ap = 0;
if ( (ap= _LP_addressfind(coin,coinaddr)) == 0 )
ap = _LP_addressadd(coin,coinaddr);
return(ap);
}
struct LP_address *LP_addressfind(struct iguana_info *coin,char *coinaddr)
{
struct LP_address *ap = 0;
if ( coin != 0 )
{
portable_mutex_lock(&coin->addrmutex);
ap = _LP_addressfind(coin,coinaddr);
portable_mutex_unlock(&coin->addrmutex);
}
return(ap);
}
struct LP_address *LP_address(struct iguana_info *coin,char *coinaddr)
{
struct LP_address *ap = 0;
if ( coin != 0 )
{
portable_mutex_lock(&coin->addrmutex);
ap = _LP_address(coin,coinaddr);
portable_mutex_unlock(&coin->addrmutex);
}
return(ap);
}
int32_t LP_address_minmax(uint64_t *minp,uint64_t *maxp,struct LP_address *ap)
{
struct LP_address_utxo *up,*tmp; int32_t n = 0;
*minp = *maxp = 0;
DL_FOREACH_SAFE(ap->utxos,up,tmp)
{
if ( up->spendheight <= 0 )
{
if ( up->U.value > *maxp )
*maxp = up->U.value;
if ( *minp == 0 || up->U.value < *minp )
*minp = up->U.value;
n++;
}
}
if ( 0 && n > 0 )
printf("n.%d %s min %.8f max %.8f\n",n,ap->coinaddr,dstr(*minp),dstr(*maxp));
return(n);
}
struct LP_utxoinfo *LP_allocated(bits256 txid,int32_t vout)
{
struct LP_utxoinfo *utxo;
if ( (utxo= _LP_utxofind(0,txid,vout)) != 0 && LP_isavailable(utxo) == 0 )
{
char str[65]; printf("%s/v%d not available\n",bits256_str(str,txid),vout);
return(utxo);
}
if ( (utxo= _LP_utxo2find(0,txid,vout)) != 0 && LP_isavailable(utxo) == 0 )
{
char str[65]; printf("%s/v%d not available2\n",bits256_str(str,txid),vout);
return(utxo);
}
if ( (utxo= _LP_utxofind(1,txid,vout)) != 0 && LP_isavailable(utxo) == 0 )
{
char str[65]; printf("%s/v%d not available\n",bits256_str(str,txid),vout);
return(utxo);
}
if ( (utxo= _LP_utxo2find(1,txid,vout)) != 0 && LP_isavailable(utxo) == 0 )
{
char str[65]; printf("%s/v%d not available2\n",bits256_str(str,txid),vout);
return(utxo);
}
return(0);
}
int32_t LP_address_utxo_ptrs(int32_t iambob,struct LP_address_utxo **utxos,int32_t max,struct LP_address *ap)
{
struct LP_address_utxo *up,*tmp; int32_t n = 0;
portable_mutex_lock(&LP_utxomutex);
DL_FOREACH_SAFE(ap->utxos,up,tmp)
{
if ( up->spendheight <= 0 )
{
if ( LP_allocated(up->U.txid,up->U.vout) == 0 )
{
utxos[n++] = up;
if ( n >= max )
break;
}
}
}
portable_mutex_unlock(&LP_utxomutex);
return(n);
}
struct LP_address_utxo *LP_address_utxofind(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout)
{
struct LP_address *ap; struct LP_address_utxo *up,*tmp;
//printf("%s add addr.%s ht.%d\n",coin->symbol,coinaddr,height);
if ( (ap= _LP_address(coin,coinaddr)) != 0 )
{
DL_FOREACH_SAFE(ap->utxos,up,tmp)
{
if ( vout == up->U.vout && bits256_cmp(up->U.txid,txid) == 0 )
return(up);
}
}
return(0);
}
int32_t LP_address_utxoadd(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight)
{
struct LP_address *ap; struct LP_address_utxo *up,*tmp; int32_t flag,retval = 0; char str[65];
//printf("%s add addr.%s ht.%d\n",coin->symbol,coinaddr,height);
if ( coin == 0 )
return(0);
if ( spendheight > 0 ) // dont autocreate entries for spends we dont care about
ap = LP_addressfind(coin,coinaddr);
else ap = LP_address(coin,coinaddr);
if ( ap != 0 )
{
flag = 0;
DL_FOREACH_SAFE(ap->utxos,up,tmp)
{
if ( vout == up->U.vout && bits256_cmp(up->U.txid,txid) == 0 )
{
flag = 1;
if ( up->U.height <= 0 && height > 0 && up->U.height != height )
up->U.height = height, flag |= 2;
if ( spendheight > 0 && up->spendheight != spendheight )
up->spendheight = spendheight, flag |= 4;
if ( up->U.value == 0 && up->U.value != value )
up->U.value = value, flag |= 8;
//printf("found >>>>>>>>>> %s %s %s/v%d ht.%d %.8f\n",coin->symbol,coinaddr,bits256_str(str,txid),vout,height,dstr(value));
break;
}
}
if ( flag == 0 )
{
up = calloc(1,sizeof(*up));
up->U.txid = txid;
up->U.vout = vout;
up->U.height = height;
up->U.value = value;
up->spendheight = spendheight;
portable_mutex_lock(&coin->addrmutex);
DL_APPEND(ap->utxos,up);
portable_mutex_unlock(&coin->addrmutex);
retval = 1;
if ( 0 && height > 0 )
printf("ADDRESS_UTXO >>>>>>>>>> %s %s %s/v%d ht.%d %.8f\n",coin->symbol,coinaddr,bits256_str(str,txid),vout,height,dstr(value));
}
} // else printf("cant get ap %s %s\n",coin->symbol,coinaddr);
//printf("done %s add addr.%s ht.%d\n",coin->symbol,coinaddr,height);
return(retval);
}
cJSON *LP_address_item(struct iguana_info *coin,struct LP_address_utxo *up,int32_t electrumret)
{
cJSON *item = cJSON_CreateObject();
if ( electrumret == 0 )
{
jaddbits256(item,"txid",up->U.txid);
jaddnum(item,"vout",up->U.vout);
jaddnum(item,"confirmations",LP_getheight(coin) - up->U.height);
jaddnum(item,"amount",dstr(up->U.value));
jaddstr(item,"scriptPubKey","");
}
else
{
jaddbits256(item,"tx_hash",up->U.txid);
jaddnum(item,"tx_pos",up->U.vout);
jaddnum(item,"height",up->U.height);
jadd64bits(item,"value",up->U.value);
}
return(item);
}
uint64_t _LP_unspents_metric(uint64_t total,int32_t n) { return((total<<16) | (n & 0xffff)); }
cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrumret)
{
cJSON *array,*item; int32_t n; uint64_t total; struct LP_address *ap=0,*atmp; struct LP_address_utxo *up,*tmp;
array = cJSON_CreateArray();
if ( coinaddr != 0 && coinaddr[0] != 0 )
{
//portable_mutex_lock(&coin->addrmutex);
if ( (ap= _LP_addressfind(coin,coinaddr)) != 0 )
{
total = n = 0;
DL_FOREACH_SAFE(ap->utxos,up,tmp)
{
//char str[65]; printf("LP_address_utxos %s/v%d %.8f ht.%d spend.%d\n",bits256_str(str,up->U.txid),up->U.vout,dstr(up->U.value),up->U.height,up->spendheight);
if ( up->spendheight <= 0 && up->U.height > 0 )
{
jaddi(array,LP_address_item(coin,up,electrumret));
n++;
total += up->U.value;
//printf("new array %s\n",jprint(array,0));
}
}
ap->total = total;
ap->n = n;
}
//portable_mutex_unlock(&coin->addrmutex);
}
else
{
HASH_ITER(hh,coin->addresses,ap,atmp)
{
if ( ap->total > 0 && ap->n > 0 )
{
item = cJSON_CreateObject();
jadd64bits(item,ap->coinaddr,_LP_unspents_metric(ap->total,ap->n));
jaddi(array,item);
}
}
}
//printf("%s %s utxos.(%s) ap.%p\n",coin->symbol,coinaddr,jprint(array,0),ap);
return(array);
}
cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electrumret)
{
cJSON *array,*retjson; int32_t i,n; uint64_t balance = 0;
if ( (array= LP_address_utxos(coin,coinaddr,1)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
balance += j64bits(jitem(array,i),"value");
}
}
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"coin",coin->symbol);
jaddstr(retjson,"address",coinaddr);
jaddnum(retjson,"balance",dstr(balance));
return(retjson);
}
void LP_postutxos(char *symbol,char *coinaddr)
{
bits256 zero; char *msg; struct iguana_info *coin; cJSON *array,*reqjson = cJSON_CreateObject();
if ( (coin= LP_coinfind(symbol)) != 0 && (array= LP_address_utxos(coin,coinaddr,1)) != 0 )
{
//printf("LP_postutxos pubsock.%d %s %s\n",pubsock,symbol,coin->smartaddr);
if ( cJSON_GetArraySize(array) == 0 )
free_json(array);
else
{
memset(zero.bytes,0,sizeof(zero));
jaddstr(reqjson,"method","postutxos");
jaddstr(reqjson,"coin",symbol);
jaddstr(reqjson,"coinaddr",coinaddr);
jadd(reqjson,"utxos",array);
msg = jprint(reqjson,1);
//printf("post (%s) -> %d\n",msg,LP_mypubsock);
LP_broadcast_message(LP_mypubsock,symbol,symbol,zero,msg);
}
}
}
int32_t LP_unspents_array(struct iguana_info *coin,char *coinaddr,cJSON *array)
{
int32_t i,n,v,ht,errs,height,count=0; uint64_t value,val; cJSON *item,*txobj; bits256 txid;
if ( (n= cJSON_GetArraySize(array)) <= 0 )
return(0);
//printf("%s %s LP_unspents.(%s)\n",coin->symbol,coinaddr,jprint(array,0));
for (i=0; i<n; i++)
{
errs = 0;
item = jitem(array,i);
txid = jbits256(item,"tx_hash");
v = jint(item,"tx_pos");
height = jint(item,"height");
val = j64bits(item,"value");
//if ( strcmp(coin->symbol,"LBC") == 0 )
// printf("(%s)\n",jprint(item,0));
if ( coin->electrum == 0 && (txobj= LP_gettxout(coin->symbol,coinaddr,txid,v)) != 0 )
{
value = LP_value_extract(txobj,0);
if ( value != 0 && value != val )
{
char str[65]; printf("REJECT %s %s/v%d value.%llu vs %llu (%s)\n",coin->symbol,bits256_str(str,txid),v,(long long)value,(long long)val,jprint(txobj,0));
errs++;
}
if ( coin->height != 0 )
ht = LP_getheight(coin) - jint(txobj,"confirmations");
else ht = 0;
/*if ( ht != 0 && ht < height-2 )
{
printf("REJECT %s %s/v%d ht.%d vs %d confs.%d (%s)\n",symbol,bits256_str(str,txid),v,ht,height,jint(txobj,"confirmations"),jprint(item,0));
errs++;
}*/
free_json(txobj);
}
if ( errs == 0 )
{
LP_address_utxoadd(coin,coinaddr,txid,v,val,height,-1);
count++;
}
}
return(count);
}
char *LP_postedutxos(cJSON *argjson)
{
int32_t n; char *symbol,*coinaddr; struct LP_address *ap; struct iguana_info *coin; cJSON *array;
//printf("posted.(%s)\n",jprint(argjson,0));
if ( (coinaddr= jstr(argjson,"coinaddr")) != 0 && (symbol= jstr(argjson,"coin")) != 0 && (coin= LP_coinfind(symbol)) != 0 ) // addsig
{
if ( coin->electrum == 0 || (ap= LP_addressfind(coin,coinaddr)) != 0 )
{
if ( (array= jarray(&n,argjson,"utxos")) != 0 )
LP_unspents_array(coin,coinaddr,array);
}
else if ( (array= electrum_address_listunspent(symbol,coin->electrum,&array,coinaddr)) != 0 )
free_json(array);
}
return(clonestr("{\"result\":\"success\"}"));
}
void LP_utxosetkey(uint8_t *key,bits256 txid,int32_t vout)
{
memcpy(key,txid.bytes,sizeof(txid));
@ -38,22 +404,39 @@ void LP_utxosetkey(uint8_t *key,bits256 txid,int32_t 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)];
/*if ( iambob != 0 )
{
static uint32_t counter;
if ( counter++ < 3 )
printf("_LP_utxofind deprecated iambob\n");
return(0);
}*/
LP_utxosetkey(key,txid,vout);
HASH_FIND(hh,LP_utxoinfos[iambob],key,sizeof(key),utxo);
HASH_FIND(hh,G.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)];
/*if ( iambob != 0 )
{
printf("_LP_utxo2find deprecated iambob\n");
return(0);
}*/
LP_utxosetkey(key2,txid2,vout2);
HASH_FIND(hh2,LP_utxoinfos2[iambob],key2,sizeof(key2),utxo);
HASH_FIND(hh2,G.LP_utxoinfos2[iambob],key2,sizeof(key2),utxo);
return(utxo);
}
struct LP_utxoinfo *LP_utxofind(int32_t iambob,bits256 txid,int32_t vout)
{
struct LP_utxoinfo *utxo=0;
/*if ( iambob != 0 )
{
printf("LP_utxofind deprecated iambob\n");
return(0);
}*/
portable_mutex_lock(&LP_utxomutex);
utxo = _LP_utxofind(iambob,txid,vout);
portable_mutex_unlock(&LP_utxomutex);
@ -63,6 +446,11 @@ struct LP_utxoinfo *LP_utxofind(int32_t iambob,bits256 txid,int32_t vout)
struct LP_utxoinfo *LP_utxo2find(int32_t iambob,bits256 txid2,int32_t vout2)
{
struct LP_utxoinfo *utxo=0;
/*if ( iambob != 0 )
{
printf("LP_utxo2find deprecated iambob\n");
return(0);
}*/
portable_mutex_lock(&LP_utxomutex);
utxo = _LP_utxo2find(iambob,txid2,vout2);
portable_mutex_unlock(&LP_utxomutex);
@ -103,12 +491,12 @@ struct LP_transaction *LP_transactionadd(struct iguana_info *coin,bits256 txid,i
uint64_t LP_txinterestvalue(uint64_t *interestp,char *destaddr,struct iguana_info *coin,bits256 txid,int32_t vout)
{
uint64_t interest,value = 0; cJSON *txobj,*sobj,*array; int32_t n=0;
uint64_t interest,value = 0; cJSON *txobj;
*interestp = 0;
destaddr[0] = 0;
if ( (txobj= LP_gettxout(coin->symbol,txid,vout)) != 0 )
if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid,vout)) != 0 )
{
if ( (value= LP_value_extract(txobj)) == 0 )
if ( (value= LP_value_extract(txobj,0)) == 0 )
{
char str[65]; printf("%s LP_txvalue.%s strange utxo.(%s) vout.%d\n",coin->symbol,bits256_str(str,txid),jprint(txobj,0),vout);
}
@ -120,54 +508,34 @@ uint64_t LP_txinterestvalue(uint64_t *interestp,char *destaddr,struct iguana_inf
*interestp = SATOSHIDEN * interest;
}
}
if ( (sobj= jobj(txobj,"scriptPubKey")) != 0 && (array= jarray(&n,sobj,"addresses")) != 0 )
{
strcpy(destaddr,jstri(array,0));
//printf("set destaddr.(%s)\n",destaddr);
if ( n > 1 )
printf("LP_txinterestvalue warning: violation of 1 output assumption n.%d\n",n);
} else printf("LP_txinterestvalue no addresses found?\n");
LP_destaddr(destaddr,txobj);
//char str[65]; printf("dest.(%s) %.8f <- %s.(%s) txobj.(%s)\n",destaddr,dstr(value),coin->symbol,bits256_str(str,txid),jprint(txobj,0));
free_json(txobj);
} //else { char str[65]; printf("null gettxout return %s/v%d\n",bits256_str(str,txid),vout); }
return(value);
}
int32_t LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter)
cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJSON *txobj)
{
struct LP_transaction *tx; char *address; int32_t i,n,height,numvouts,numvins,spentvout; cJSON *txobj,*vins,*vouts,*vout,*vin,*sobj,*addresses; bits256 spenttxid; char str[65];
if ( (txobj= LP_gettx(coin->symbol,txid)) != 0 )
struct LP_transaction *tx; int32_t i,height,numvouts,numvins,spentvout; cJSON *vins,*vouts,*vout,*vin; bits256 spenttxid; char str[65];
if ( txobj != 0 || (txobj= LP_gettx(coin->symbol,txid)) != 0 )
{
//printf("TX.(%s)\n",jprint(txobj,0));
if ( coin->electrum == 0 )
height = LP_txheight(coin,txid);
else height = -1;
vins = jarray(&numvins,txobj,"vin");
vouts = jarray(&numvouts,txobj,"vout");
// maybe filter so only addresses we care about are using RAM
if ( iter == 0 && vouts != 0 && (tx= LP_transactionadd(coin,txid,height,numvouts,numvins)) != 0 )
{
//printf("create txid numvouts.%d numvins.%d\n",numvouts,numvins);
//printf("create txid %s numvouts.%d numvins.%d\n",bits256_str(str,txid),numvouts,numvins);
for (i=0; i<numvouts; i++)
{
vout = jitem(vouts,i);
tx->outpoints[i].value = LP_value_extract(vout);
tx->outpoints[i].value = LP_value_extract(vout,0);
tx->outpoints[i].interest = SATOSHIDEN * jdouble(vout,"interest");
if ( (sobj= jobj(vout,"scriptPubKey")) != 0 )
{
if ( (addresses= jarray(&n,sobj,"addresses")) != 0 && n > 0 )
{
if ( n > 1 )
printf("LP_transactioninit: txid.(%s) multiple addresses.[%s]\n",bits256_str(str,txid),jprint(addresses,0));
if ( (address= jstri(addresses,0)) != 0 && strlen(address) < sizeof(tx->outpoints[i].coinaddr) )
{
strcpy(tx->outpoints[i].coinaddr,address);
//printf("(%s %.8f) ",address,dstr(tx->outpoints[i].value));
} else if ( tx->outpoints[i].value != 0 )
printf("LP_transactioninit: unexpected address.(%s)\n",jprint(addresses,0));
}
//else if ( tx->outpoints[i].value != 0 )
// printf("LP_transactioninit: pax tx ht.%d i.%d (%s) n.%d\n",height,i,jprint(vout,0),n);
}
LP_destaddr(tx->outpoints[i].coinaddr,vout);
LP_address_utxoadd(coin,tx->outpoints[i].coinaddr,txid,i,tx->outpoints[i].value,height,-1);
}
//printf("numvouts.%d\n",numvouts);
}
@ -184,20 +552,24 @@ int32_t LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter)
{
if ( spentvout < tx->numvouts )
{
tx->outpoints[spentvout].spendtxid = txid;
tx->outpoints[spentvout].spendvini = i;
tx->outpoints[spentvout].spendheight = height;
//printf("spend %s %s/v%d at ht.%d\n",coin->symbol,bits256_str(str,tx->txid),spentvout,height);
} else printf("LP_transactioninit: %s spentvout.%d < numvouts.%d\n",bits256_str(str,spenttxid),spentvout,tx->numvouts);
if ( tx->outpoints[spentvout].spendheight <= 0 )
{
tx->outpoints[spentvout].spendtxid = txid;
tx->outpoints[spentvout].spendvini = i;
tx->outpoints[spentvout].spendheight = height > 0 ? height : 1;
LP_address_utxoadd(coin,tx->outpoints[spentvout].coinaddr,spenttxid,spentvout,tx->outpoints[spentvout].value,-1,height>0?height:1);
if ( 0 && strcmp(coin->symbol,"BTC") != 0 )
printf("spend %s %s/v%d at ht.%d\n",coin->symbol,bits256_str(str,tx->txid),spentvout,height);
}
} else printf("LP_transactioninit: %s spentvout.%d < numvouts.%d spendheight.%d\n",bits256_str(str,spenttxid),spentvout,tx->numvouts,tx->outpoints[spentvout].spendheight);
} //else printf("LP_transactioninit: couldnt find (%s) ht.%d %s\n",bits256_str(str,spenttxid),height,jprint(vin,0));
if ( bits256_cmp(spenttxid,txid) == 0 )
printf("spending same tx's %p vout ht.%d %s.[%d] s%d\n",tx,height,bits256_str(str,txid),tx!=0?tx->numvouts:0,spentvout);
}
}
free_json(txobj);
return(0);
return(txobj);
} //else printf("LP_transactioninit error for %s %s\n",coin->symbol,bits256_str(str,txid));
return(-1);
return(0);
}
int32_t LP_txheight(struct iguana_info *coin,bits256 txid)
@ -229,21 +601,18 @@ int32_t LP_txheight(struct iguana_info *coin,bits256 txid)
return(height);
}
int32_t LP_numconfirms(char *symbol,char *coinaddr,bits256 txid,int32_t mempool)
int32_t LP_numconfirms(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t mempool)
{
struct iguana_info *coin; int32_t ht,numconfirms = 100;
//#ifndef BASILISK_DISABLEWAITTX
cJSON *txobj;
if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 )
return(-1);
if ( coin->electrum == 0 )
{
numconfirms = -1;
if ( (txobj= LP_gettx(symbol,txid)) != 0 )
if ( (txobj= LP_gettxout(symbol,coinaddr,txid,vout)) != 0 )
{
if ( coin->electrum == 0 )
numconfirms = jint(txobj,"confirmations");
else numconfirms = coin->height - jint(txobj,"height");
numconfirms = jint(txobj,"confirmations");
free_json(txobj);
}
else if ( mempool != 0 && LP_mempoolscan(symbol,txid) >= 0 )
@ -251,12 +620,15 @@ int32_t LP_numconfirms(char *symbol,char *coinaddr,bits256 txid,int32_t mempool)
}
else
{
LP_listunspent_issue(symbol,coinaddr);
if ( (ht= LP_txheight(coin,txid)) > 0 && ht <= coin->height )
numconfirms = (coin->height - ht);
else if ( mempool != 0 && LP_waitmempool(symbol,coinaddr,txid,-1) >= 0 )
numconfirms = 0;
numconfirms = (LP_getheight(coin) - ht + 1);
else if ( mempool != 0 )
{
if ( LP_waitmempool(symbol,coinaddr,txid,vout,30) >= 0 )
numconfirms = 0;
}
}
//#endif
return(numconfirms);
}
@ -272,7 +644,7 @@ int64_t basilisk_txvalue(char *symbol,bits256 txid,int32_t vout)
uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout)
{
struct LP_transaction *tx; cJSON *txobj; uint64_t value; struct iguana_info *coin; char str[65],str2[65];
struct LP_transaction *tx; cJSON *txobj=0; uint64_t value; struct iguana_info *coin; char str[65],_coinaddr[65];
if ( bits256_nonz(txid) == 0 )
return(0);
if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 )
@ -281,8 +653,10 @@ uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout)
coinaddr[0] = 0;
if ( (tx= LP_transactionfind(coin,txid)) == 0 )
{
LP_transactioninit(coin,txid,0);
LP_transactioninit(coin,txid,1);
txobj = LP_transactioninit(coin,txid,0,0);
txobj = LP_transactioninit(coin,txid,1,txobj);
if ( txobj != 0 )
free_json(txobj);
tx = LP_transactionfind(coin,txid);
}
if ( tx != 0 )
@ -291,7 +665,7 @@ uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout)
{
if ( bits256_nonz(tx->outpoints[vout].spendtxid) != 0 )
{
printf("LP_txvalue %s/v%d is spent at %s\n",bits256_str(str,txid),vout,bits256_str(str2,tx->outpoints[vout].spendtxid));
//printf("LP_txvalue %s/v%d is spent at %s\n",bits256_str(str,txid),vout,bits256_str(str2,tx->outpoints[vout].spendtxid));
return(0);
}
else
@ -303,20 +677,28 @@ uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout)
strcpy(coinaddr,tx->outpoints[vout].coinaddr);
//printf("(%s) return value %.8f + interest %.8f\n",coinaddr,dstr(tx->outpoints[vout].value),dstr(tx->outpoints[vout].interest));
}
return(tx->outpoints[vout].value + tx->outpoints[vout].interest);
return(tx->outpoints[vout].value + 0*tx->outpoints[vout].interest);
}
} else printf("LP_txvalue vout.%d >= tx->numvouts.%d\n",vout,tx->numvouts);
}
else
{
if ( (txobj= LP_gettxout(coin->symbol,txid,vout)) != 0 )
if ( (txobj= LP_gettxout(coin->symbol,coinaddr,txid,vout)) != 0 )
{
value = SATOSHIDEN * jdouble(txobj,"value");
free_json(txobj);
printf("pruned node? LP_txvalue couldnt find %s tx %s, but gettxout %.8f\n",coin->symbol,bits256_str(str,txid),dstr(value));
return(value);
value = LP_value_extract(txobj,0);//SATOSHIDEN * (jdouble(txobj,"value") + jdouble(txobj,"interest"));
if ( coinaddr == 0 )
coinaddr = _coinaddr;
LP_destaddr(coinaddr,txobj);
//printf("pruned node? LP_txvalue couldnt find %s tx %s, but gettxout %.8f\n",coin->symbol,bits256_str(str,txid),dstr(value));
if ( value != 0 )
{
free_json(txobj);
return(value);
}
}
printf("pruned node? LP_txvalue couldnt find %s tx %s\n",coin->symbol,bits256_str(str,txid));
printf("pruned node? LP_txvalue couldnt find %s tx %s/v%d (%s)\n",coin->symbol,bits256_str(str,txid),vout,txobj!=0?jprint(txobj,0):"");
if ( txobj != 0 )
free_json(txobj);
}
return(0);
}
@ -324,7 +706,7 @@ uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout)
int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2)
{
//struct LP_utxoinfo *utxo;
uint64_t val,val2=0,txfee,threshold=0; int32_t bypass = 0; char destaddr[64],destaddr2[64]; struct iguana_info *coin = LP_coinfind(symbol);
struct LP_address_utxo *up; uint64_t val,val2=0,txfee,threshold=0; int32_t bypass = 0; char destaddr[64],destaddr2[64]; struct iguana_info *coin = LP_coinfind(symbol);
if ( bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 )
{
printf("null txid not eligible\n");
@ -336,6 +718,10 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol
if ( bypass != 0 )
val = satoshis;
else val = LP_txvalue(destaddr,symbol,txid,vout);
if ( (up= LP_address_utxofind(coin,destaddr,txid,vout)) != 0 && up->spendheight > 0 )
return(-2);
if ( (up= LP_address_utxofind(coin,destaddr,txid2,vout2)) != 0 && up->spendheight > 0 )
return(-3);
txfee = LP_txfeecalc(LP_coinfind(symbol),0);
if ( val >= satoshis && val > (1+LP_MINSIZE_TXFEEMULT)*txfee )
{
@ -357,7 +743,13 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol
}
} // else printf("no val2\n");
}
char str[65],str2[65]; printf("spent.%d %s txid or value %.8f < %.8f or val2 %.8f < %.8f, %s/v%d %s/v%d or < 10x txfee %.8f\n",iambob,symbol,dstr(val),dstr(satoshis),dstr(val2),dstr(threshold),bits256_str(str,txid),vout,bits256_str(str2,txid2),vout2,dstr(txfee));
char str[65],str2[65];
if ( val != 0 && val2 != 0 )
printf("spent.%d %s txid or value %.8f < %.8f or val2 %.8f < %.8f, %s/v%d %s/v%d or < 10x txfee %.8f\n",iambob,symbol,dstr(val),dstr(satoshis),dstr(val2),dstr(threshold),bits256_str(str,txid),vout,bits256_str(str2,txid2),vout2,dstr(txfee));
if ( val == 0 )
LP_address_utxoadd(coin,destaddr,txid,vout,satoshis,-1,1);
if ( val2 == 0 )
LP_address_utxoadd(coin,destaddr,txid2,vout2,threshold,-1,1);
/*for (iter=0; iter<2; iter++)
{
if ( (utxo= LP_utxofind(iter,txid,vout)) != 0 )
@ -403,7 +795,7 @@ int32_t LP_inventory_prevent(int32_t iambob,char *symbol,bits256 txid,int32_t vo
}
if ( utxo->T.spentflag != 0 )
{
char str[65]; printf("prevent adding iambob.%d %s/v%d to inventory\n",iambob,bits256_str(str,txid),vout);
//char str[65]; printf("prevent adding iambob.%d %s/v%d to inventory\n",iambob,bits256_str(str,txid),vout);
return(1);
}
}

495
iguana/exchanges/LP_utxos.c

@ -20,7 +20,7 @@
int32_t LP_ismine(struct LP_utxoinfo *utxo)
{
if ( utxo != 0 && bits256_cmp(utxo->pubkey,LP_mypub25519) == 0 )
if ( utxo != 0 && bits256_cmp(utxo->pubkey,G.LP_mypub25519) == 0 )
return(1);
else return(0);
}
@ -154,46 +154,10 @@ void LP_availableset(struct LP_utxoinfo *utxo)
}
}
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_mypub25519));
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","utxo");
//jaddstr(item,"method","oldutxo");
if ( utxo == 0 )
return(item);
if ( utxo->gui[0] != 0 )
@ -242,54 +206,27 @@ cJSON *LP_utxojson(struct LP_utxoinfo *utxo)
jaddbits256(item,"pubkey",utxo->pubkey);
//jaddnum(item,"profit",utxo->S.profitmargin);
jaddstr(item,"base",utxo->coin);
jaddstr(item,"script",utxo->spendscript);
//jaddstr(item,"script",utxo->spendscript);
return(item);
}
char *LP_utxos(int32_t iambob,struct LP_peerinfo *mypeer,char *symbol,int32_t lastn)
{
int32_t i,n,m; uint64_t val,val2; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray();
//n = mypeer != 0 ? mypeer->numutxos : 0;
if ( lastn <= 0 )
lastn = LP_PROPAGATION_SLACK * 2;
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 ( (symbol == 0 || symbol[0] == 0 || strcmp(symbol,utxo->coin) == 0) && utxo->T.spentflag == 0 )
{
u = (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) == 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));
}
}
if ( (n= cJSON_GetArraySize(utxosjson)) > lastn )
{
m = n - lastn;
for (i=0; i<m; i++)
cJSON_DeleteItemFromArray(utxosjson,0);
}
return(jprint(utxosjson,1));
}
struct LP_utxoinfo *LP_utxo_bestfit(char *symbol,uint64_t destsatoshis)
{
uint64_t srcvalue,srcvalue2; struct LP_utxoinfo *utxo,*tmp,*bestutxo = 0;
uint64_t srcvalue,srcvalue2; struct LP_utxoinfo *utxo,*tmp,*bestutxo = 0; int32_t iambob = 0;
if ( symbol == 0 || destsatoshis == 0 )
{
printf("LP_utxo_bestfit error symbol.%p %.8f\n",symbol,dstr(destsatoshis));
return(0);
}
HASH_ITER(hh,LP_utxoinfos[0],utxo,tmp)
// jl777 remove mempool
HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,tmp)
{
//char str[65]; printf("s%u %d [%.8f vs %.8f] check %s.%s avail.%d ismine.%d >= %d\n",utxo->T.spentflag,LP_iseligible(&srcvalue,&srcvalue2,utxo->iambob,symbol,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,utxo->fee.txid,utxo->fee.vout),dstr(destsatoshis),dstr(utxo->S.satoshis),utxo->coin,bits256_str(str,utxo->payment.txid),LP_isavailable(utxo) > 0,LP_ismine(utxo) > 0,utxo->S.satoshis >= destsatoshis);
if ( strcmp(symbol,utxo->coin) != 0 )
continue;
if ( LP_isavailable(utxo) > 0 && LP_ismine(utxo) > 0 )
{
if ( utxo->S.satoshis >= destsatoshis/2 && (bestutxo == 0 || (bestutxo->S.satoshis < destsatoshis && utxo->S.satoshis >= destsatoshis) || (bestutxo->S.satoshis >= destsatoshis && utxo->S.satoshis < bestutxo->S.satoshis)) )
if ( utxo->S.satoshis >= destsatoshis && (bestutxo == 0 || (bestutxo->S.satoshis < destsatoshis && utxo->S.satoshis >= destsatoshis) || (bestutxo->S.satoshis >= destsatoshis && utxo->S.satoshis < bestutxo->S.satoshis)) )
{
if ( LP_iseligible(&srcvalue,&srcvalue2,utxo->iambob,symbol,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,utxo->fee.txid,utxo->fee.vout) == 0 )
{
@ -306,29 +243,9 @@ struct LP_utxoinfo *LP_utxo_bestfit(char *symbol,uint64_t destsatoshis)
void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector)
{
//cJSON *argjson; struct _LP_utxoinfo u; char *msg;
if ( utxo == 0 )
return;
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)
@ -349,8 +266,8 @@ char *LP_spentcheck(cJSON *argjson)
}
if ( LP_txvalue(0,utxo->coin,checktxid,checkvout) == 0 )
{
if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 )
LP_mypeer->numutxos--;
//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");
@ -362,45 +279,20 @@ char *LP_spentcheck(cJSON *argjson)
return(clonestr("{\"error\":\"cant find txid to check spent status\"}"));
}
void LP_utxo_clientpublish(struct LP_utxoinfo *utxo)
{
bits256 zero; char *msg;
if ( LP_isunspent(utxo) > 0 )
{
memset(zero.bytes,0,sizeof(zero));
msg = jprint(LP_utxojson(utxo),1);
LP_broadcast_message(LP_mypubsock,utxo->coin,"",zero,msg);
}
/*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 )
{
utxo->T.lasttime = (uint32_t)time(NULL);
n++;
}
free_json(retjson);
}
free(retstr);
}
//if ( utxo->T.lasttime != 0 )
// return(0);
}
return(n);*/
}
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,char *gui,uint32_t sessionid)
struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t vout,int64_t value,bits256 txid2,int32_t vout2,int64_t value2,char *coinaddr,bits256 pubkey,char *gui,uint32_t sessionid)
{
uint64_t val,val2=0,tmpsatoshis,txfee; int32_t spendvini,numconfirms,selector; bits256 spendtxid; struct iguana_info *coin; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo = 0;
if ( symbol == 0 || symbol[0] == 0 || 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 || sessionid == 0 )
if ( symbol == 0 || symbol[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 || vout < 0 || vout2 < 0 || value <= 0 || value2 <= 0 )//|| sessionid == 0 )
{
printf("session.%u malformed addutxo %d %d %d %d %d %d %d %d %d\n",sessionid,symbol == 0,spendscript == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(txid2) == 0,vout < 0,vout2 < 0,value <= 0,value2 <= 0);
char str[65],str2[65]; printf("REJECT %s iambob.%d %s utxoadd.(%.8f %.8f) %s %s\n",coinaddr,iambob,symbol,dstr(value),dstr(value2),bits256_str(str,txid),bits256_str(str2,txid2));
printf("session.%u addutxo %d %d %d %d %d %d %d %d\n",sessionid,symbol == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(txid2) == 0,vout < 0,vout2 < 0,value <= 0,value2 <= 0);
return(0);
}
/*if ( iambob != 0 )
{
printf("deprecated bob utxos\n");
return(0);
}*/
if ( (coin= LP_coinfind(symbol)) == 0 || (IAMLP == 0 && coin->inactive != 0) )
{
//printf("LP_utxoadd reject inactive %s\n",symbol);
@ -411,48 +303,33 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit
{
if ( value2 > 2*txfee )
tmpsatoshis = (((value2 - 2*txfee) / 9) << 3);
else return(0);
else
{
printf("value2 %.8f <= 2 * %.8f\n",dstr(value2),dstr(txfee));
return(0);
}
} else tmpsatoshis = (value - txfee);
char str[65],str2[65],dispflag = (iambob == 0);
if ( iambob == 0 && bits256_cmp(pubkey,LP_mypub25519) != 0 )
char str[65],str2[65],dispflag = 0;//(iambob == 0);
if ( iambob == 0 && bits256_cmp(pubkey,G.LP_mypub25519) != 0 )
{
printf("trying to add Alice utxo when not mine? %s/v%d\n",bits256_str(str,txid),vout);
return(0);
}
/*numconfirms = -1;
if ( (txobj= LP_gettx(symbol,txid)) != 0 )
{
if ( coin->electrum == 0 )
numconfirms = jint(txobj,"confirmations");
else numconfirms = coin->height - jint(txobj,"height");
free_json(txobj);
}
numconfirms = -1;
if ( (txobj= LP_gettx(symbol,txid2)) != 0 )
{
if ( coin->electrum == 0 )
numconfirms = jint(txobj,"confirmations");
else numconfirms = coin->height - jint(txobj,"height");
free_json(txobj);
}
if ( numconfirms <= 0 )
{
printf("LP_utxoadd reject2 numconfirms.%d\n",numconfirms);
return(0);
}*/
if ( coin->inactive == 0 )
{
if ( LP_iseligible(&val,&val2,iambob,symbol,txid,vout,tmpsatoshis,txid2,vout2) <= 0 )
{
printf("iambob.%d utxoadd %s inactive.%u got ineligible txid value %.8f:%.8f, value2 %.8f:%.8f, tmpsatoshis %.8f\n",iambob,symbol,coin->inactive,dstr(value),dstr(val),dstr(value2),dstr(val2),dstr(tmpsatoshis));
static uint32_t counter;
if ( counter++ < 3 )
printf("iambob.%d utxoadd %s inactive.%u got ineligible txid value %.8f:%.8f, value2 %.8f:%.8f, tmpsatoshis %.8f\n",iambob,symbol,coin->inactive,dstr(value),dstr(val),dstr(value2),dstr(val2),dstr(tmpsatoshis));
return(0);
}
if ( (numconfirms= LP_numconfirms(symbol,coinaddr,txid,0)) <= 0 )
if ( (numconfirms= LP_numconfirms(symbol,coinaddr,txid,vout,0)) <= 0 )
{
printf("LP_utxoadd reject numconfirms.%d %s.%s\n",numconfirms,symbol,bits256_str(str,txid));
return(0);
}
if ( (numconfirms= LP_numconfirms(symbol,coinaddr,txid2,0)) <= 0 )
if ( (numconfirms= LP_numconfirms(symbol,coinaddr,txid2,vout2,0)) <= 0 )
{
printf("LP_utxoadd reject2 numconfirms.%d\n",numconfirms);
return(0);
@ -463,6 +340,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit
val = value;
val2 = value2;
}
dispflag = 0;
if ( dispflag != 0 )
printf("%.8f %.8f %s iambob.%d %s utxoadd.(%.8f %.8f) %s %s\n",dstr(val),dstr(val2),coinaddr,iambob,symbol,dstr(value),dstr(value2),bits256_str(str,txid),bits256_str(str2,txid2));
dispflag = 1;
@ -474,7 +352,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit
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 )
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(coinaddr,utxo->coinaddr) != 0 || bits256_cmp(pubkey,utxo->pubkey) != 0 )
{
utxo->T.errors++;
char str[65],str2[65],str3[65],str4[65],str5[65],str6[65];
@ -484,7 +362,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit
// utxo->T.spentflag = (uint32_t)time(NULL);
printf("original utxo pair not valid\n");
if ( dispflag != 0 )
printf("error on subsequent utxo iambob.%d %.8f %.8f add.(%s %s) when.(%s %s) %d %d %d %d %d %d %d %d %d %d %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));
printf("error on subsequent utxo iambob.%d %.8f %.8f add.(%s %s) when.(%s %s) %d %d %d %d %d %d %d %d %d %d pubkeys.(%s vs %s)\n",iambob,dstr(val),dstr(val2),bits256_str(str,txid),bits256_str(str2,txid2),bits256_str(str3,utxo->payment.txid),bits256_str(str4,utxo->deposit.txid),bits256_cmp(txid,utxo->payment.txid) != 0,bits256_cmp(txid2,u.txid) != 0,vout != utxo->payment.vout,tmpsatoshis != utxo->S.satoshis,vout2 != u.vout,value2 != u.value,strcmp(symbol,utxo->coin) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,bits256_cmp(pubkey,utxo->pubkey) != 0,value != utxo->payment.value,bits256_str(str5,pubkey),bits256_str(str6,utxo->pubkey));
utxo = 0;
}
}
@ -495,6 +373,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit
//else if ( profitmargin > SMALLVAL )
// utxo->S.profitmargin = profitmargin;
utxo->T.lasttime = (uint32_t)time(NULL);
//printf("return existing utxo[%d] %s %s\n",iambob,bits256_str(str,utxo->payment.txid),bits256_str(str2,iambob != 0 ? utxo->deposit.txid : utxo->fee.txid));
return(utxo);
}
}
@ -504,7 +383,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit
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));
//safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript));
utxo->payment.txid = txid;
utxo->payment.vout = vout;
utxo->payment.value = value;
@ -524,31 +403,24 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit
LP_utxosetkey(utxo->key,txid,vout);
LP_utxosetkey(utxo->key2,txid2,vout2);
if ( LP_ismine(utxo) > 0 )
utxo->T.sessionid = LP_sessionid;
utxo->T.sessionid = G.LP_sessionid;
else utxo->T.sessionid = sessionid;
if ( coin->inactive == 0 && (selector= LP_mempool_vinscan(&spendtxid,&spendvini,symbol,coinaddr,txid,vout,txid2,vout2)) >= 0 )
{
printf("utxoadd selector.%d spent in mempool %s vini.%d",selector,bits256_str(str,spendtxid),spendvini);
utxo->T.spentflag = (uint32_t)time(NULL);
}
printf("U.%d %s %.8f %.8f addutxo.%d pubkey.%s session.%u\n",LP_mypeer!=0?LP_mypeer->numutxos:-1,symbol,dstr(value),dstr(value2),LP_ismine(utxo) > 0,bits256_str(str,utxo->pubkey),utxo->T.sessionid);
//printf(" %s %.8f %.8f %p addutxo.%d (%s %s) session.%u iambob.%d <<<<<<<<<<<<<<<\n",symbol,dstr(value),dstr(value2),utxo,LP_ismine(utxo) > 0,bits256_str(str,utxo->payment.txid),bits256_str(str2,iambob != 0 ? utxo->deposit.txid : utxo->fee.txid),utxo->T.sessionid,iambob);
portable_mutex_lock(&LP_utxomutex);
HASH_ADD_KEYPTR(hh,LP_utxoinfos[iambob],utxo->key,sizeof(utxo->key),utxo);
HASH_ADD_KEYPTR(hh,G.LP_utxoinfos[iambob],utxo->key,sizeof(utxo->key),utxo);
if ( _LP_utxo2find(iambob,txid2,vout2) == 0 )
HASH_ADD_KEYPTR(hh2,LP_utxoinfos2[iambob],utxo->key2,sizeof(utxo->key2),utxo);
HASH_ADD_KEYPTR(hh2,G.LP_utxoinfos2[iambob],utxo->key2,sizeof(utxo->key2),utxo);
portable_mutex_unlock(&LP_utxomutex);
/*if ( 0 && coin->electrum == 0 )
{
LP_address_utxoadd(coin,coinaddr,txid,vout,value);
LP_address_utxoadd(coin,coinaddr,txid2,vout2,value2);
}*/
if ( iambob != 0 )
{
if ( LP_mypeer != 0 )
LP_mypeer->numutxos++;
if ( LP_ismine(utxo) > 0 )
{
LP_utxo_clientpublish(utxo);
//LP_utxo_clientpublish(utxo);
if ( LP_mypeer != 0 )
utxo->T.lasttime = (uint32_t)time(NULL);
}
@ -556,110 +428,16 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit
return(utxo);
}
struct LP_utxoinfo *LP_utxoaddjson(int32_t iambob,int32_t pubsock,cJSON *argjson)
{
struct LP_utxoinfo *utxo;
if ( jobj(argjson,"iambob") == 0 || iambob != jint(argjson,"iambob") )
{
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"),jstr(argjson,"gui"),juint(argjson,"session"));
if ( LP_ismine(utxo) > 0 && utxo->T.lasttime == 0 )
{
utxo->T.lasttime = (uint32_t)time(NULL);
printf("set lasttime!\n");
}
portable_mutex_unlock(&LP_UTXOmutex);
return(utxo);
}
int32_t LP_utxosparse(char *destipaddr,uint16_t destport,char *retstr,uint32_t now)
cJSON *LP_inventory(char *symbol)
{
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 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( (argipaddr= jstr(item,"ipaddr")) != 0 && (argport= juint(item,"port")) != 0 )
{
if ( (pushport= juint(item,"push")) == 0 )
pushport = argport + 1;
if ( (subport= juint(item,"sub")) == 0 )
subport = argport + 2;
argipbits = (uint32_t)calc_ipbits(argipaddr);
if ( (peer= LP_peerfind(argipbits,argport)) == 0 )
peer = LP_addpeer(0,-1,argipaddr,argport,pushport,subport,jint(item,"numpeers"),jint(item,"numutxos"),juint(item,"session"));
}
if ( jobj(item,"txid") != 0 )
{
txid = jbits256(item,"txid");
//printf("parse.(%s)\n",jprint(item,0));
if ( (utxo= LP_utxoaddjson(1,-1,item)) != 0 )
utxo->T.lasttime = now;
}
}
if ( (destpeer= LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport)) != 0 )
{
destpeer->numutxos = n;
}
}
free_json(array);
}
return(n);
}
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,int32_t maxentries)
{
char *retstr; struct LP_peerinfo *peer; uint32_t now; int32_t retval = -1;
peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport);
if ( coin == 0 )
coin = "";
//printf("utxo query.(%s)\n",destipaddr);
if ( IAMLP != 0 )
retstr = issue_LP_getutxos(destipaddr,destport,coin,lastn,myipaddr,myport,mypeer != 0 ? mypeer->numpeers : 0,maxentries);
else retstr = issue_LP_clientgetutxos(destipaddr,destport,coin,maxentries);
if ( retstr != 0 )
{
now = (uint32_t)time(NULL);
retval = LP_utxosparse(destipaddr,destport,retstr,now);
//printf("got.(%s)\n",retstr);
free(retstr);
/*i = 0;
if ( lastn >= mypeer->numutxos )
firsti = -1;
else firsti = (mypeer->numutxos - lastn);
HASH_ITER(hh,LP_utxoinfos,utxo,tmp)
{
if ( i++ < firsti )
continue;
if ( utxo->lasttime != now && strcmp(utxo->ipaddr,"127.0.0.1") != 0 )
{
char str[65]; printf("{%s:%u %s} ",utxo->ipaddr,utxo->port,bits256_str(str,utxo->txid));
flag++;
if ( (retstr= issue_LP_notifyutxo(destipaddr,destport,utxo)) != 0 )
free(retstr);
}
}
if ( flag != 0 )
printf(" <- missing utxos\n");*/
}
return(retval);
}
cJSON *LP_inventory(char *symbol,int32_t iambob)
{
struct LP_utxoinfo *utxo,*tmp; struct _LP_utxoinfo u; char *myipaddr; cJSON *array; uint64_t val,val2;
struct LP_utxoinfo *utxo,*tmp; struct _LP_utxoinfo u; char *myipaddr; cJSON *array; uint64_t val,val2; int32_t iambob = 0; struct iguana_info *coin;
array = cJSON_CreateArray();
if ( LP_mypeer != 0 )
myipaddr = LP_mypeer->ipaddr;
else myipaddr = "127.0.0.1";
HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp)
if ( (coin= LP_coinfind(symbol)) != 0 )
LP_listunspent_both(symbol,coin->smartaddr);
HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,tmp)
{
char str[65];
//printf("iambob.%d iterate %s\n",iambob,bits256_str(str,LP_mypub25519));
@ -673,8 +451,8 @@ cJSON *LP_inventory(char *symbol,int32_t iambob)
printf("%s %s ineligible %.8f %.8f\n",utxo->coin,bits256_str(str,u.txid),dstr(val),dstr(val2));
continue;
}
if ( iambob != 0 )
LP_utxo_clientpublish(utxo);
//if ( iambob != 0 )
// LP_utxo_clientpublish(utxo);
jaddi(array,LP_inventoryjson(cJSON_CreateObject(),utxo));
}
else if ( LP_ismine(utxo) > 0 && strcmp(symbol,utxo->coin) == 0 )
@ -713,67 +491,63 @@ int32_t LP_nearestvalue(int32_t iambob,uint64_t *values,int32_t n,uint64_t targe
return(mini);
}
uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 myprivkey,bits256 mypub)
int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 myprivkey,bits256 mypub)
{
char *script,destaddr[64]; struct LP_utxoinfo *utxo; cJSON *array,*item; bits256 txid,deposittxid; int32_t used,i,n,cmpflag,iambob,vout,depositvout; uint64_t *values=0,satoshis,txfee,depositval,value,total = 0; int64_t targetval;
if ( coin == 0 )
int32_t enable_utxos = 0;
char *script,destaddr[64]; struct LP_utxoinfo *utxo; cJSON *array,*item; bits256 txid,deposittxid; int32_t used,i,flag=0,height,n,cmpflag,iambob,vout,depositvout; uint64_t *values=0,satoshis,txfee,depositval,value,total = 0; int64_t targetval;
if ( coin == 0 || coin->inactive != 0 )
{
printf("coin not active\n");
return(0);
}
//printf("privkey init.(%s) %s\n",coin->symbol,coin->smartaddr);
if ( coin->inactive == 0 )
LP_listunspent_issue(coin->symbol,coin->smartaddr);
if ( coin->inactive == 0 && (array= LP_listunspent(coin->symbol,coin->smartaddr)) != 0 )
{
txfee = LP_txfeecalc(coin,0);
if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{
//printf("LP_privkey_init %s %s\n",coin->symbol,jprint(array,0));
for (iambob=0; iambob<=1; iambob++)
{
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);
if ( coin->electrum == 0 )
{
//satoshis = SATOSHIDEN * jdouble(item,"amount");
//if ( satoshis == 0 )
// satoshis = SATOSHIDEN * jdouble(item,"value");
satoshis = LP_txvalue(destaddr,coin->symbol,jbits256(item,"txid"),juint(item,"vout"));
if ( LP_inventory_prevent(iambob,coin->symbol,jbits256(item,"txid"),juint(item,"vout")) == 0 && jint(item,"confirmations") > 0 )
{
//printf("%s\n",jprint(item,0));
values[i] = satoshis;
} else used++;
txid = jbits256(item,"txid");
vout = juint(item,"vout");
value = LP_value_extract(item,0);
height = LP_getheight(coin) - jint(item,"confirmations");
}
else
{
//{"value":1000000,"tx_hash":"4e4f818c53486c0576693b4cd379849e5ff95538b38e4100f48884073a4e7636","tx_pos":0,"height":484877}
satoshis = j64bits(item,"value");
satoshis = LP_txvalue(destaddr,coin->symbol,jbits256(item,"tx_hash"),juint(item,"tx_pos"));
if ( LP_inventory_prevent(iambob,coin->symbol,jbits256(item,"tx_hash"),juint(item,"tx_pos")) == 0 && jint(item,"height") < coin->height )
{
//printf("%s\n",jprint(item,0));
values[i] = satoshis;
}
else
{
printf("skip.(%s) coinht.%d\n",jprint(item,0),coin->height);
used++;
}
txid = jbits256(item,"tx_hash");
vout = juint(item,"tx_pos");
value = j64bits(item,"value");
height = jint(item,"height");
}
//printf("%.8f ",dstr(satoshis));
satoshis = LP_txvalue(destaddr,coin->symbol,txid,vout);
if ( satoshis != 0 && satoshis != value )
printf("unexpected privkey_init value mismatch %.8f vs %.8f (%s) %.8f %.8f\n",dstr(satoshis),dstr(value),jprint(item,0),jdouble(item,"amount"),jdouble(item,"interest"));
if ( LP_inventory_prevent(iambob,coin->symbol,txid,vout) == 0 && height > 0 )
{
//printf("%s\n",jprint(item,0));
values[i] = satoshis;
flag += LP_address_utxoadd(coin,destaddr,txid,vout,satoshis,height,-1);
} else used++;
}
//printf("array.%d\n",n);
while ( used < n-1 )
{
for (i=0; i<n; i++)
printf("%.8f ",dstr(values[i]));
printf("used.%d of n.%d\n",used,n);
//for (i=0; i<n; i++)
// printf("%.8f ",dstr(values[i]));
//printf("used.%d of n.%d\n",used,n);
if ( (i= LP_maxvalue(values,n)) >= 0 )
{
item = jitem(array,i);
@ -796,7 +570,7 @@ uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypr
else targetval = (depositval / 9) * 8 + 2*txfee;
if ( targetval < txfee*2 )
targetval = txfee*2;
printf("iambob.%d i.%d deposit %.8f min %.8f target %.8f\n",iambob,i,dstr(depositval),dstr((1+LP_MINSIZE_TXFEEMULT)*txfee),dstr(targetval));
//printf("iambob.%d i.%d deposit %.8f min %.8f target %.8f\n",iambob,i,dstr(depositval),dstr((1+LP_MINSIZE_TXFEEMULT)*txfee),dstr(targetval));
if ( depositval < (1+LP_MINSIZE_TXFEEMULT)*txfee )
continue;
i = -1;
@ -832,14 +606,14 @@ uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypr
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_gui,LP_sessionid)) != 0 )
if ( (utxo= LP_utxoadd(1,coin->symbol,txid,vout,value,deposittxid,depositvout,depositval,coin->smartaddr,mypub,LP_gui,G.LP_sessionid)) != 0 )
{
}
}
else
{
//printf("call utxoadd\n");
if ( (utxo= LP_utxoadd(0,mypubsock,coin->symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coin->smartaddr,mypub,LP_gui,LP_sessionid)) != 0 )
if ( (utxo= LP_utxoadd(0,coin->symbol,deposittxid,depositvout,depositval,txid,vout,value,coin->smartaddr,mypub,LP_gui,G.LP_sessionid)) != 0 )
{
}
}
@ -849,14 +623,18 @@ uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypr
} //else printf("nothing near i.%d\n",i);
} else break;
}
if ( iambob == 1 )
free(values);
if ( enable_utxos == 0 )
break;
}
}
free_json(array);
if ( flag != 0 )
LP_postutxos(coin->symbol,coin->smartaddr);
}
if ( values != 0 )
free(values);
//printf("privkey.%s %.8f\n",symbol,dstr(total));
return(total);
return(flag);
}
char *LP_secretaddresses(void *ctx,char *passphrase,int32_t n,uint8_t taddr,uint8_t pubtype)
@ -903,7 +681,7 @@ char *LP_secretaddresses(void *ctx,char *passphrase,int32_t n,uint8_t taddr,uint
bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguana_info *coin,char *passphrase,char *wifstr)
{
static uint32_t counter;
//static uint32_t counter;
bits256 privkey,userpub,userpass,checkkey; char tmpstr[128]; cJSON *retjson; uint8_t tmptype;
if ( passphrase != 0 && passphrase[0] != 0 )
{
@ -927,53 +705,110 @@ bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguan
if ( coin->counter == 0 )
{
coin->counter++;
memcpy(G.LP_pubsecp,coin->pubkey33,33);
bitcoin_priv2wif(coin->wiftaddr,tmpstr,privkey,coin->wiftype);
bitcoin_addr2rmd160(coin->taddr,&tmptype,LP_myrmd160,coin->smartaddr);
LP_privkeyadd(privkey,LP_myrmd160);
bitcoin_addr2rmd160(coin->taddr,&tmptype,G.LP_myrmd160,coin->smartaddr);
LP_privkeyadd(privkey,G.LP_myrmd160);
if ( 0 && (coin->pubtype != 60 || strcmp(coin->symbol,"KMD") == 0) )
printf("%s (%s) %d wif.(%s) (%s)\n",coin->symbol,coin->smartaddr,coin->pubtype,tmpstr,passphrase);
if ( counter++ == 0 )
if ( G.counter++ == 0 )
{
bitcoin_priv2wif(coin->wiftaddr,USERPASS_WIFSTR,privkey,188);
bitcoin_wif2priv(coin->wiftaddr,&tmptype,&checkkey,USERPASS_WIFSTR);
bitcoin_priv2wif(coin->wiftaddr,G.USERPASS_WIFSTR,privkey,188);
bitcoin_wif2priv(coin->wiftaddr,&tmptype,&checkkey,G.USERPASS_WIFSTR);
if ( bits256_cmp(checkkey,privkey) != 0 )
{
char str[65],str2[65];
printf("FATAL ERROR converting USERPASS_WIFSTR %s -> %s != %s\n",USERPASS_WIFSTR,bits256_str(str,checkkey),bits256_str(str2,privkey));
printf("FATAL ERROR converting USERPASS_WIFSTR %s -> %s != %s\n",G.USERPASS_WIFSTR,bits256_str(str,checkkey),bits256_str(str2,privkey));
exit(-1);
}
conv_NXTpassword(userpass.bytes,pubkeyp->bytes,(uint8_t *)USERPASS_WIFSTR,(int32_t)strlen(USERPASS_WIFSTR));
conv_NXTpassword(userpass.bytes,pubkeyp->bytes,(uint8_t *)G.USERPASS_WIFSTR,(int32_t)strlen(G.USERPASS_WIFSTR));
userpub = curve25519(userpass,curve25519_basepoint9());
printf("userpass.(%s)\n",bits256_str(USERPASS,userpub));
printf("userpass.(%s)\n",bits256_str(G.USERPASS,userpub));
}
if ( coin->electrum == 0 && (retjson= LP_importprivkey(coin->symbol,tmpstr,coin->smartaddr,-1)) != 0 )
if ( coin->electrum == 0 )
{
if ( jobj(retjson,"error") != 0 )
LP_listunspent_issue(coin->symbol,coin->smartaddr);
if ( (retjson= LP_importprivkey(coin->symbol,tmpstr,coin->smartaddr,-1)) != 0 )
{
printf("cant importprivkey.%s -> (%s), abort session\n",coin->symbol,jprint(retjson,1));
exit(-1);
}
if ( jobj(retjson,"error") != 0 )
{
printf("cant importprivkey.%s -> (%s), abort session\n",coin->symbol,jprint(retjson,1));
exit(-1);
}
} else free_json(retjson);
}
}
LP_mypub25519 = *pubkeyp = curve25519(privkey,curve25519_basepoint9());
LP_mypriv25519 = privkey;
//printf("privkey.(%s) -> LP_mypub25519.(%s)\n",bits256_str(str,privkey),bits256_str(str2,LP_mypub25519));
vcalc_sha256(0,checkkey.bytes,privkey.bytes,sizeof(privkey));
checkkey.bytes[0] &= 248, checkkey.bytes[31] &= 127, checkkey.bytes[31] |= 64;
G.LP_mypub25519 = *pubkeyp = curve25519(checkkey,curve25519_basepoint9());
G.LP_mypriv25519 = checkkey;
return(privkey);
}
void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase,int32_t initonly)
void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase)
{
struct iguana_info *coin,*tmp; bits256 pubkey,privkey; uint8_t pubkey33[33];
struct iguana_info *coin,*tmp; bits256 pubkey,privkey; uint8_t pubkey33[33]; int32_t initonly;
initonly = (passphrase != 0);
memset(privkey.bytes,0,sizeof(privkey));
pubkey = privkey;
memset(pubkey.bytes,0,sizeof(pubkey));
HASH_ITER(hh,LP_coins,coin,tmp)
{
if ( initonly != 0 )
{
coin->counter = 0;
memset(coin->smartaddr,0,sizeof(coin->smartaddr));
if ( bits256_nonz(privkey) == 0 || coin->smartaddr[0] == 0 )
privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,coin,passphrase,"");
}
//printf("i.%d of %d\n",i,LP_numcoins);
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);
else if ( coin->inactive == 0 )
{
if ( LP_privkey_init(pubsock,coin,G.LP_mypriv25519,G.LP_mypub25519) == 0 && (rand() % 10) == 0 )
LP_postutxos(coin->symbol,coin->smartaddr);
}
}
}
int32_t LP_passphrase_init(char *passphrase,char *gui)
{
static void *ctx; int32_t iambob; struct LP_utxoinfo *utxo,*tmp;
if ( ctx == 0 )
ctx = bitcoin_ctx();
if ( G.LP_pendingswaps != 0 )
return(-1);
G.initializing = 1;
if ( gui == 0 )
gui = "cli";
while ( G.waiting == 0 )
{
printf("waiting for G.waiting\n");
sleep(5);
}
for (iambob=0; iambob<2; iambob++)
{
if ( G.LP_utxoinfos[iambob] != 0 )
{
HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,tmp)
{
HASH_DELETE(hh,G.LP_utxoinfos[iambob],utxo);
free(utxo);
}
}
if ( G.LP_utxoinfos2[iambob] != 0 )
{
HASH_ITER(hh,G.LP_utxoinfos2[iambob],utxo,tmp)
{
HASH_DELETE(hh,G.LP_utxoinfos2[iambob],utxo);
free(utxo);
}
}
}
memset(&G,0,sizeof(G));
LP_privkey_updates(ctx,LP_mypubsock,passphrase);
init_hexbytes_noT(G.LP_myrmd160str,G.LP_myrmd160,20);
G.LP_sessionid = (uint32_t)time(NULL);
safecopy(G.gui,gui,sizeof(G.gui));
return(0);
}

1
iguana/exchanges/autofill

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autofill\",\"base\":\"KMD\",\"rel\":\"BTC\",\"price\":0.0005,\"relvolume\":0.1}"

1
iguana/exchanges/autoprice

@ -1,3 +1,4 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"BTC\",\"margin\":0.0001}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"BTC\",\"rel\":\"KMD\",\"margin\":0.0001}"

1
iguana/exchanges/autotrade

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autotrade\",\"base\":\"REVS\",\"rel\":\"KMD\",\"relvolume\":1.01,\"price\":1.234}"

3
iguana/exchanges/balance

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"balance\",\"coin\":\"KMD\",\"address\":\"RHV2As4rox97BuE3LK96vMeNY8VsGRTmBj\"}"

1
iguana/exchanges/balance_loop

@ -1,3 +1,4 @@
#!/bin/bash
source userpass
ht=$1
while true

1
iguana/exchanges/bestfit

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"bestfit\",\"rel\":\"KMD\",\"relvolume\":1.01}"

3
iguana/exchanges/buy

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"buy\",\"base\":\"KMD\",\"rel\":\"BTC\",\"relvolume\":0.005,\"price\":0.0005}"

1
iguana/exchanges/cancelorder

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"setprice\",\"base\":\"REVS\",\"rel\":\"KMD\",\"price\":9999999.99}"

1
iguana/exchanges/client

@ -1,3 +1,4 @@
#!/bin/bash
source passphrase
source coins
pkill -15 marketmaker;

1
iguana/exchanges/client_osx

@ -1,3 +1,4 @@
#!/bin/bash
source passphrase
source coins
pkill -15 marketmaker;

2
iguana/exchanges/coins

File diff suppressed because one or more lines are too long

1
iguana/exchanges/debug

@ -1,3 +1,4 @@
#!/bin/bash
source passphrase
source coins
pkill -15 marketmaker;

1
iguana/exchanges/deletemessages

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"deletemessages\",\"firsti\":0,\"num\":10}"

1
iguana/exchanges/disable

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"disable\",\"coin\":\"REVS\"}"

1
iguana/exchanges/dividends

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"dividends\",\"coin\":\"KMD\",\"height\":$1,\"prefix\":\"fiat/jumblr sendtoaddress\",\"suffix\":\"\",\"dividend\":50000,\"dust\":1}"

3
iguana/exchanges/electrum

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"BTC\",\"ipaddr\":\"46.4.125.2\",\"port\":50001}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"BTC\",\"ipaddr\":\"173.212.225.176\",\"port\":50001}"

3
iguana/exchanges/electrum.chips

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"CHIPS\",\"ipaddr\":\"173.212.225.176\",\"port\":50076}"

3
iguana/exchanges/electrum.chips2

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"CHIPS\",\"ipaddr\":\"136.243.45.140\",\"port\":50076}"

3
iguana/exchanges/electrum.kmd

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"KMD\",\"ipaddr\":\"96.44.166.176\",\"port\":8777}"

3
iguana/exchanges/electrum.kmd2

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"KMD\",\"ipaddr\":\"173.212.225.176\",\"port\":50011}"

3
iguana/exchanges/electrum.kmd3

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"KMD\",\"ipaddr\":\"136.243.45.140\",\"port\":50011}"

39
iguana/exchanges/electrums

@ -0,0 +1,39 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"REVS\",\"ipaddr\":\"173.212.225.176\",\"port\":50050}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"CHIPS\",\"ipaddr\":\"173.212.225.176\",\"port\":50076}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"ARG\",\"ipaddr\":\"173.212.225.176\",\"port\":50081}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"BTC\",\"ipaddr\":\"136.243.45.140\",\"port\":50001}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"BTC\",\"ipaddr\":\"173.212.225.176\",\"port\":50001}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"CRW\",\"ipaddr\":\"173.212.225.176\",\"port\":50041}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"DASH\",\"ipaddr\":\"173.212.225.176\",\"port\":50098}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"DGB\",\"ipaddr\":\"136.243.45.140\",\"port\":50022}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"DGB\",\"ipaddr\":\"173.212.225.176\",\"port\":50022}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"DOGE\",\"ipaddr\":\"173.212.225.176\",\"port\":50015}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"FAIR\",\"ipaddr\":\"173.212.225.176\",\"port\":50005}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"HUSH\",\"ipaddr\":\"173.212.225.176\",\"port\":50013}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"KMD\",\"ipaddr\":\"136.243.45.140\",\"port\":50011}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"KMD\",\"ipaddr\":\"173.212.225.176\",\"port\":50011}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"LTC\",\"ipaddr\":\"173.212.225.176\",\"port\":50012}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"MONA\",\"ipaddr\":\"173.212.225.176\",\"port\":50002}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"NMC\",\"ipaddr\":\"173.212.225.176\",\"port\":50036}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"VTC\",\"ipaddr\":\"173.212.225.176\",\"port\":50088}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"ZEC\",\"ipaddr\":\"173.212.225.176\",\"port\":50032}"

3
iguana/exchanges/enable

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"BTC\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"REVS\"}"

1
iguana/exchanges/getcoin

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getcoin\",\"coin\":\"LTC\"}"

1
iguana/exchanges/getcoins

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getcoins\"}"

1
iguana/exchanges/getmessages

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getmessages\",\"firsti\":0,\"num\":10}"

1
iguana/exchanges/getpeers

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getpeers\"}"

1
iguana/exchanges/getpeersIP

@ -1,3 +1,4 @@
#!/bin/bash
curl --url "http://5.9.253.195:7783" --data "{\"method\":\"getpeers\"}"
curl --url "http://5.9.253.196:7783" --data "{\"method\":\"getpeers\"}"
curl --url "http://5.9.253.197:7783" --data "{\"method\":\"getpeers\"}"

1
iguana/exchanges/getprices

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprices\",\"coin\":\"REVS\"}"

1
iguana/exchanges/getutxos

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getutxos\",\"coin\":\"REVS\"}"

1
iguana/exchanges/goal

@ -1,3 +1,4 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"goal\",\"coin\":\"KMD\",\"val\":99}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"goal\",\"coin\":\"BTC\",\"val\":10}"

1
iguana/exchanges/goals

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"goal\"}"

1
iguana/exchanges/help

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"help\"}"

5
iguana/exchanges/install

@ -1,4 +1,5 @@
cp electrum snapshot_balance snapshot_loop secretaddresses dividends snapshot goals goal portfolio autoprice deletemessages getmessages debug register registerall trade ordermatch bestfit orderbook autotrade client run_osx client_osx run coins disable enable myprice myprices getcoins getpeers getpeersIP getprices getutxos help inv setprice status utxos ../dexscripts
#!/bin/bash
cp balance listunspent electrum snapshot_balance snapshot_loop secretaddresses dividends snapshot goals goal portfolio autoprice deletemessages getmessages debug register registerall buy sell bestfit orderbook client run_osx client_osx run coins disable enable myprice myprices getcoins getpeers getpeersIP getprices getutxos help inv setprice status utxos ../dexscripts
cd ../dexscripts
#cp ../exchanges/passphrase ../exchanges/userpass .
echo you will need to have a passphrase file with your passphrase and userpass file with userpass value in dexscripts dir
#echo you will need to have a passphrase file with your passphrase and userpass file with userpass value in dexscripts dir

3
iguana/exchanges/inv

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"inventory\",\"coin\":\"KMD\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"inventory\",\"coin\":\"REVS\"}"

3
iguana/exchanges/listunspent

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"listunspent\",\"coin\":\"BTC\",\"address\":\"1DPDsPCNNCF5SHhPPrddXcJe78rM6CBcH3\"}"

1
iguana/exchanges/loop

@ -1,3 +1,4 @@
#!/bin/bash
while true
do
source userpass

1
iguana/exchanges/message

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"$1\",\"method\":\"sendmessage\",\"message\":\"some sort of message\"}"

1
iguana/exchanges/myprice

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"myprice\",\"base\":\"REVS\",\"rel\":\"KMD\"}"

1
iguana/exchanges/myprices

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"myprices\"}"

1
iguana/exchanges/numutxos

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"numutxos\"}"

1
iguana/exchanges/orderbook

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"orderbook\",\"base\":\"JUMBLR\",\"rel\":\"KMD\"}"

1
iguana/exchanges/ordermatch

@ -1,3 +1,4 @@
#!/bin/bash
source userpass
#ordermatch(base, txfee=0, rel, desttxfee=0, price, txid, vout, feetxid, feevout, duration=3600)\n\
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"ordermatch\",\"base\":\"REVS\",\"rel\":\"KMD\",\"price\":1.234,\"duration\":600,\"txfee\":0,\"desttxfee\":0,\"txid\":\"$1\",\"vout\":$2,\"feetxid\":\"$3\",\"feevout\":$4}"

1
iguana/exchanges/portfolio

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"portfolio\"}"

1
iguana/exchanges/pricearray

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"pricearray\",\"base\":\"KMD\",\"rel\":\"BTC\",\"timescale\":60}"

1
iguana/exchanges/pub

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"6578099f6474d9b8bd66a7a136b922029a989818ec0309aee962dd6ac1862b74\",\"method\":\"forward\",\"method2\":\"publish\",\"data\":\"nonsense\"}"

1
iguana/exchanges/register

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://5.9.253.195:7783" --data "{\"userpass\":\"9bb4846d24136fc7c33515e45bccbab5c8fb7b57b411aa20057b371da9358255\",\"agent\":\"stats\",\"method\":\"register\",\"client\":\"6d3332be4904feafd326609bd76b66528dc7b2e2d75a7bd110c6bf8d19c4cf58\",\"pushaddr\":\"5.9.253.195\",\"pushport\":\"10000\"}"

1
iguana/exchanges/registerall

@ -1,3 +1,4 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"registerall\",\"numnodes\":10}"

1
iguana/exchanges/run

@ -1,3 +1,4 @@
#!/bin/bash
source passphrase
source coins
pkill -15 marketmaker;

1
iguana/exchanges/run_osx

@ -1,3 +1,4 @@
#!/bin/bash
source passphrase
source coins
pkill -15 marketmaker;

1
iguana/exchanges/secretaddresses

@ -1,3 +1,4 @@
#!/bin/bash
source userpass
echo "usage: ./secretaddresses 'passphrase'"

3
iguana/exchanges/sell

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"sell\",\"base\":\"KMD\",\"rel\":\"BTC\",\"basevolume\":10.0\"price\":0.0005}"

1
iguana/exchanges/setprice

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"setprice\",\"base\":\"REVS\",\"rel\":\"KMD\",\"price\":1.234}"

1
iguana/exchanges/snapshot

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"snapshot\",\"coin\":\"KMD\",\"height\":$1}"

1
iguana/exchanges/snapshot_balance

@ -1,3 +1,4 @@
#!/bin/bash
source userpass
ht=$1
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"snapshot_balance\",\"coin\":\"KMD\",\"height\":$ht,\"addresses\":[\"RSAzPFzgTZHNcxLNLdGyVPbjbMA8PRY7Ss\", \"RBgD5eMGwZppid4x7PTEC2Wg1AzvxbsQqB\"]}"

1
iguana/exchanges/snapshot_loop

@ -1,3 +1,4 @@
#!/bin/bash
source userpass
ht=$1
while true

1
iguana/exchanges/status

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"swapstatus\"}"

1
iguana/exchanges/swapstatus

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"swapstatus\",\"requestid\":2291973695,\"quoteid\":3387529385}"

1
iguana/exchanges/trade

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"trade\",\"price\":1.234,\"base\":\"REVS\",\"rel\":\"KMD\",\"quote\":{}}"

1
iguana/exchanges/utxos

@ -1,2 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getutxos\",\"coin\":\"REVS\"}"

2
iguana/iguana_notary.c

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

1
iguana/m_notary

@ -41,6 +41,7 @@ coins/wlc_7776
coins/kv_7776
coins/ceal_7776
coins/mesh_7776
coins/mnz_7776
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"passthru\",\"method\":\"paxfiats\",\"timeout\":900000}"
#curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"$myip\"}"

Loading…
Cancel
Save