Browse Source

Merge pull request #14 from ca333/dev

dev update
win-cross^2
ca333 8 years ago
committed by GitHub
parent
commit
8cc806b96e
  1. 13
      .gitignore
  2. 22
      .vscode/launch.json
  3. 32
      README.md
  4. 2
      basilisk/basilisk_bitcoin.c
  5. 2
      crypto777/OS_portable.h
  6. 4
      crypto777/hmac/sha224.c
  7. 86
      crypto777/hmac/sha256.c
  8. 8
      crypto777/hmac/tomcrypt_hash.h
  9. 24
      crypto777/hmac_sha512.c
  10. 57
      crypto777/iguana_utils.c
  11. 34
      crypto777/scrypt.c
  12. 2
      iguana/dPoW.h
  13. 17
      iguana/dpow/dpow_network.c
  14. 34
      iguana/dpow/dpow_prices.c
  15. 0
      iguana/exchanges/DB/.tmpmarker
  16. 0
      iguana/exchanges/DB/ECB/.tmpmarker
  17. 0
      iguana/exchanges/DB/SWAPS/.tmpmarker
  18. 0
      iguana/exchanges/DB/TRANSACTIONS/.tmpmarker
  19. 0
      iguana/exchanges/DB/purgeable/.tmpmarker
  20. 0
      iguana/exchanges/DB/purgeable/BTC/.tmpmarker
  21. 0
      iguana/exchanges/DB/purgeable/BTCD/.tmpmarker
  22. 2
      iguana/exchanges/DEXstats.h
  23. 55
      iguana/exchanges/LP_bitcoin.c
  24. 120
      iguana/exchanges/LP_coins.c
  25. 262
      iguana/exchanges/LP_commands.c
  26. 124
      iguana/exchanges/LP_forwarding.c
  27. 59
      iguana/exchanges/LP_include.h
  28. 97
      iguana/exchanges/LP_messages.c
  29. 471
      iguana/exchanges/LP_nativeDEX.c
  30. 410
      iguana/exchanges/LP_network.c
  31. 357
      iguana/exchanges/LP_ordermatch.c
  32. 94
      iguana/exchanges/LP_peers.c
  33. 577
      iguana/exchanges/LP_portfolio.c
  34. 328
      iguana/exchanges/LP_prices.c
  35. 98
      iguana/exchanges/LP_remember.c
  36. 209
      iguana/exchanges/LP_rpc.c
  37. 443
      iguana/exchanges/LP_scan.c
  38. 115
      iguana/exchanges/LP_statemachine.c
  39. 130
      iguana/exchanges/LP_swap.c
  40. 120
      iguana/exchanges/LP_transaction.c
  41. 420
      iguana/exchanges/LP_utxos.c
  42. 0
      iguana/exchanges/SVM/.tmpmarker
  43. 0
      iguana/exchanges/SVM/models/.tmpmarker
  44. 0
      iguana/exchanges/SVM/rawfeatures/.tmpmarker
  45. 2
      iguana/exchanges/autofill
  46. 9
      iguana/exchanges/autoprice
  47. 11
      iguana/exchanges/balance_loop
  48. 2
      iguana/exchanges/cancelorder
  49. 4
      iguana/exchanges/coins
  50. 0
      iguana/exchanges/confs/.tmpmarker
  51. 8
      iguana/exchanges/debug
  52. 2
      iguana/exchanges/deletemessages
  53. 2
      iguana/exchanges/dividends
  54. 2
      iguana/exchanges/forward
  55. 0
      iguana/exchanges/genesis/.tmpmarker
  56. 2
      iguana/exchanges/getcoin
  57. 2
      iguana/exchanges/getmessages
  58. 4
      iguana/exchanges/goal
  59. 2
      iguana/exchanges/goals
  60. 3
      iguana/exchanges/install
  61. 2
      iguana/exchanges/lookup
  62. 2
      iguana/exchanges/message
  63. 19
      iguana/exchanges/mm.c
  64. 2
      iguana/exchanges/numutxos
  65. 2
      iguana/exchanges/portfolio
  66. 2
      iguana/exchanges/pricearray
  67. 5
      iguana/exchanges/secretaddresses
  68. 2
      iguana/exchanges/snapshot
  69. 4
      iguana/exchanges/snapshot_balance
  70. 11
      iguana/exchanges/snapshot_loop
  71. 25
      iguana/exchanges/stats.c
  72. 0
      iguana/exchanges/tmp/.tmpmarker
  73. 3
      iguana/exchanges/userpass
  74. 19
      iguana/iguana777.c
  75. 3
      iguana/iguana_exchanges.c
  76. 4
      iguana/iguana_msg.c
  77. 4
      iguana/iguana_notary.c
  78. 1
      iguana/iguana_peers.c
  79. 32
      iguana/iguana_ramchain.c
  80. 1
      iguana/iguana_rpc.c
  81. 2
      iguana/iguana_sign.c
  82. 2
      iguana/m_LP_StaticNanoMsg
  83. 28
      iguana/m_mm_StaticNanoMsg
  84. 7
      iguana/secp256k1/m_unix_Makefile
  85. 2
      iguana/tests/rawtx2
  86. 12
      osx_deploy.sh

13
.gitignore

@ -38,6 +38,17 @@ deprecated/.DS_Store
.DS_Store .DS_Store
iguana/help/.tmpmarker
iguana/genesis/.tmpmarker
iguana/help.json
iguana/autoAPI.md
iguana/basilisk.o-2ad8cb38
=======
*.pbxproj *.pbxproj
iguana/tmp/.tmpmarker iguana/tmp/.tmpmarker
@ -473,3 +484,5 @@ iguana/client
iguana/marketmaker.dSYM/Contents/Resources/DWARF/marketmaker iguana/marketmaker.dSYM/Contents/Resources/DWARF/marketmaker
iguana/confs/97f18454bb61e9eb7a827cfbefe42fbf7ae2832dc74c4812bdaef8bcf5c10474 iguana/confs/97f18454bb61e9eb7a827cfbefe42fbf7ae2832dc74c4812bdaef8bcf5c10474
iguana/DB/PRICES/.tmpmarker

22
.vscode/launch.json

@ -0,0 +1,22 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "C++ Launch (Windows)",
"type": "cppvsdbg",
"request": "launch",
"program": "enter program name, for example ${workspaceRoot}/a.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceRoot}",
"environment": [],
"externalConsole": false
},
{
"name": "C++ Attach (Windows)",
"type": "cppvsdbg",
"request": "attach",
"processId": "${command:pickProcess}"
}
]
}

32
README.md

@ -245,3 +245,35 @@ sudo service ntp start
Now things should be ready. To update and run notary node: Now things should be ready. To update and run notary node:
pkill iguana; ./m_LP; tests/notaryinit pkill iguana; ./m_LP; tests/notaryinit
##Build for OSX distribution##
Get OSX SDK 10.6 from https://github.com/ca333/MacOSX-SDKs/releases/tag/10.6
Unpack & move the .sdk folder to Xcodes SDK folder:
```cd DownloadDirectory```
```mv MacOSX10.6.sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/.```
If you are using Xcode > 7.3 add the new SDK to XCode by changing MinimumSDKVersion in your Info.plist:
```vi /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Info.plist```
Change the value to:
```
<key>MinimumSDKVersion</key>
<string>10.6</string>
```
Build crypto777 library and agents with OSX release makefile:
```./m_onetime m_osx_release```
Execute the OSX deploy script:
```
./osx_deploy.sh
```
The iguana binary and its linked libraries are in ```$HOME/tmp/iguana```.

2
basilisk/basilisk_bitcoin.c

@ -602,7 +602,7 @@ char *iguana_utxoduplicates(struct supernet_info *myinfo,struct iguana_info *coi
free_json(vins); free_json(vins);
return(rawtx); return(rawtx);
} }
//printf("duplicatesTX.(%s)\n",rawtx); printf("splitfunds tx.(%s) vins.(%s)\n",rawtx,jprint(vins,0));
if ( signedtxidp != 0 ) if ( signedtxidp != 0 )
{ {
if ( (signedtx= iguana_signrawtx(myinfo,coin,0,signedtxidp,completedp,vins,rawtx,0,0)) != 0 ) if ( (signedtx= iguana_signrawtx(myinfo,coin,0,signedtxidp,completedp,vins,rawtx,0,0)) != 0 )

2
crypto777/OS_portable.h

@ -198,6 +198,8 @@ int32_t OS_nonportable_init();
void OS_portable_init(); void OS_portable_init();
void OS_init(); void OS_init();
int32_t sortds(double *buf,uint32_t num,int32_t size);
int32_t revsortds(double *buf,uint32_t num,int32_t size);
double OS_portable_milliseconds(); double OS_portable_milliseconds();
void OS_portable_randombytes(uint8_t *x,long xlen); void OS_portable_randombytes(uint8_t *x,long xlen);

4
crypto777/hmac/sha224.c

@ -26,7 +26,7 @@ const struct ltc_hash_descriptor sha224_desc =
9, 9,
&sha224_init, &sha224_init,
&sha256_process, &sha256i_process,
&sha224_done, &sha224_done,
&sha224_test, &sha224_test,
NULL NULL
@ -69,7 +69,7 @@ int sha224_done(hash_state * md, unsigned char *out)
LTC_ARGCHK(md != NULL); LTC_ARGCHK(md != NULL);
LTC_ARGCHK(out != NULL); LTC_ARGCHK(out != NULL);
err = sha256_done(md, buf); err = sha256i_done(md, buf);
XMEMCPY(out, buf, 28); XMEMCPY(out, buf, 28);
#ifdef LTC_CLEAN_STACK #ifdef LTC_CLEAN_STACK
zeromem(buf, sizeof(buf)); zeromem(buf, sizeof(buf));

86
crypto777/hmac/sha256.c

@ -17,24 +17,6 @@
//#ifdef LTC_SHA256 //#ifdef LTC_SHA256
const struct ltc_hash_descriptor sha256_desc =
{
"sha256",
0,
32,
64,
/* OID */
{ 2, 16, 840, 1, 101, 3, 4, 2, 1, },
9,
&sha256_init,
&sha256_process,
&sha256_done,
&sha256_test,
NULL
};
#ifdef LTC_SMALL_CODE #ifdef LTC_SMALL_CODE
/* the K array */ /* the K array */
static const ulong32 K[64] = { static const ulong32 K[64] = {
@ -203,7 +185,7 @@ static int sha256_compress(hash_state * md, unsigned char *buf)
@param md The hash state you wish to initialize @param md The hash state you wish to initialize
@return CRYPT_OK if successful @return CRYPT_OK if successful
*/ */
int sha256_init(hash_state * md) int sha256i_init(hash_state * md)
{ {
LTC_ARGCHK(md != NULL); LTC_ARGCHK(md != NULL);
@ -227,7 +209,7 @@ int sha256_init(hash_state * md)
@param inlen The length of the data (octets) @param inlen The length of the data (octets)
@return CRYPT_OK if successful @return CRYPT_OK if successful
*/ */
HASH_PROCESS(sha256_process, sha256_compress, sha256, 64) HASH_PROCESS(sha256i_process, sha256_compress, sha256, 64)
/** /**
Terminate the hash to get the digest Terminate the hash to get the digest
@ -235,7 +217,7 @@ HASH_PROCESS(sha256_process, sha256_compress, sha256, 64)
@param out [out] The destination of the hash (32 bytes) @param out [out] The destination of the hash (32 bytes)
@return CRYPT_OK if successful @return CRYPT_OK if successful
*/ */
int sha256_done(hash_state * md, unsigned char *out) int sha256i_done(hash_state * md, unsigned char *out)
{ {
int i; int i;
@ -287,9 +269,9 @@ int sha256_done(hash_state * md, unsigned char *out)
void calc_sha256(char hashstr[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len) void calc_sha256(char hashstr[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len)
{ {
hash_state md; hash_state md;
sha256_init(&md); sha256i_init(&md);
sha256_process(&md,src,len); sha256i_process(&md,src,len);
sha256_done(&md,hash); sha256i_done(&md,hash);
if ( hashstr != 0 ) if ( hashstr != 0 )
{ {
int32_t init_hexbytes_noT(char *hexbytes,uint8_t *message,long len); int32_t init_hexbytes_noT(char *hexbytes,uint8_t *message,long len);
@ -300,11 +282,11 @@ void calc_sha256(char hashstr[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t
void calc_sha256cat(uint8_t hash[256 >> 3],uint8_t *src,int32_t len,uint8_t *src2,int32_t len2) void calc_sha256cat(uint8_t hash[256 >> 3],uint8_t *src,int32_t len,uint8_t *src2,int32_t len2)
{ {
hash_state md; hash_state md;
sha256_init(&md); sha256i_init(&md);
sha256_process(&md,src,len); sha256i_process(&md,src,len);
if ( src2 != 0 ) if ( src2 != 0 )
sha256_process(&md,src2,len2); sha256i_process(&md,src2,len2);
sha256_done(&md,hash); sha256i_done(&md,hash);
} }
void update_sha256(uint8_t hash[256 >> 3],struct sha256_state *state,uint8_t *src,int32_t len) void update_sha256(uint8_t hash[256 >> 3],struct sha256_state *state,uint8_t *src,int32_t len)
@ -312,14 +294,14 @@ void update_sha256(uint8_t hash[256 >> 3],struct sha256_state *state,uint8_t *sr
hash_state md; hash_state md;
memset(&md,0,sizeof(md)); memset(&md,0,sizeof(md));
if ( src == 0 ) if ( src == 0 )
sha256_init(&md); sha256i_init(&md);
else else
{ {
md.sha256 = *state; md.sha256 = *state;
sha256_process(&md,src,len); sha256i_process(&md,src,len);
} }
*state = md.sha256; *state = md.sha256;
sha256_done(&md,hash); sha256i_done(&md,hash);
} }
/*void calc_OP_HASH160(char hexstr[41],uint8_t hash160[20],char *pubkey) /*void calc_OP_HASH160(char hexstr[41],uint8_t hash160[20],char *pubkey)
@ -334,9 +316,9 @@ void update_sha256(uint8_t hash[256 >> 3],struct sha256_state *state,uint8_t *sr
return; return;
} }
decode_hex(buf,len,pubkey); decode_hex(buf,len,pubkey);
sha256_init(&md); sha256i_init(&md);
sha256_process(&md,buf,len); sha256i_process(&md,buf,len);
sha256_done(&md,sha256); sha256i_done(&md,sha256);
rmd160_init(&md); rmd160_init(&md);
rmd160_process(&md,sha256,256 >> 3); rmd160_process(&md,sha256,256 >> 3);
@ -389,9 +371,9 @@ int sha256_test(void)
char *str; char *str;
for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
sha256_init(&md); sha256i_init(&md);
sha256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg)); sha256i_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
sha256_done(&md, tmp); sha256i_done(&md, tmp);
if (XMEMCMP(tmp, tests[i].hash, 32) != 0) { if (XMEMCMP(tmp, tests[i].hash, 32) != 0) {
for (j=0; j<32; j++) for (j=0; j<32; j++)
printf("%02x",tmp[j]); printf("%02x",tmp[j]);
@ -400,16 +382,16 @@ int sha256_test(void)
strcpy(str,(char*)tests[i].msg); strcpy(str,(char*)tests[i].msg);
reverse_hexstr(str); reverse_hexstr(str);
printf("reversed.(%s)\n",str); printf("reversed.(%s)\n",str);
sha256_init(&md); sha256i_init(&md);
sha256_process(&md, (unsigned char*)str, (unsigned long)strlen(str)); sha256i_process(&md, (unsigned char*)str, (unsigned long)strlen(str));
sha256_done(&md, tmp); sha256i_done(&md, tmp);
for (j=0; j<32; j++) for (j=0; j<32; j++)
printf("%02x",tmp[j]); printf("%02x",tmp[j]);
printf(" <- sha256(%s)\n",str); printf(" <- sha256(%s)\n",str);
decode_hex(buf,(int)strlen(tests[i].msg),tests[i].msg); decode_hex(buf,(int)strlen(tests[i].msg),tests[i].msg);
sha256_init(&md); sha256i_init(&md);
sha256_process(&md, (unsigned char*)buf, (unsigned long)strlen(tests[i].msg)/2); sha256i_process(&md, (unsigned char*)buf, (unsigned long)strlen(tests[i].msg)/2);
sha256_done(&md, tmp); sha256i_done(&md, tmp);
for (j=0; j<32; j++) for (j=0; j<32; j++)
printf("%02x",tmp[j]); printf("%02x",tmp[j]);
printf(" <- sha256(binary %s)\n",tests[i].msg); printf(" <- sha256(binary %s)\n",tests[i].msg);
@ -436,6 +418,24 @@ int sha256_test(void)
#undef Maj #undef Maj
const struct ltc_hash_descriptor sha256_desc =
{
"sha256",
0,
32,
64,
/* OID */
{ 2, 16, 840, 1, 101, 3, 4, 2, 1, },
9,
&sha256i_init,
&sha256i_process,
&sha256i_done,
&sha256_test,
NULL
};
/* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha2/sha256.c,v $ */ /* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha2/sha256.c,v $ */
/* $Revision: 1.11 $ */ /* $Revision: 1.11 $ */

8
crypto777/hmac/tomcrypt_hash.h

@ -228,9 +228,9 @@ extern const struct ltc_hash_descriptor sha384_desc;
#endif #endif
#ifdef LTC_SHA256 #ifdef LTC_SHA256
int sha256_init(hash_state * md); int sha256i_init(hash_state * md);
int sha256_process(hash_state * md, const unsigned char *in, unsigned long inlen); int sha256i_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int sha256_done(hash_state * md, unsigned char *hash); int sha256i_done(hash_state * md, unsigned char *hash);
int sha256_test(void); int sha256_test(void);
extern const struct ltc_hash_descriptor sha256_desc; extern const struct ltc_hash_descriptor sha256_desc;
@ -239,7 +239,7 @@ extern const struct ltc_hash_descriptor sha256_desc;
#error LTC_SHA256 is required for LTC_SHA224 #error LTC_SHA256 is required for LTC_SHA224
#endif #endif
int sha224_init(hash_state * md); int sha224_init(hash_state * md);
#define sha224_process sha256_process #define sha224_process sha256i_process
int sha224_done(hash_state * md, unsigned char *hash); int sha224_done(hash_state * md, unsigned char *hash);
int sha224_test(void); int sha224_test(void);
extern const struct ltc_hash_descriptor sha224_desc; extern const struct ltc_hash_descriptor sha224_desc;

24
crypto777/hmac_sha512.c

@ -621,4 +621,28 @@ char *hmac_whirlpool_str(char *dest,char *key,int32_t key_size,char *message)
return(dest); return(dest);
} }
void calc_md2str(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len)
{
bits128 x;
calc_md2(hexstr,buf,msg,len);
decode_hex(buf,sizeof(x),hexstr);
//memcpy(buf,x.bytes,sizeof(x));
}
void calc_md4str(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len)
{
bits128 x;
calc_md4(hexstr,buf,msg,len);
decode_hex(buf,sizeof(x),hexstr);
//memcpy(buf,x.bytes,sizeof(x));
}
void calc_md5str(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len)
{
bits128 x;
calc_md5(hexstr,msg,len);
decode_hex(buf,sizeof(x),hexstr);
//memcpy(buf,x.bytes,sizeof(x));
}

57
crypto777/iguana_utils.c

@ -522,11 +522,24 @@ static int _increasing_double(const void *a,const void *b)
{ {
#define double_a (*(double *)a) #define double_a (*(double *)a)
#define double_b (*(double *)b) #define double_b (*(double *)b)
if ( double_b > double_a ) if ( double_b > double_a )
return(-1); return(-1);
else if ( double_b < double_a ) else if ( double_b < double_a )
return(1); return(1);
return(0); return(0);
#undef double_a
#undef double_b
}
static int _decreasing_double(const void *a,const void *b)
{
#define double_a (*(double *)a)
#define double_b (*(double *)b)
if ( double_b > double_a )
return(1);
else if ( double_b < double_a )
return(-1);
return(0);
#undef double_a #undef double_a
#undef double_b #undef double_b
} }
@ -572,8 +585,14 @@ static int _decreasing_uint32(const void *a,const void *b)
int32_t sortds(double *buf,uint32_t num,int32_t size) int32_t sortds(double *buf,uint32_t num,int32_t size)
{ {
qsort(buf,num,size,_increasing_double); qsort(buf,num,size,_increasing_double);
return(0); return(0);
}
int32_t revsortds(double *buf,uint32_t num,int32_t size)
{
qsort(buf,num,size,_decreasing_double);
return(0);
} }
int32_t sort64s(uint64_t *buf,uint32_t num,int32_t size) int32_t sort64s(uint64_t *buf,uint32_t num,int32_t size)
@ -1086,30 +1105,6 @@ void rmd160ofsha256(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len)
calc_rmd160(hexstr,buf,sha256,sizeof(sha256)); calc_rmd160(hexstr,buf,sha256,sizeof(sha256));
} }
void calc_md2str(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len)
{
bits128 x;
calc_md2(hexstr,buf,msg,len);
decode_hex(buf,sizeof(x),hexstr);
//memcpy(buf,x.bytes,sizeof(x));
}
void calc_md4str(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len)
{
bits128 x;
calc_md4(hexstr,buf,msg,len);
decode_hex(buf,sizeof(x),hexstr);
//memcpy(buf,x.bytes,sizeof(x));
}
void calc_md5str(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len)
{
bits128 x;
calc_md5(hexstr,msg,len);
decode_hex(buf,sizeof(x),hexstr);
//memcpy(buf,x.bytes,sizeof(x));
}
void calc_crc32str(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len) void calc_crc32str(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len)
{ {
uint32_t crc; uint8_t serialized[sizeof(crc)]; uint32_t crc; uint8_t serialized[sizeof(crc)];

34
crypto777/scrypt.c

@ -69,7 +69,7 @@ static const uint32_t sha256_k[64] = {
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
}; };
static inline void sha256_init(uint32_t *state) static inline void scrypt_sha256_init(uint32_t *state)
{ {
memcpy(state, sha256_h, 32); memcpy(state, sha256_h, 32);
} }
@ -102,7 +102,7 @@ W[i] + sha256_k[i])
#define swab32(x) ((((x) << 24) & 0xff000000u) | (((x) << 8) & 0x00ff0000u) | (((x) >> 8) & 0x0000ff00u) | (((x) >> 24) & 0x000000ffu)) #define swab32(x) ((((x) << 24) & 0xff000000u) | (((x) << 8) & 0x00ff0000u) | (((x) >> 8) & 0x0000ff00u) | (((x) >> 24) & 0x000000ffu))
static inline void sha256_transform(uint32_t *state, const uint32_t *block, int swap) static inline void scrypt_sha256_transform(uint32_t *state, const uint32_t *block, int swap)
{ {
uint32_t W[64]; uint32_t W[64];
uint32_t S[8]; uint32_t S[8];
@ -203,29 +203,29 @@ static inline void HMAC_SHA256_80_init(const uint32_t *key,uint32_t *tstate, uin
/* tstate is assumed to contain the midstate of key */ /* tstate is assumed to contain the midstate of key */
memcpy(pad, key + 16, 16); memcpy(pad, key + 16, 16);
memcpy(pad + 4, keypad, 48); memcpy(pad + 4, keypad, 48);
sha256_transform(tstate, pad, 0); scrypt_sha256_transform(tstate, pad, 0);
memcpy(ihash, tstate, 32); memcpy(ihash, tstate, 32);
sha256_init(ostate); scrypt_sha256_init(ostate);
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
pad[i] = ihash[i] ^ 0x5c5c5c5c; pad[i] = ihash[i] ^ 0x5c5c5c5c;
for (; i < 16; i++) for (; i < 16; i++)
pad[i] = 0x5c5c5c5c; pad[i] = 0x5c5c5c5c;
sha256_transform(ostate, pad, 0); scrypt_sha256_transform(ostate, pad, 0);
sha256_init(tstate); scrypt_sha256_init(tstate);
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
pad[i] = ihash[i] ^ 0x36363636; pad[i] = ihash[i] ^ 0x36363636;
for (; i < 16; i++) for (; i < 16; i++)
pad[i] = 0x36363636; pad[i] = 0x36363636;
sha256_transform(tstate, pad, 0); scrypt_sha256_transform(tstate, pad, 0);
} }
static inline void PBKDF2_SHA256_80_128(const uint32_t *tstate,const uint32_t *ostate, const uint32_t *salt, uint32_t *output) static inline void PBKDF2_SHA256_80_128(const uint32_t *tstate,const uint32_t *ostate, const uint32_t *salt, uint32_t *output)
{ {
uint32_t istate[8], ostate2[8],ibuf[16], obuf[16]; int i, j; uint32_t istate[8], ostate2[8],ibuf[16], obuf[16]; int i, j;
memcpy(istate, tstate, 32); memcpy(istate, tstate, 32);
sha256_transform(istate, salt, 0); scrypt_sha256_transform(istate, salt, 0);
memcpy(ibuf, salt + 16, 16); memcpy(ibuf, salt + 16, 16);
memcpy(ibuf + 5, innerpad, 44); memcpy(ibuf + 5, innerpad, 44);
memcpy(obuf + 8, outerpad, 32); memcpy(obuf + 8, outerpad, 32);
@ -233,9 +233,9 @@ static inline void PBKDF2_SHA256_80_128(const uint32_t *tstate,const uint32_t *o
{ {
memcpy(obuf, istate, 32); memcpy(obuf, istate, 32);
ibuf[4] = i + 1; ibuf[4] = i + 1;
sha256_transform(obuf, ibuf, 0); scrypt_sha256_transform(obuf, ibuf, 0);
memcpy(ostate2, ostate, 32); memcpy(ostate2, ostate, 32);
sha256_transform(ostate2, obuf, 0); scrypt_sha256_transform(ostate2, obuf, 0);
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
output[8 * i + j] = swab32(ostate2[j]); output[8 * i + j] = swab32(ostate2[j]);
} }
@ -244,12 +244,12 @@ static inline void PBKDF2_SHA256_80_128(const uint32_t *tstate,const uint32_t *o
static inline void PBKDF2_SHA256_128_32(uint32_t *tstate, uint32_t *ostate,const uint32_t *salt, uint32_t *output) static inline void PBKDF2_SHA256_128_32(uint32_t *tstate, uint32_t *ostate,const uint32_t *salt, uint32_t *output)
{ {
uint32_t buf[16]; int i; uint32_t buf[16]; int i;
sha256_transform(tstate, salt, 1); scrypt_sha256_transform(tstate, salt, 1);
sha256_transform(tstate, salt + 16, 1); scrypt_sha256_transform(tstate, salt + 16, 1);
sha256_transform(tstate, finalblk, 0); scrypt_sha256_transform(tstate, finalblk, 0);
memcpy(buf, tstate, 32); memcpy(buf, tstate, 32);
memcpy(buf + 8, outerpad, 32); memcpy(buf + 8, outerpad, 32);
sha256_transform(ostate, buf, 0); scrypt_sha256_transform(ostate, buf, 0);
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
output[i] = swab32(ostate[i]); output[i] = swab32(ostate[i]);
} }
@ -363,11 +363,11 @@ void calc_scrypthash(uint32_t *hash,void *data)
uint8_t *scratchbuf; uint32_t midstate[8]; uint8_t *scratchbuf; uint32_t midstate[8];
memset(midstate,0,sizeof(midstate)); memset(midstate,0,sizeof(midstate));
memset(hash,0,32); memset(hash,0,32);
sha256_init(midstate); scrypt_sha256_init(midstate);
sha256_transform(midstate,(void *)data,0); scrypt_sha256_transform(midstate,(void *)data,0);
scratchbuf = malloc(1024 * 128 + 64); scratchbuf = malloc(1024 * 128 + 64);
scrypt_1024_1_1_256((void *)data,hash,midstate,scratchbuf,1024); scrypt_1024_1_1_256((void *)data,hash,midstate,scratchbuf,1024);
free(scratchbuf); free(scratchbuf);
} }
//010000000000000000000000000000000000000000000000000000000000000000000000d9ced4ed1130f7b7faad9be25323ffafa33232a17c3edf6cfd97bee6bafbdd97b9aa8e4ef0ff0f1ecd513f7c //010000000000000000000000000000000000000000000000000000000000000000000000d9ced4ed1130f7b7faad9be25323ffafa33232a17c3edf6cfd97bee6bafbdd97b9aa8e4ef0ff0f1ecd513f7c
//010000000000000000000000000000000000000000000000000000000000000000000000d9ced4ed1130f7b7faad9be25323ffafa33232a17c3edf6cfd97bee6bafbdd97b9aa8e4ef0ff0f1ecd513f7c00 //010000000000000000000000000000000000000000000000000000000000000000000000d9ced4ed1130f7b7faad9be25323ffafa33232a17c3edf6cfd97bee6bafbdd97b9aa8e4ef0ff0f1ecd513f7c00

2
iguana/dPoW.h

@ -137,7 +137,7 @@ struct dpow_info
int32_t lastheight,maxblocks,SRCHEIGHT,SHORTFLAG,ratifying; int32_t lastheight,maxblocks,SRCHEIGHT,SHORTFLAG,ratifying;
struct pax_transaction *PAX; struct pax_transaction *PAX;
portable_mutex_t paxmutex,dexmutex; portable_mutex_t paxmutex,dexmutex;
uint32_t ipbits[64],numipbits; uint32_t ipbits[128],numipbits;
struct dpow_block **blocks; struct dpow_block **blocks;
}; };
uint64_t dpow_notarybestk(uint64_t refmask,struct dpow_block *bp,int8_t *lastkp); uint64_t dpow_notarybestk(uint64_t refmask,struct dpow_block *bp,int8_t *lastkp);

17
iguana/dpow/dpow_network.c

@ -561,7 +561,7 @@ void dex_channelsend(struct supernet_info *myinfo,bits256 srchash,bits256 destha
void dpow_randipbits(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *retjson) void dpow_randipbits(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *retjson)
{ {
int32_t m; uint32_t ipbits; char *coinstr; int32_t m; uint32_t ipbits; char *coinstr; cJSON *infojson;
if ( is_cJSON_Array(retjson) == 0 ) if ( is_cJSON_Array(retjson) == 0 )
{ {
if ( (m= myinfo->numdpowipbits) > 0 ) if ( (m= myinfo->numdpowipbits) > 0 )
@ -572,6 +572,11 @@ void dpow_randipbits(struct supernet_info *myinfo,struct iguana_info *coin,cJSON
} }
if ( (coinstr= jstr(retjson,"coin")) == 0 ) if ( (coinstr= jstr(retjson,"coin")) == 0 )
jaddstr(retjson,"coin",coin->symbol); jaddstr(retjson,"coin",coin->symbol);
if ( (infojson= dpow_getinfo(myinfo,coin)) != 0 )
{
jaddnum(retjson,"notaryheight",juint(infojson,"blocks"));
free_json(infojson);
}
} }
} }
@ -1318,7 +1323,7 @@ struct dpow_nanomsghdr
{ {
bits256 srchash,desthash; bits256 srchash,desthash;
struct dpow_nanoutxo ratify,notarize; struct dpow_nanoutxo ratify,notarize;
uint32_t channel,height,size,datalen,crc32,myipbits,numipbits,ipbits[64]; uint32_t channel,height,size,datalen,crc32,myipbits,numipbits,ipbits[128];
char symbol[16]; char symbol[16];
uint8_t senderind,version0,version1,packet[]; uint8_t senderind,version0,version1,packet[];
} PACKED; } PACKED;
@ -2026,10 +2031,10 @@ void dpow_send(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_blo
printf("%d NANOSEND.%d ht.%d channel.%08x (%d) pax.%08x datalen.%d (%d %llx) (%d %llx) recv.%llx\n",i,sentbytes,np->height,np->channel,size,np->notarize.paxwdcrc,datalen,(int8_t)np->notarize.bestk,(long long)np->notarize.bestmask,bp->notaries[bp->myind].bestk,(long long)bp->notaries[bp->myind].bestmask,(long long)bp->recvmask); printf("%d NANOSEND.%d ht.%d channel.%08x (%d) pax.%08x datalen.%d (%d %llx) (%d %llx) recv.%llx\n",i,sentbytes,np->height,np->channel,size,np->notarize.paxwdcrc,datalen,(int8_t)np->notarize.bestk,(long long)np->notarize.bestmask,bp->notaries[bp->myind].bestk,(long long)bp->notaries[bp->myind].bestmask,(long long)bp->recvmask);
} }
void dpow_ipbitsadd(struct supernet_info *myinfo,struct dpow_info *dp,uint32_t *ipbits,int32_t numipbits,int32_t fromid,uint32_t senderipbits) void dpow_ipbitsadd(struct supernet_info *myinfo,struct dpow_info *dp,uint32_t *ipbits,int32_t numipbits,int32_t maxipbits,int32_t fromid,uint32_t senderipbits)
{ {
int32_t i,j,matched,missing,n; char ipaddr[64]; int32_t i,j,matched,missing,n; char ipaddr[64];
if ( numipbits >= 64 ) if ( numipbits >= maxipbits )
{ {
static int32_t counter; static int32_t counter;
if ( counter++ < 100 ) if ( counter++ < 100 )
@ -2088,7 +2093,7 @@ int32_t dpow_nanomsg_update(struct supernet_info *myinfo)
if ( (flags & 1) == 0 && (size= signed_nn_recv(&freeptr,myinfo,myinfo->notaries,myinfo->numnotaries,myinfo->dpowsock,&np)) > 0 ) if ( (flags & 1) == 0 && (size= signed_nn_recv(&freeptr,myinfo,myinfo->notaries,myinfo->numnotaries,myinfo->dpowsock,&np)) > 0 )
{ {
num++; num++;
if ( size > 0 ) if ( size >= sizeof(*np) )
{ {
//fprintf(stderr,"%d ",size); //fprintf(stderr,"%d ",size);
if ( np->version0 == (DPOW_VERSION & 0xff) && np->version1 == ((DPOW_VERSION >> 8) & 0xff) ) if ( np->version0 == (DPOW_VERSION & 0xff) && np->version1 == ((DPOW_VERSION >> 8) & 0xff) )
@ -2112,7 +2117,7 @@ int32_t dpow_nanomsg_update(struct supernet_info *myinfo)
printf("received nnpacket for (%s)\n",np->symbol); printf("received nnpacket for (%s)\n",np->symbol);
else else
{ {
dpow_ipbitsadd(myinfo,dp,np->ipbits,np->numipbits,np->senderind,np->myipbits); dpow_ipbitsadd(myinfo,dp,np->ipbits,np->numipbits,sizeof(np->ipbits)/sizeof(*np->ipbits),np->senderind,np->myipbits);
if ( (bp= dpow_heightfind(myinfo,dp,np->height)) != 0 && bp->state != 0xffffffff && bp->myind >= 0 ) if ( (bp= dpow_heightfind(myinfo,dp,np->height)) != 0 && bp->state != 0xffffffff && bp->myind >= 0 )
{ {
//char str[65]; printf("%s RECV ht.%d ch.%08x (%d) crc32.%08x:%08x datalen.%d:%d firstz.%d i.%d senderind.%d myind.%d\n",bits256_str(str,np->srchash),np->height,np->channel,size,np->crc32,crc32,np->datalen,(int32_t)(size - sizeof(*np)),firstz,i,np->senderind,bp->myind); //char str[65]; printf("%s RECV ht.%d ch.%08x (%d) crc32.%08x:%08x datalen.%d:%d firstz.%d i.%d senderind.%d myind.%d\n",bits256_str(str,np->srchash),np->height,np->channel,size,np->crc32,crc32,np->datalen,(int32_t)(size - sizeof(*np)),firstz,i,np->senderind,bp->myind);

34
iguana/dpow/dpow_prices.c

@ -1438,7 +1438,7 @@ void PAX_update(struct PAX_data *dp,double *btcusdp,double *kmdbtcp)
*kmdbtcp = 0; *kmdbtcp = 0;
bitcoinave = 0;//url_json("https://api.bitcoinaverage.com/ticker/USD/"); bitcoinave = 0;//url_json("https://api.bitcoinaverage.com/ticker/USD/");
//bitcoincharts = url_json("http://api.bitcoincharts.com/v1/weighted_prices.json"); //bitcoincharts = url_json("http://api.bitcoincharts.com/v1/weighted_prices.json");
blockchaininfo = 0;//url_json("https://blockchain.info/ticker"); blockchaininfo = url_json("https://blockchain.info/ticker");
coindesk = 0;//url_json("http://api.coindesk.com/v1/bpi/historical/close.json"); coindesk = 0;//url_json("http://api.coindesk.com/v1/bpi/historical/close.json");
sprintf(url,"https://poloniex.com/public?command=returnChartData&currencyPair=BTC_KMD&start=%ld&end=9999999999&period=86400",(long)(time(NULL)-3600*24)); sprintf(url,"https://poloniex.com/public?command=returnChartData&currencyPair=BTC_KMD&start=%ld&end=9999999999&period=86400",(long)(time(NULL)-3600*24));
sprintf(url2,"https://poloniex.com/public?command=returnChartData&currencyPair=BTC_BTCD&start=%ld&end=9999999999&period=86400",(long)(time(NULL)-3600*24)); sprintf(url2,"https://poloniex.com/public?command=returnChartData&currencyPair=BTC_BTCD&start=%ld&end=9999999999&period=86400",(long)(time(NULL)-3600*24));
@ -1541,7 +1541,7 @@ void PAX_update(struct PAX_data *dp,double *btcusdp,double *kmdbtcp)
if ( (item= jobj(blockchaininfo,"USD")) != 0 && item != 0 && (price= jdouble(item,"15m")) > SMALLVAL ) if ( (item= jobj(blockchaininfo,"USD")) != 0 && item != 0 && (price= jdouble(item,"15m")) > SMALLVAL )
{ {
dpow_price("blockchain.info","BTCUSD",price,price); dpow_price("blockchain.info","BTCUSD",price,price);
//printf("blockchaininfo %f %f\n",btcusd,price); printf("blockchaininfo %f %f\n",btcusd,price);
dxblend(&btcusd,price,0.5); dxblend(&btcusd,price,0.5);
} }
free_json(blockchaininfo); free_json(blockchaininfo);
@ -1832,13 +1832,16 @@ void PAX_genecbsplines(struct PAX_data *dp)
portable_mutex_unlock(&mutex); portable_mutex_unlock(&mutex);
} }
#define BTCFACTOR_TIMESTAMP 1503746319
#define BTCFACTOR_HEIGHT 466266
int32_t PAX_idle(struct supernet_info *myinfo)//struct PAX_data *argdp,int32_t idlegap) int32_t PAX_idle(struct supernet_info *myinfo)//struct PAX_data *argdp,int32_t idlegap)
{ {
static double lastupdate,lastdayupdate; static int32_t didinit; static char *userhome; int32_t idlegap = 10; static double lastupdate,lastdayupdate; static uint32_t didinit; static char *userhome; int32_t idlegap = 10;
FILE *fp; long filesize; char fname[512]; double splineval; uint32_t pvals[128],timestamp; int32_t i,datenum,seconds,c; struct tai t; struct PAX_data *dp; uint8_t data[512]; FILE *fp; long filesize; char fname[512]; double splineval; uint32_t pvals[128],timestamp; int32_t i,datenum,seconds,c; struct tai t; struct PAX_data *dp; uint8_t data[512];
if ( Currencymasks[0] == 0 ) if ( Currencymasks[0] == 0 )
return(0); return(0);
if ( didinit == 0 ) if ( time(NULL) > didinit+12*3600 )
{ {
if ( (userhome= OS_filestr(&filesize,"userhome.txt")) == 0 ) if ( (userhome= OS_filestr(&filesize,"userhome.txt")) == 0 )
userhome = "root"; userhome = "root";
@ -1849,15 +1852,15 @@ int32_t PAX_idle(struct supernet_info *myinfo)//struct PAX_data *argdp,int32_t i
userhome[strlen(userhome)-1] = 0; userhome[strlen(userhome)-1] = 0;
} }
} }
myinfo->PAXDATA = calloc(1,sizeof(*dp)); if ( myinfo->PAXDATA == 0 )
didinit = 1; myinfo->PAXDATA = calloc(1,sizeof(*dp));
dp = myinfo->PAXDATA; dp = myinfo->PAXDATA;
PAX_genecbsplines(dp); PAX_genecbsplines(dp);
printf("generated splines\n"); printf("generated splines\n");
datenum = OS_conv_unixtime(&t,&seconds,(uint32_t)time(NULL)); didinit = (uint32_t)time(NULL);
datenum = OS_conv_unixtime(&t,&seconds,didinit);
expand_datenum(dp->edate,datenum); expand_datenum(dp->edate,datenum);
} }
dp = myinfo->PAXDATA; dp = myinfo->PAXDATA;
/*if ( 0 && time(NULL) > dp->lastupdate+10 ) /*if ( 0 && time(NULL) > dp->lastupdate+10 )
{ {
@ -1904,8 +1907,9 @@ int32_t PAX_idle(struct supernet_info *myinfo)//struct PAX_data *argdp,int32_t i
PAX_emitprices(pvals,dp); PAX_emitprices(pvals,dp);
} }
timestamp = (uint32_t)time(NULL); timestamp = (uint32_t)time(NULL);
int32_t dispflag = ((rand() % 64) == 0); int32_t dispflag = ((rand() % 6) == 0);
if ( dp->kmdbtc == 0 || dispflag != 0 ) //printf("PAX_IDLE.%d %.8f %.8f\n",dispflag,dp->kmdbtc,dp->btcusd);
if ( dp->kmdbtc == 0 || dp->btcusd == 0 || dispflag != 0 )
{ {
PAX_update(dp,&dp->btcusd,&dp->kmdbtc); PAX_update(dp,&dp->btcusd,&dp->kmdbtc);
for (i=0; i<MAX_CURRENCIES; i++) for (i=0; i<MAX_CURRENCIES; i++)
@ -1920,10 +1924,12 @@ int32_t PAX_idle(struct supernet_info *myinfo)//struct PAX_data *argdp,int32_t i
pvals[1] = timestamp; pvals[1] = timestamp;
pvals[2] = MAX_CURRENCIES + 3; pvals[2] = MAX_CURRENCIES + 3;
pvals[3] = PAX_val32(dp->kmdbtc * 1000); pvals[3] = PAX_val32(dp->kmdbtc * 1000);
pvals[4] = PAX_val32(dp->btcusd * .001); double btcfactor;
//if ( time(NULL) > BTCFACTOR_TIMESTAMP )
btcfactor = .00001;
//else btcfactor = .001;
pvals[4] = PAX_val32(dp->btcusd * btcfactor);
pvals[5] = PAX_val32(dp->CNYUSD); pvals[5] = PAX_val32(dp->CNYUSD);
if ( dispflag != 0 )
printf("KMD %.8f BTC %f CNY %f (%f)\n",dp->kmdbtc,dp->btcusd,dp->CNYUSD,1./dp->CNYUSD);
sprintf(fname,"/%s/.komodo/komodofeed",userhome); sprintf(fname,"/%s/.komodo/komodofeed",userhome);
if ( (fp= fopen(fname,"wb")) != 0 ) if ( (fp= fopen(fname,"wb")) != 0 )
{ {
@ -1939,7 +1945,7 @@ int32_t PAX_idle(struct supernet_info *myinfo)//struct PAX_data *argdp,int32_t i
{ {
for (i=0; i<6; i++) for (i=0; i<6; i++)
printf("%u ",pvals[i]); printf("%u ",pvals[i]);
printf("pvals -> %s\n",fname); printf("KMD %.8f BTC %f CNY %f (%f) btcusd pval.%u\n",dp->kmdbtc,dp->btcusd,dp->CNYUSD,1./dp->CNYUSD,pvals[4]);
} }
} }
} }

0
iguana/exchanges/DB/.tmpmarker

0
iguana/exchanges/DB/ECB/.tmpmarker

0
iguana/exchanges/DB/SWAPS/.tmpmarker

0
iguana/exchanges/DB/TRANSACTIONS/.tmpmarker

0
iguana/exchanges/DB/purgeable/.tmpmarker

0
iguana/exchanges/DB/purgeable/BTC/.tmpmarker

0
iguana/exchanges/DB/purgeable/BTCD/.tmpmarker

2
iguana/exchanges/DEXstats.h

@ -927,7 +927,7 @@ char *stats_prices(char *symbol,char *dest,struct DEXstats_disp *prices,int32_t
} }
#ifndef FROM_MARKETMAKER #ifndef FROM_MARKETMAKER
char *stats_JSON(char *myipaddr,int32_t mypubsock,double profitmargin,cJSON *argjson,char *remoteaddr,uint16_t port) char *stats_JSON(void *ctx,char *myipaddr,int32_t mypubsock,cJSON *argjson,char *remoteaddr,uint16_t port)
{ {
char *method,*agent,*retstr,*source,*dest; struct tai T; uint32_t endtimestamp; struct DEXstats_disp prices[365]; int32_t leftdatenum,seconds,numdates; char *method,*agent,*retstr,*source,*dest; struct tai T; uint32_t endtimestamp; struct DEXstats_disp prices[365]; int32_t leftdatenum,seconds,numdates;
if ( (method= jstr(argjson,"method")) == 0 ) if ( (method= jstr(argjson,"method")) == 0 )

55
iguana/exchanges/LP_bitcoin.c

@ -2025,7 +2025,12 @@ int32_t bitcoin_p2shscript(uint8_t *script,int32_t n,const uint8_t *p2shscript,c
char *bitcoind_passthru(char *coinstr,char *serverport,char *userpass,char *method,char *params) char *bitcoind_passthru(char *coinstr,char *serverport,char *userpass,char *method,char *params)
{ {
return(bitcoind_RPC(0,coinstr,serverport,userpass,method,params,2)); return(bitcoind_RPC(0,coinstr,serverport,userpass,method,params,4));
}
char *bitcoind_passthrut(char *coinstr,char *serverport,char *userpass,char *method,char *params,int32_t timeout)
{
return(bitcoind_RPC(0,coinstr,serverport,userpass,method,params,timeout));
} }
int32_t bitcoin_addr2rmd160(uint8_t taddr,uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr) int32_t bitcoin_addr2rmd160(uint8_t taddr,uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr)
@ -2083,7 +2088,7 @@ char *bitcoin_address(char *coinaddr,uint8_t taddr,uint8_t addrtype,uint8_t *pub
return(coinaddr); return(coinaddr);
} }
void iguana_priv2pub(void *ctx,uint8_t *pubkey33,char *coinaddr,bits256 privkey,uint8_t taddr,uint8_t addrtype) void bitcoin_priv2pub(void *ctx,uint8_t *pubkey33,char *coinaddr,bits256 privkey,uint8_t taddr,uint8_t addrtype)
{ {
bits256 pub; //char privstr[65],url[512],postdata[1024],*retstr,*pubstr,*addr; cJSON *retjson; bits256 pub; //char privstr[65],url[512],postdata[1024],*retstr,*pubstr,*addr; cJSON *retjson;
memset(pubkey33,0,33); memset(pubkey33,0,33);
@ -2145,9 +2150,10 @@ int32_t base58encode_checkbuf(uint8_t taddr,uint8_t addrtype,uint8_t *data,int32
return(data_len + 4 + offset); return(data_len + 4 + offset);
} }
int32_t bitcoin_wif2priv(uint8_t *addrtypep,bits256 *privkeyp,char *wifstr) int32_t bitcoin_wif2priv(uint8_t wiftaddr,uint8_t *addrtypep,bits256 *privkeyp,char *wifstr)
{ {
int32_t len = -1; bits256 hash; uint8_t buf[256]; int32_t offset,len = -1; bits256 hash; uint8_t buf[256];
offset = 1 + (wiftaddr != 0);
memset(buf,0,sizeof(buf)); memset(buf,0,sizeof(buf));
if ( (len= bitcoin_base58decode(buf,wifstr)) >= 4 ) if ( (len= bitcoin_base58decode(buf,wifstr)) >= 4 )
{ {
@ -2155,8 +2161,8 @@ int32_t bitcoin_wif2priv(uint8_t *addrtypep,bits256 *privkeyp,char *wifstr)
if ( len < 38 ) if ( len < 38 )
len = 38; len = 38;
hash = bits256_doublesha256(0,buf,len - 4); hash = bits256_doublesha256(0,buf,len - 4);
*addrtypep = *buf; *addrtypep = (wiftaddr == 0) ? *buf : buf[1];
memcpy(privkeyp,buf+1,32); memcpy(privkeyp,buf+offset,32);
if ( (buf[len - 4]&0xff) == hash.bytes[31] && (buf[len - 3]&0xff) == hash.bytes[30] &&(buf[len - 2]&0xff) == hash.bytes[29] && (buf[len - 1]&0xff) == hash.bytes[28] ) if ( (buf[len - 4]&0xff) == hash.bytes[31] && (buf[len - 3]&0xff) == hash.bytes[30] &&(buf[len - 2]&0xff) == hash.bytes[29] && (buf[len - 1]&0xff) == hash.bytes[28] )
{ {
//int32_t i; for (i=0; i<len; i++) //int32_t i; for (i=0; i<len; i++)
@ -2175,18 +2181,30 @@ int32_t bitcoin_wif2priv(uint8_t *addrtypep,bits256 *privkeyp,char *wifstr)
return(-1); return(-1);
} }
int32_t bitcoin_priv2wif(char *wifstr,bits256 privkey,uint8_t addrtype) int32_t bitcoin_wif2addr(void *ctx,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,char *coinaddr,char *wifstr)
{ {
uint8_t data[128]; int32_t len = 32; bits256 privkey; uint8_t addrtype,pubkey33[33];
coinaddr[0] = 0;
if ( bitcoin_wif2priv(wiftaddr,&addrtype,&privkey,wifstr) == sizeof(privkey) )
{
bitcoin_priv2pub(ctx,pubkey33,coinaddr,privkey,taddr,pubtype);
}
return(-1);
}
int32_t bitcoin_priv2wif(uint8_t wiftaddr,char *wifstr,bits256 privkey,uint8_t addrtype)
{
uint8_t data[128]; int32_t offset,len = 32;
memcpy(data+1,privkey.bytes,sizeof(privkey)); memcpy(data+1,privkey.bytes,sizeof(privkey));
data[1 + len++] = 1; offset = 1 + (wiftaddr != 0);
len = base58encode_checkbuf(0,addrtype,data,len); data[offset + len++] = 1;
len = base58encode_checkbuf(wiftaddr,addrtype,data,len);
if ( bitcoin_base58encode(wifstr,data,len) == 0 ) if ( bitcoin_base58encode(wifstr,data,len) == 0 )
return(-1); return(-1);
if ( 1 ) if ( 1 )
{ {
uint8_t checktype; bits256 checkpriv; char str[65],str2[65]; uint8_t checktype; bits256 checkpriv; char str[65],str2[65];
if ( bitcoin_wif2priv(&checktype,&checkpriv,wifstr) == sizeof(bits256) ) if ( bitcoin_wif2priv(wiftaddr,&checktype,&checkpriv,wifstr) == sizeof(bits256) )
{ {
if ( checktype != addrtype || bits256_cmp(checkpriv,privkey) != 0 ) if ( checktype != addrtype || bits256_cmp(checkpriv,privkey) != 0 )
printf("(%s) -> wif.(%s) addrtype.%02x -> %02x (%s)\n",bits256_str(str,privkey),wifstr,addrtype,checktype,bits256_str(str2,checkpriv)); printf("(%s) -> wif.(%s) addrtype.%02x -> %02x (%s)\n",bits256_str(str,privkey),wifstr,addrtype,checktype,bits256_str(str2,checkpriv));
@ -2195,17 +2213,18 @@ int32_t bitcoin_priv2wif(char *wifstr,bits256 privkey,uint8_t addrtype)
return((int32_t)strlen(wifstr)); return((int32_t)strlen(wifstr));
} }
int32_t bitcoin_priv2wiflong(char *wifstr,bits256 privkey,uint8_t addrtype) int32_t bitcoin_priv2wiflong(uint8_t wiftaddr,char *wifstr,bits256 privkey,uint8_t addrtype)
{ {
uint8_t data[128]; int32_t len = 32; uint8_t data[128]; int32_t offset,len = 32;
memcpy(data+1,privkey.bytes,sizeof(privkey)); offset = 1 + (wiftaddr != 0);
len = base58encode_checkbuf(0,addrtype,data,len); memcpy(data+offset,privkey.bytes,sizeof(privkey));
len = base58encode_checkbuf(wiftaddr,addrtype,data,len);
if ( bitcoin_base58encode(wifstr,data,len) == 0 ) if ( bitcoin_base58encode(wifstr,data,len) == 0 )
return(-1); return(-1);
if ( 1 ) if ( 1 )
{ {
uint8_t checktype; bits256 checkpriv; char str[65],str2[65]; uint8_t checktype; bits256 checkpriv; char str[65],str2[65];
if ( bitcoin_wif2priv(&checktype,&checkpriv,wifstr) == sizeof(bits256) ) if ( bitcoin_wif2priv(wiftaddr,&checktype,&checkpriv,wifstr) == sizeof(bits256) )
{ {
if ( checktype != addrtype || bits256_cmp(checkpriv,privkey) != 0 ) if ( checktype != addrtype || bits256_cmp(checkpriv,privkey) != 0 )
printf("(%s) -> wif.(%s) addrtype.%02x -> %02x (%s)\n",bits256_str(str,privkey),wifstr,addrtype,checktype,bits256_str(str2,checkpriv)); printf("(%s) -> wif.(%s) addrtype.%02x -> %02x (%s)\n",bits256_str(str,privkey),wifstr,addrtype,checktype,bits256_str(str2,checkpriv));
@ -2229,11 +2248,11 @@ bits256 LP_pubkey(bits256 privkey)
return(pubkey); return(pubkey);
} }
char *_setVsigner(uint8_t pubtype,struct vin_info *V,int32_t ind,char *pubstr,char *wifstr) char *_setVsigner(uint8_t wiftaddr,uint8_t pubtype,struct vin_info *V,int32_t ind,char *pubstr,char *wifstr)
{ {
uint8_t addrtype; uint8_t addrtype;
decode_hex(V->signers[ind].pubkey,(int32_t)strlen(pubstr)/2,pubstr); decode_hex(V->signers[ind].pubkey,(int32_t)strlen(pubstr)/2,pubstr);
bitcoin_wif2priv(&addrtype,&V->signers[ind].privkey,wifstr); bitcoin_wif2priv(wiftaddr,&addrtype,&V->signers[ind].privkey,wifstr);
if ( addrtype != pubtype ) if ( addrtype != pubtype )
return(clonestr("{\"error\":\"invalid wifA\"}")); return(clonestr("{\"error\":\"invalid wifA\"}"));
else return(0); else return(0);

120
iguana/exchanges/LP_coins.c

@ -18,7 +18,7 @@
// marketmaker // marketmaker
// //
char *portstrs[][2] = { { "BTC", "8332" }, { "KMD", "7771" } }; char *portstrs[][3] = { { "BTC", "8332" }, { "KMD", "7771" } };
uint16_t LP_rpcport(char *symbol) uint16_t LP_rpcport(char *symbol)
{ {
@ -29,6 +29,15 @@ uint16_t LP_rpcport(char *symbol)
return(0); return(0);
} }
uint16_t LP_busport(uint16_t rpcport)
{
if ( rpcport == 8332 )
return(8334); // BTC
else if ( rpcport < (1 << 15) )
return(65535 - rpcport);
else return(rpcport+1);
}
char *parse_conf_line(char *line,char *field) char *parse_conf_line(char *line,char *field)
{ {
line += strlen(field); line += strlen(field);
@ -72,8 +81,13 @@ void LP_userpassfp(char *symbol,char *username,char *password,FILE *fp)
free(rpcpassword); free(rpcpassword);
} }
void LP_statefname(char *fname,char *symbol,char *assetname,char *str,char *name) void LP_statefname(char *fname,char *symbol,char *assetname,char *str,char *name,char *confpath)
{ {
if ( confpath != 0 && confpath[0] != 0 )
{
strcpy(fname,confpath);
return;
}
sprintf(fname,"%s",LP_getdatadir()); sprintf(fname,"%s",LP_getdatadir());
#ifdef WIN32 #ifdef WIN32
strcat(fname,"\\"); strcat(fname,"\\");
@ -129,11 +143,13 @@ void LP_statefname(char *fname,char *symbol,char *assetname,char *str,char *name
strcat(fname,str); strcat(fname,str);
} }
int32_t LP_userpass(char *userpass,char *symbol,char *assetname,char *confroot,char *name) int32_t LP_userpass(char *userpass,char *symbol,char *assetname,char *confroot,char *name,char *confpath)
{ {
FILE *fp; char fname[512],username[512],password[512],confname[16]; FILE *fp; char fname[512],username[512],password[512],confname[512];
userpass[0] = 0; userpass[0] = 0;
sprintf(confname,"%s.conf",confroot); sprintf(confname,"%s.conf",confroot);
if ( 0 )
printf("%s (%s) %s confname.(%s) confroot.(%s)\n",symbol,assetname,name,confname,confroot);
#ifdef __APPLE__ #ifdef __APPLE__
int32_t len; int32_t len;
confname[0] = toupper(confname[0]); confname[0] = toupper(confname[0]);
@ -141,23 +157,31 @@ int32_t LP_userpass(char *userpass,char *symbol,char *assetname,char *confroot,c
if ( strcmp(&confname[len-4],"coin") == 0 ) if ( strcmp(&confname[len-4],"coin") == 0 )
confname[len - 4] = 'C'; confname[len - 4] = 'C';
#endif #endif
LP_statefname(fname,symbol,assetname,confname,name); LP_statefname(fname,symbol,assetname,confname,name,confpath);
if ( (fp= fopen(fname,"rb")) != 0 ) if ( (fp= fopen(fname,"rb")) != 0 )
{ {
LP_userpassfp(symbol,username,password,fp); LP_userpassfp(symbol,username,password,fp);
sprintf(userpass,"%s:%s",username,password); sprintf(userpass,"%s:%s",username,password);
fclose(fp); fclose(fp);
if ( 0 && strcmp(symbol,"HUSH") == 0 ) if ( 0 )
printf("LP_statefname.(%s) <- %s %s %s (%s)\n",fname,name,symbol,assetname,userpass); printf("LP_statefname.(%s) <- %s %s %s (%s) (%s)\n",fname,name,symbol,assetname,userpass,confpath);
return((int32_t)strlen(userpass)); return((int32_t)strlen(userpass));
} else printf("cant open.(%s)\n",fname); } else printf("cant open.(%s)\n",fname);
return(-1); return(-1);
} }
cJSON *LP_coinjson(struct iguana_info *coin) cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif)
{ {
cJSON *item = cJSON_CreateObject(); char wifstr[128]; uint8_t tmptype; bits256 checkkey; cJSON *item = cJSON_CreateObject();
jaddstr(item,"coin",coin->symbol); jaddstr(item,"coin",coin->symbol);
if ( showwif != 0 )
{
bitcoin_priv2wif(coin->wiftaddr,wifstr,LP_mypriv25519,coin->wiftype);
bitcoin_wif2priv(coin->wiftaddr,&tmptype,&checkkey,wifstr);
if ( bits256_cmp(LP_mypriv25519,checkkey) == 0 )
jaddstr(item,"wif",wifstr);
else jaddstr(item,"wif","error creating wif");
}
if ( coin->inactive != 0 ) if ( coin->inactive != 0 )
jaddstr(item,"status","inactive"); jaddstr(item,"status","inactive");
else jaddstr(item,"status","active"); else jaddstr(item,"status","active");
@ -168,21 +192,42 @@ cJSON *LP_coinjson(struct iguana_info *coin)
jaddnum(item,"pubtype",coin->pubtype); jaddnum(item,"pubtype",coin->pubtype);
jaddnum(item,"p2shtype",coin->p2shtype); jaddnum(item,"p2shtype",coin->p2shtype);
jaddnum(item,"wiftype",coin->wiftype); jaddnum(item,"wiftype",coin->wiftype);
jaddnum(item,"estimatedrate",coin->estimatedrate);
jaddnum(item,"txfee",coin->txfee); jaddnum(item,"txfee",coin->txfee);
return(item); return(item);
} }
cJSON *LP_coinsjson() cJSON *LP_coinsjson(int32_t showwif)
{ {
struct iguana_info *coin,*tmp; cJSON *array = cJSON_CreateArray(); struct iguana_info *coin,*tmp; cJSON *array = cJSON_CreateArray();
HASH_ITER(hh,LP_coins,coin,tmp) HASH_ITER(hh,LP_coins,coin,tmp)
{ {
jaddi(array,LP_coinjson(coin)); jaddi(array,LP_coinjson(coin,showwif));
} }
return(array); return(array);
} }
char *LP_getcoin(char *symbol)
{
int32_t numenabled,numdisabled; struct iguana_info *coin,*tmp; cJSON *item=0,*retjson;
numenabled = numdisabled = 0;
retjson = cJSON_CreateObject();
HASH_ITER(hh,LP_coins,coin,tmp)
{
if ( strcmp(symbol,coin->symbol) == 0 )
item = LP_coinjson(coin,0);
if ( coin->inactive == 0 )
numenabled++;
else numdisabled++;
}
jaddstr(retjson,"result","success");
jaddnum(retjson,"enabled",numenabled);
jaddnum(retjson,"disabled",numdisabled);
if ( item == 0 )
item = cJSON_CreateObject();
jadd(retjson,"coin",item);
return(jprint(retjson,1));
}
struct iguana_info *LP_coinsearch(char *symbol) struct iguana_info *LP_coinsearch(char *symbol)
{ {
struct iguana_info *coin; struct iguana_info *coin;
@ -204,7 +249,7 @@ struct iguana_info *LP_coinadd(struct iguana_info *cdata)
return(coin); return(coin);
} }
int32_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *assetname,int32_t isPoS,uint16_t port,uint8_t pubtype,uint8_t p2shtype,uint8_t wiftype,uint64_t txfee,double estimatedrate,int32_t longestchain,uint8_t taddr) int32_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *assetname,int32_t isPoS,uint16_t port,uint8_t pubtype,uint8_t p2shtype,uint8_t wiftype,uint64_t txfee,double estimatedrate,int32_t longestchain,uint8_t wiftaddr,uint8_t taddr,uint16_t busport,char *confpath)
{ {
char *name2; char *name2;
memset(coin,0,sizeof(*coin)); memset(coin,0,sizeof(*coin));
@ -212,17 +257,23 @@ int32_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *asset
sprintf(coin->serverport,"127.0.0.1:%u",port); sprintf(coin->serverport,"127.0.0.1:%u",port);
coin->isPoS = isPoS; coin->isPoS = isPoS;
coin->taddr = taddr; coin->taddr = taddr;
coin->wiftaddr = wiftaddr;
coin->longestchain = longestchain; coin->longestchain = longestchain;
coin->txfee = txfee; coin->txfee = txfee;
coin->estimatedrate = estimatedrate;
coin->pubtype = pubtype; coin->pubtype = pubtype;
coin->p2shtype = p2shtype; coin->p2shtype = p2shtype;
coin->wiftype = wiftype; coin->wiftype = wiftype;
coin->inactive = (uint32_t)time(NULL); coin->inactive = (uint32_t)time(NULL);
coin->bussock = LP_coinbus(busport);
if ( strcmp(symbol,"KMD") == 0 || (assetname != 0 && assetname[0] != 0) ) if ( strcmp(symbol,"KMD") == 0 || (assetname != 0 && assetname[0] != 0) )
name2 = 0; name2 = 0;
else name2 = name; else name2 = name;
return(LP_userpass(coin->userpass,symbol,assetname,name,name2)); if ( strcmp(symbol,"XVG") == 0 || strcmp(symbol,"CLOAK") == 0 || strcmp(symbol,"PPC") == 0 || strcmp(symbol,"BCC") == 0 || strcmp(symbol,"ORB") == 0 )
{
coin->noimportprivkey_flag = 1;
printf("truncate importprivkey for %s\n",symbol);
}
return(LP_userpass(coin->userpass,symbol,assetname,name,name2,confpath));
} }
int32_t LP_isdisabled(char *base,char *rel) int32_t LP_isdisabled(char *base,char *rel)
@ -237,13 +288,15 @@ int32_t LP_isdisabled(char *base,char *rel)
struct iguana_info *LP_coinfind(char *symbol) struct iguana_info *LP_coinfind(char *symbol)
{ {
struct iguana_info *coin,cdata; int32_t isPoS,longestchain = 1; uint16_t port; uint64_t txfee; double estimatedrate; uint8_t pubtype,p2shtype,wiftype; char *name,*assetname; 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 ( (coin= LP_coinsearch(symbol)) != 0 ) if ( (coin= LP_coinsearch(symbol)) != 0 )
return(coin); return(coin);
if ( (port= LP_rpcport(symbol)) == 0 ) if ( (port= LP_rpcport(symbol)) == 0 )
return(0); return(0);
if ( (busport= LP_busport(port)) == 0 )
return(0);
isPoS = 0; isPoS = 0;
txfee = 10000; txfee = LP_MIN_TXFEE;
estimatedrate = 20; estimatedrate = 20;
pubtype = 60; pubtype = 60;
p2shtype = 85; p2shtype = 85;
@ -251,7 +304,7 @@ struct iguana_info *LP_coinfind(char *symbol)
assetname = ""; assetname = "";
if ( strcmp(symbol,"BTC") == 0 ) if ( strcmp(symbol,"BTC") == 0 )
{ {
txfee = 50000; txfee = 0;
estimatedrate = 300; estimatedrate = 300;
pubtype = 0; pubtype = 0;
p2shtype = 5; p2shtype = 5;
@ -261,17 +314,16 @@ struct iguana_info *LP_coinfind(char *symbol)
else if ( strcmp(symbol,"KMD") == 0 ) else if ( strcmp(symbol,"KMD") == 0 )
name = "komodo"; name = "komodo";
else return(0); else return(0);
if ( LP_coininit(&cdata,symbol,name,assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,0) > 0 ) isinactive = LP_coininit(&cdata,symbol,name,assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,0,0,busport,0) < 0;
if ( (coin= LP_coinadd(&cdata)) != 0 )
{ {
if ( (coin= LP_coinadd(&cdata)) != 0 ) coin->inactive = isinactive * (uint32_t)time(NULL);
if ( strcmp(symbol,"KMD") == 0 )
coin->inactive = 0;
else if ( strcmp(symbol,"BTC") == 0 )
{ {
if ( strcmp(symbol,"KMD") == 0 ) coin->inactive = (uint32_t)time(NULL) * !IAMLP;
coin->inactive = 0; printf("BTC inactive.%u\n",coin->inactive);
else if ( strcmp(symbol,"BTC") == 0 )
{
coin->inactive = (uint32_t)time(NULL); // * !IAMLP
printf("BTC inactive.%u\n",coin->inactive);
}
} }
} }
return(coin); return(coin);
@ -286,26 +338,28 @@ struct iguana_info *LP_coincreate(cJSON *item)
if ( (symbol= jstr(item,"coin")) != 0 && symbol[0] != 0 && strlen(symbol) < 16 && LP_coinfind(symbol) == 0 && (port= juint(item,"rpcport")) != 0 ) if ( (symbol= jstr(item,"coin")) != 0 && symbol[0] != 0 && strlen(symbol) < 16 && LP_coinfind(symbol) == 0 && (port= juint(item,"rpcport")) != 0 )
{ {
isPoS = jint(item,"isPoS"); isPoS = jint(item,"isPoS");
if ( (txfee= j64bits(item,"txfee")) == 0 ) txfee = j64bits(item,"txfee");
txfee = 10000;
if ( (estimatedrate= jdouble(item,"estimatedrate")) == 0. ) if ( (estimatedrate= jdouble(item,"estimatedrate")) == 0. )
estimatedrate = 20; estimatedrate = 20;
if ( (pubtype= juint(item,"pubtype")) == 0 ) pubtype = juint(item,"pubtype");
pubtype = 60;
if ( (p2shtype= juint(item,"p2shtype")) == 0 ) if ( (p2shtype= juint(item,"p2shtype")) == 0 )
p2shtype = 85; p2shtype = 85;
if ( (wiftype= juint(item,"wiftype")) == 0 ) if ( (wiftype= juint(item,"wiftype")) == 0 )
wiftype = 188; wiftype = 188;
if ( (assetname= jstr(item,"asset")) != 0 ) if ( (assetname= jstr(item,"asset")) != 0 )
{
name = assetname; name = assetname;
pubtype = 60;
}
else if ( (name= jstr(item,"name")) == 0 ) else if ( (name= jstr(item,"name")) == 0 )
name = symbol; name = symbol;
if ( LP_coininit(&cdata,symbol,name,assetname==0?"":assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,jint(item,"taddr")) < 0 ) if ( LP_coininit(&cdata,symbol,name,assetname==0?"":assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,juint(item,"wiftaddr"),juint(item,"taddr"),LP_busport(port),jstr(item,"confpath")) < 0 )
{ {
coin = LP_coinadd(&cdata); coin = LP_coinadd(&cdata);
coin->inactive = (uint32_t)time(NULL); coin->inactive = (uint32_t)time(NULL);
} else coin = LP_coinadd(&cdata); } else coin = LP_coinadd(&cdata);
} } else if ( symbol != 0 && jobj(item,"rpcport") == 0 )
printf("SKIP %s, missing rpcport field in coins array\n",symbol);
if ( coin != 0 && item != 0 ) if ( coin != 0 && item != 0 )
{ {
if ( strcmp("KMD",coin->symbol) != 0 ) if ( strcmp("KMD",coin->symbol) != 0 )

262
iguana/exchanges/LP_commands.c

@ -18,11 +18,24 @@
// marketmaker // marketmaker
// //
char *LP_numutxos()
{
cJSON *retjson = cJSON_CreateObject();
if ( LP_mypeer != 0 )
{
jaddstr(retjson,"ipaddr",LP_mypeer->ipaddr);
jaddnum(retjson,"port",LP_mypeer->port);
jaddnum(retjson,"numutxos",LP_mypeer->numutxos);
jaddnum(retjson,"numpeers",LP_mypeer->numpeers);
jaddnum(retjson,"session",LP_sessionid);
} else jaddstr(retjson,"error","client node");
return(jprint(retjson,1));
}
char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port 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 otherpeers,othernumutxos,flag = 0; struct LP_peerinfo *peer; cJSON *retjson; struct iguana_info *ptr; 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;
//printf("stats_JSON(%s)\n",jprint(argjson,0)); //printf("stats_JSON(%s)\n",jprint(argjson,0));
if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 ) if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 )
{ {
if ( strcmp(ipaddr,"127.0.0.1") != 0 && argport >= 1000 ) if ( strcmp(ipaddr,"127.0.0.1") != 0 && argport >= 1000 )
@ -41,8 +54,10 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,cJ
printf("change.(%s) numutxos.%d -> %d mynumutxos.%d\n",peer->ipaddr,peer->numutxos,othernumutxos,LP_mypeer != 0 ? LP_mypeer->numutxos:0); printf("change.(%s) numutxos.%d -> %d mynumutxos.%d\n",peer->ipaddr,peer->numutxos,othernumutxos,LP_mypeer != 0 ? LP_mypeer->numutxos:0);
peer->numutxos = othernumutxos; 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)); //printf("peer.(%s) found (%d %d) (%d %d) (%s)\n",peer->ipaddr,peer->numpeers,peer->numutxos,otherpeers,othernumutxos,jprint(argjson,0));
} else LP_addpeer(LP_mypeer,LP_mypubsock,ipaddr,argport,pushport,subport,jdouble(argjson,"profit"),jint(argjson,"numpeers"),jint(argjson,"numutxos")); } 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= jstr(argjson,"method")) == 0 )
@ -51,42 +66,66 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,cJ
printf("stats_JSON no method: (%s) (%s:%u)\n",jprint(argjson,0),ipaddr,argport); printf("stats_JSON no method: (%s) (%s:%u)\n",jprint(argjson,0),ipaddr,argport);
return(0); return(0);
} }
if ( strcmp(method,"hello") == 0 ) /*if ( strcmp(method,"hello") == 0 )
{ {
//printf("got hello from %s:%u\n",ipaddr!=0?ipaddr:"",argport); //printf("got hello from %s:%u\n",ipaddr!=0?ipaddr:"",argport);
return(0); return(0);
} }
else if ( strcmp(method,"nn_tests") == 0 ) else*/ if ( strcmp(method,"sendmessage") == 0 && jobj(argjson,"userpass") == 0 )
return(clonestr("{\"result\":\"success\"}")); {
static char *laststr;
char *newstr; bits256 pubkey = jbits256(argjson,"pubkey");
if ( bits256_nonz(pubkey) == 0 || bits256_cmp(pubkey,LP_mypub25519) == 0 )
{
newstr = jprint(argjson,0);
if ( laststr == 0 || strcmp(laststr,newstr) != 0 )
{
printf("got message.(%s) from %s:%u\n",newstr,ipaddr!=0?ipaddr:"",argport);
if ( laststr != 0 )
free(laststr);
laststr = newstr;
LP_gotmessage(argjson);
retstr = clonestr(laststr);
}
} else retstr = clonestr("{\"error\":\"duplicate message\"}");
}
//else if ( strcmp(method,"nn_tests") == 0 )
// return(clonestr("{\"result\":\"success\"}"));
else if ( strcmp(method,"help") == 0 ) else if ( strcmp(method,"help") == 0 )
return(clonestr("{\"result\":\" \ return(clonestr("{\"result\":\" \
available localhost RPC commands:\n \ available localhost RPC commands:\n \
pricearray(base, rel, firsttime=0, lasttime=-1, timescale=60) -> [timestamp, avebid, aveask, highbid, lowask]\n\
setprice(base, rel, price)\n\ setprice(base, rel, price)\n\
autoprice(base, rel, price, margin, type)\n\
goal(coin=*, val=<autocalc>)\n\
myprice(base, rel)\n\ myprice(base, rel)\n\
enable(coin)\n\ enable(coin)\n\
disable(coin)\n\ disable(coin)\n\
inventory(coin)\n\ inventory(coin)\n\
bestfit(rel, relvolume)\n\ bestfit(rel, relvolume)\n\
ordermatch(base, txfee=0, rel, desttxfee=0, price, txid, vout, feetxid, feevout, duration=3600)\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\ trade(price, timeout=10, duration=3600, <quotejson returned from ordermatch>)\n\
autotrade(base, rel, price, relvolume, timeout=10, duration=3600)\n\ autotrade(base, rel, price, relvolume, timeout=10, duration=3600)\n\
swapstatus()\n\ swapstatus()\n\
swapstatus(requestid, quoteid)\n\ swapstatus(requestid, quoteid)\n\
public API:\n \ public API:\n \
getcoins()\n\ getcoins()\n\
getcoin(coin)\n\
portfolio()\n\
getpeers()\n\ getpeers()\n\
getutxos()\n\ getutxos()\n\
getutxos(coin, lastn)\n\ getutxos(coin, lastn)\n\
orderbook(base, rel, duration=3600)\n\ orderbook(base, rel, duration=3600)\n\
getprices(base, rel)\n\ getprices(base, rel)\n\
trust(pubkey, trust)\n\ sendmessage(base=coin, rel="", pubkey=zero, <argjson method2>)\n\
register(pubkey,pushaddr)\n\ getmessages(firsti=0, num=100)\n\
registerall(numnodes)\n\ clearmessages(firsti=0, num=100)\n\
lookup(pubkey)\n\ secretaddresses(passphrase, num=10, pubtype=60, taddr=0)\n\
forward(pubkey,method2,<argjson>)\n\ snapshot(coin, height)\n\
forward(pubkey,method2=publish,<argjson>)\n\ snapshot_balance(coin, height, addresses[])\n\
forwardhex(pubkey,hex)\n\ dividends(coin, height, <args>)\n\
\"}")); \"}"));
base = jstr(argjson,"base"); base = jstr(argjson,"base");
rel = jstr(argjson,"rel"); rel = jstr(argjson,"rel");
if ( USERPASS[0] != 0 && strcmp(remoteaddr,"127.0.0.1") == 0 && port != 0 ) if ( USERPASS[0] != 0 && strcmp(remoteaddr,"127.0.0.1") == 0 && port != 0 )
@ -96,27 +135,71 @@ forwardhex(pubkey,hex)\n\
USERPASS_COUNTER = 1; USERPASS_COUNTER = 1;
retjson = cJSON_CreateObject(); retjson = cJSON_CreateObject();
jaddstr(retjson,"userpass",USERPASS); jaddstr(retjson,"userpass",USERPASS);
jaddbits256(retjson,"mypubkey",LP_mypubkey); jaddbits256(retjson,"mypubkey",LP_mypub25519);
jadd(retjson,"coins",LP_coinsjson()); jadd(retjson,"coins",LP_coinsjson(LP_showwif));
return(jprint(retjson,1)); return(jprint(retjson,1));
} }
if ( (userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,USERPASS) != 0 ) if ( (userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,USERPASS) != 0 )
return(clonestr("{\"error\":\"authentication error\"}")); return(clonestr("{\"error\":\"authentication error\"}"));
jdelete(argjson,"userpass");
if ( strcmp(method,"sendmessage") == 0 )
{
if ( jobj(argjson,"method2") == 0 )
{
printf("broadcast message\n");
LP_broadcast_message(LP_mypubsock,base!=0?base:jstr(argjson,"coin"),rel,jbits256(argjson,"pubkey"),jprint(argjson,0));
}
return(clonestr("{\"result\":\"success\"}"));
}
else if ( strcmp(method,"getmessages") == 0 )
{
if ( (retjson= LP_getmessages(jint(argjson,"firsti"),jint(argjson,"num"))) != 0 )
return(jprint(retjson,1));
else return(clonestr("{\"error\":\"null messages\"}"));
}
else if ( strcmp(method,"deletemessages") == 0 )
{
LP_deletemessages(jint(argjson,"firsti"),jint(argjson,"num"));
return(clonestr("{\"result\":\"success\"}"));
}
else if ( strcmp(method,"portfolio") == 0 )
{
return(LP_portfolio());
}
else if ( strcmp(method,"secretaddresses") == 0 )
{
uint8_t taddr,pubtype;
pubtype = (jobj(argjson,"pubtype") == 0) ? 60 : juint(argjson,"pubtype");
taddr = (jobj(argjson,"taddr") == 0) ? 0 : juint(argjson,"taddr");
return(LP_secretaddresses(ctx,jstr(argjson,"passphrase"),juint(argjson,"num"),taddr,pubtype));
}
if ( base != 0 && rel != 0 ) if ( base != 0 && rel != 0 )
{ {
double price,bid,ask; double price,bid,ask;
if ( LP_isdisabled(base,rel) != 0 ) if ( IAMLP == 0 && LP_isdisabled(base,rel) != 0 )
return(clonestr("{\"error\":\"at least one of coins disabled\"}")); return(clonestr("{\"error\":\"at least one of coins disabled\"}"));
price = jdouble(argjson,"price"); price = jdouble(argjson,"price");
if ( strcmp(method,"setprice") == 0 ) if ( strcmp(method,"setprice") == 0 )
{ {
if ( price > SMALLVAL ) if ( price > SMALLVAL )
{ {
if ( LP_mypriceset(base,rel,price) < 0 ) if ( LP_mypriceset(&changed,base,rel,price) < 0 )
return(clonestr("{\"error\":\"couldnt set price\"}")); return(clonestr("{\"error\":\"couldnt set price\"}"));
else return(LP_pricepings(ctx,myipaddr,LP_mypubsock,profitmargin,base,rel,price * LP_profitratio)); //else if ( LP_mypriceset(&changed,rel,base,1./price) < 0 )
// return(clonestr("{\"error\":\"couldnt set price\"}"));
else return(LP_pricepings(ctx,myipaddr,LP_mypubsock,base,rel,price * LP_profitratio));
} else return(clonestr("{\"error\":\"no price\"}")); } else return(clonestr("{\"error\":\"no price\"}"));
} }
else if ( strcmp(method,"autoprice") == 0 )
{
if ( LP_autoprice(base,rel,price,jdouble(argjson,"margin"),jstr(argjson,"type")) < 0 )
return(clonestr("{\"error\":\"couldnt set autoprice\"}"));
else return(clonestr("{\"result\":\"success\"}"));
}
else if ( strcmp(method,"pricearray") == 0 )
{
return(jprint(LP_pricearray(base,rel,juint(argjson,"firsttime"),juint(argjson,"lasttime"),jint(argjson,"timescale")),1));
}
else if ( strcmp(method,"myprice") == 0 ) else if ( strcmp(method,"myprice") == 0 )
{ {
if ( LP_myprice(&bid,&ask,base,rel) > SMALLVAL ) if ( LP_myprice(&bid,&ask,base,rel) > SMALLVAL )
@ -132,7 +215,7 @@ forwardhex(pubkey,hex)\n\
else if ( strcmp(method,"ordermatch") == 0 ) else if ( strcmp(method,"ordermatch") == 0 )
{ {
if ( price > SMALLVAL ) if ( price > SMALLVAL )
return(LP_ordermatch(base,j64bits(argjson,"txfee"),price,rel,jbits256(argjson,"txid"),jint(argjson,"vout"),jbits256(argjson,"feetxid"),jint(argjson,"feevout"),j64bits(argjson,"desttxfee"),jint(argjson,"duration"))); 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 return(clonestr("{\"error\":\"no price set\"}"));
} }
else if ( strcmp(method,"trade") == 0 ) else if ( strcmp(method,"trade") == 0 )
@ -141,16 +224,14 @@ forwardhex(pubkey,hex)\n\
if ( price > SMALLVAL || jobj(argjson,"quote") != 0 ) if ( price > SMALLVAL || jobj(argjson,"quote") != 0 )
{ {
LP_quoteparse(&Q,jobj(argjson,"quote")); LP_quoteparse(&Q,jobj(argjson,"quote"));
return(LP_trade(ctx,myipaddr,pubsock,profitmargin,&Q,price,jint(argjson,"timeout"),jint(argjson,"duration"))); 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 return(clonestr("{\"error\":\"no price set or no quote object\"}"));
} }
else if ( strcmp(method,"autotrade") == 0 ) else if ( strcmp(method,"autotrade") == 0 )
{ {
if ( price > SMALLVAL ) if ( price > SMALLVAL )
{ {
printf("price set (%s/%s) <- %.8f\n",rel,base,1./price); return(LP_autotrade(ctx,myipaddr,pubsock,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration")));
LP_mypriceset(rel,base,1./price);
return(LP_autotrade(ctx,myipaddr,pubsock,profitmargin,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration")));
} else return(clonestr("{\"error\":\"no price set\"}")); } else return(clonestr("{\"error\":\"no price set\"}"));
} }
} }
@ -167,24 +248,43 @@ forwardhex(pubkey,hex)\n\
{ {
if ( (ptr= LP_coinsearch(coin)) != 0 ) if ( (ptr= LP_coinsearch(coin)) != 0 )
ptr->inactive = 0; ptr->inactive = 0;
return(jprint(LP_coinsjson(),1)); return(jprint(LP_coinsjson(0),1));
} }
else if ( strcmp(method,"disable") == 0 ) else if ( strcmp(method,"disable") == 0 )
{ {
if ( (ptr= LP_coinsearch(coin)) != 0 ) if ( (ptr= LP_coinsearch(coin)) != 0 )
ptr->inactive = (uint32_t)time(NULL); ptr->inactive = (uint32_t)time(NULL);
return(jprint(LP_coinsjson(),1)); return(jprint(LP_coinsjson(0),1));
}
else if ( strcmp(method,"snapshot") == 0 )
{
if ( (ptr= LP_coinsearch(coin)) != 0 )
return(jprint(LP_snapshot(ptr,juint(argjson,"height")),1));
else return(clonestr("{\"error\":\"cant find coind\"}"));
}
else if ( strcmp(method,"dividends") == 0 )
{
if ( (ptr= LP_coinsearch(coin)) != 0 )
return(LP_dividends(ptr,juint(argjson,"height"),argjson));
else return(clonestr("{\"error\":\"cant find coind\"}"));
}
else if ( strcmp(method,"snapshot_balance") == 0 )
{
if ( (ptr= LP_coinsearch(coin)) != 0 )
return(LP_snapshot_balance(ptr,juint(argjson,"height"),argjson));
else return(clonestr("{\"error\":\"cant find coind\"}"));
} }
if ( LP_isdisabled(coin,0) != 0 ) if ( LP_isdisabled(coin,0) != 0 )
return(clonestr("{\"error\":\"coin is disabled\"}")); return(clonestr("{\"error\":\"coin is disabled\"}"));
if ( strcmp(method,"inventory") == 0 ) if ( strcmp(method,"inventory") == 0 )
{ {
struct iguana_info *ptr; bits256 privkey,pubkey; uint8_t pubkey33[33]; struct iguana_info *ptr;
if ( (ptr= LP_coinfind(coin)) != 0 ) if ( (ptr= LP_coinfind(coin)) != 0 )
{ {
privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,ptr,"",USERPASS_WIFSTR); //privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,ptr,"",USERPASS_WIFSTR);
//LP_utxopurge(0); //LP_utxopurge(0);
LP_privkey_init(-1,ptr,privkey,pubkey,pubkey33); if ( bits256_nonz(LP_mypriv25519) != 0 )
LP_privkey_init(-1,ptr,LP_mypriv25519,LP_mypub25519);
retjson = cJSON_CreateObject(); retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success"); jaddstr(retjson,"result","success");
jaddstr(retjson,"coin",coin); jaddstr(retjson,"coin",coin);
@ -194,7 +294,13 @@ forwardhex(pubkey,hex)\n\
return(jprint(retjson,1)); return(jprint(retjson,1));
} }
} }
else if ( strcmp(method,"goal") == 0 )
return(LP_portfolio_goal(coin,jdouble(argjson,"val")));
else if ( strcmp(method,"getcoin") == 0 )
return(LP_getcoin(coin));
} }
else if ( strcmp(method,"goal") == 0 )
return(LP_portfolio_goal("*",100.));
else if ( strcmp(method,"swapstatus") == 0 ) else if ( strcmp(method,"swapstatus") == 0 )
{ {
uint32_t requestid,quoteid; uint32_t requestid,quoteid;
@ -207,9 +313,22 @@ forwardhex(pubkey,hex)\n\
else if ( strcmp(method,"trust") == 0 ) else if ( strcmp(method,"trust") == 0 )
return(LP_pubkey_trustset(jbits256(argjson,"pubkey"),jint(argjson,"trust"))); return(LP_pubkey_trustset(jbits256(argjson,"pubkey"),jint(argjson,"trust")));
} }
if ( LP_isdisabled(base,rel) != 0 ) if ( IAMLP == 0 )
{
if ( (reqjson= LP_dereference(argjson,"broadcast")) != 0 )
{
if ( jobj(reqjson,"method2") != 0 )
{
jdelete(reqjson,"method");
method = jstr(reqjson,"method2");
jaddstr(reqjson,"method",method);
}
argjson = reqjson;
}
}
if ( IAMLP == 0 && LP_isdisabled(base,rel) != 0 )
return(clonestr("{\"result\":\"at least one of coins disabled\"}")); return(clonestr("{\"result\":\"at least one of coins disabled\"}"));
else if ( LP_isdisabled(jstr(argjson,"coin"),0) != 0 ) else if ( IAMLP == 0 && LP_isdisabled(jstr(argjson,"coin"),0) != 0 )
retstr = clonestr("{\"result\":\"coin is disabled\"}"); retstr = clonestr("{\"result\":\"coin is disabled\"}");
else if ( strcmp(method,"reserved") == 0 ) else if ( strcmp(method,"reserved") == 0 )
retstr = LP_quotereceived(argjson); retstr = LP_quotereceived(argjson);
@ -218,59 +337,63 @@ forwardhex(pubkey,hex)\n\
else if ( strcmp(method,"checktxid") == 0 ) else if ( strcmp(method,"checktxid") == 0 )
retstr = LP_spentcheck(argjson); retstr = LP_spentcheck(argjson);
else if ( strcmp(method,"getcoins") == 0 ) else if ( strcmp(method,"getcoins") == 0 )
return(jprint(LP_coinsjson(),1)); return(jprint(LP_coinsjson(0),1));
else if ( strcmp(method,"numutxos") == 0 )
return(LP_numutxos());
else if ( strcmp(method,"postprice") == 0 ) else if ( strcmp(method,"postprice") == 0 )
retstr = LP_postedprice(argjson); retstr = LP_postedprice(argjson);
else if ( strcmp(method,"broadcast") == 0 ) else if ( strcmp(method,"encrypted") == 0 )
retstr = LP_broadcasted(argjson); retstr = clonestr("{\"result\":\"success\"}");
else if ( strcmp(method,"getprices") == 0 ) else if ( strcmp(method,"getprices") == 0 )
return(LP_prices()); return(LP_prices());
else if ( strcmp(method,"orderbook") == 0 ) else if ( strcmp(method,"orderbook") == 0 )
return(LP_orderbook(base,rel,jint(argjson,"duration"))); return(LP_orderbook(base,rel,jint(argjson,"duration")));
else if ( strcmp(method,"registerall") == 0 ) else if ( strcmp(method,"registerall") == 0 )
return(LP_registerall(jint(argjson,"numnodes"))); return(clonestr("{\"error\":\"you are running an obsolete version, update\"}"));
else if ( strcmp(method,"forward") == 0 ) else if ( strcmp(method,"forward") == 0 )
{ return(clonestr("{\"error\":\"you are running an obsolete version, update\"}"));
cJSON *reqjson;
if ( (reqjson= LP_dereference(argjson,"forward")) != 0 )
{
//printf("FORWARDED.(%s)\n",jprint(argjson,0));
if ( LP_forward(ctx,myipaddr,pubsock,profitmargin,jbits256(argjson,"pubkey"),jprint(reqjson,1),1) > 0 )
retstr = clonestr("{\"result\":\"success\"}");
else retstr = clonestr("{\"result\":\"error forwarding\"}");
} else retstr = clonestr("{\"result\":\"cant recurse forwards\"}");
}
else if ( strcmp(method,"keepalive") == 0 ) else if ( strcmp(method,"keepalive") == 0 )
{ return(clonestr("{\"error\":\"you are running an obsolete version, update\"}"));
printf("got keepalive lag.%d switch.%u\n",(int32_t)time(NULL) - LP_deadman_switch,LP_deadman_switch);
LP_deadman_switch = (uint32_t)time(NULL);
return(clonestr("{\"result\":\"success\"}"));
}
else if ( strcmp(method,"getpeers") == 0 ) else if ( strcmp(method,"getpeers") == 0 )
return(LP_peers()); return(LP_peers());
else if ( strcmp(method,"getutxos") == 0 ) else if ( strcmp(method,"getutxos") == 0 )
return(LP_utxos(1,LP_mypeer,jstr(argjson,"coin"),jint(argjson,"lastn"))); return(LP_utxos(1,LP_mypeer,jstr(argjson,"coin"),jint(argjson,"lastn")));
else if ( strcmp(method,"notified") == 0 ) else if ( strcmp(method,"utxo") == 0 )
{ {
if ( LP_utxoaddjson(1,LP_mypubsock,argjson) != 0 ) if ( LP_utxoaddjson(1,LP_mypubsock,argjson) != 0 )
return(clonestr("{\"result\":\"success\",\"notifyutxo\":\"received\"}")); retstr = clonestr("{\"result\":\"success\",\"utxo\":\"received\"}");
else return(clonestr("{\"result\":\"couldnt add utxo\"}")); else retstr = clonestr("{\"result\":\"couldnt add utxo\"}");
} }
else else
{ {
if ( IAMLP != 0 ) if ( IAMLP != 0 )
{ {
if ( strcmp(method,"register") == 0 ) if ( strcmp(method,"register") == 0 )
return(clonestr("{\"error\":\"you are running an obsolete version, update\"}"));
else if ( strcmp(method,"lookup") == 0 )
return(clonestr("{\"error\":\"you are running an obsolete version, update\"}"));
if ( strcmp(method,"broadcast") == 0 )
{ {
retstr = LP_register(jbits256(argjson,"client"),jstr(argjson,"pushaddr"),juint(argjson,"pushport")); bits256 zero; char *cipherstr; int32_t cipherlen; uint8_t cipher[LP_ENCRYPTED_MAXSIZE];
//printf("got (%s) from register\n",retstr!=0?retstr:""); if ( (reqjson= LP_dereference(argjson,"broadcast")) != 0 )
return(retstr); {
if ( (cipherstr= jstr(reqjson,"cipher")) != 0 )
{
cipherlen = (int32_t)strlen(cipherstr) >> 1;
if ( cipherlen <= sizeof(cipher) )
{
decode_hex(cipher,cipherlen,cipherstr);
LP_queuesend(calc_crc32(0,&cipher[2],cipherlen-2),LP_mypubsock,base,rel,cipher,cipherlen);
} else retstr = clonestr("{\"error\":\"cipher too big\"}");
}
else
{
memset(zero.bytes,0,sizeof(zero));
LP_broadcast_message(LP_mypubsock,base!=0?base:jstr(argjson,"coin"),rel,zero,jprint(reqjson,0));
}
retstr = clonestr("{\"result\":\"success\"}");
} else retstr = clonestr("{\"error\":\"couldnt dereference sendmessage\"}");
} }
else if ( strcmp(method,"lookup") == 0 )
return(LP_lookup(jbits256(argjson,"client")));
else if ( strcmp(method,"forwardhex") == 0 )
retstr = LP_forwardhex(ctx,pubsock,jbits256(argjson,"pubkey"),jstr(argjson,"hex"));
else if ( strcmp(method,"psock") == 0 ) else if ( strcmp(method,"psock") == 0 )
{ {
if ( myipaddr == 0 || myipaddr[0] == 0 || strcmp(myipaddr,"127.0.0.1") == 0 ) if ( myipaddr == 0 || myipaddr[0] == 0 || strcmp(myipaddr,"127.0.0.1") == 0 )
@ -279,25 +402,30 @@ forwardhex(pubkey,hex)\n\
myipaddr = LP_mypeer->ipaddr; myipaddr = LP_mypeer->ipaddr;
else printf("LP_psock dont have actual ipaddr?\n"); else printf("LP_psock dont have actual ipaddr?\n");
} }
return(LP_psock(myipaddr,jint(argjson,"ispaired"))); if ( jint(argjson,"ispaired") != 0 )
return(LP_psock(myipaddr,jint(argjson,"ispaired")));
else return(clonestr("{\"error\":\"you are running an obsolete version, update\"}"));
} }
else if ( strcmp(method,"notify") == 0 ) else if ( strcmp(method,"notify") == 0 )
retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}"); retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}");
} }
else else
{ {
if ( strcmp(method,"register") == 0 ) if ( strcmp(method,"psock") == 0 )
{ {
printf("nonLP got (%s)\n",jprint(argjson,0)); //printf("nonLP got (%s)\n",jprint(argjson,0));
retstr = clonestr("{\"result\":\"success\",\"register\":\"received\"}"); retstr = clonestr("{\"result\":\"success\"}");
} }
} }
} }
if ( retstr == 0 )
printf("ERROR.(%s)\n",jprint(argjson,0));
if ( reqjson != 0 )
free_json(reqjson);
if ( retstr != 0 ) if ( retstr != 0 )
{ {
free(retstr); free(retstr);
return(0); return(0);
} }
printf("ERROR.(%s)\n",jprint(argjson,0));
return(0); return(0);
} }

124
iguana/exchanges/LP_forwarding.c

@ -18,6 +18,19 @@
// marketmaker // marketmaker
// //
cJSON *LP_dereference(cJSON *argjson,char *excludemethod)
{
cJSON *reqjson = 0;
if ( jstr(argjson,"method2") != 0 && strncmp(excludemethod,jstr(argjson,"method2"),strlen(excludemethod)) != 0 )
{
reqjson = jduplicate(argjson);
jdelete(reqjson,"method");
jaddstr(reqjson,"method",jstr(argjson,"method2"));
}
return(reqjson);
}
/*
struct LP_forwardinfo struct LP_forwardinfo
{ {
UT_hash_handle hh; UT_hash_handle hh;
@ -176,24 +189,13 @@ int32_t LP_forwarding_register(bits256 pubkey,char *publicaddr,uint16_t publicpo
if ( peer->pushsock >= 0 ) if ( peer->pushsock >= 0 )
{ {
if ( LP_send(peer->pushsock,argstr,arglen,0) != arglen ) if ( LP_send(peer->pushsock,argstr,arglen,0) != arglen )
printf("error sending command to %s:%u\n",peer->ipaddr,peer->port); {
else printf("sent register to %s:%u\n",peer->ipaddr,peer->port); if ( strncmp(peer->ipaddr,"5.9.253",strlen("5.9.253")) == 0 )
printf("error registering with %s:%u\n",peer->ipaddr,peer->port);
}
n++; n++;
} }
//printf("register.(%s) %s %u with (%s)\n",publicaddr,ipaddr,publicport,peer->ipaddr); //printf("register.(%s) %s %u with (%s)\n",publicaddr,ipaddr,publicport,peer->ipaddr);
/*if ( (retstr= issue_LP_register(peer->ipaddr,peer->port,pubkey,ipaddr,publicport)) != 0 )
{
//printf("[%s] LP_register.(%s) returned.(%s)\n",publicaddr,peer->ipaddr,retstr);
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( jint(retjson,"registered") != 0 && ++n >= max )
retval = 0;
free_json(retjson);
}
free(retstr);
} else printf("timeout registering with %s errs.%d good.%d\n",peer->ipaddr,peer->errors,peer->good);
if ( retval == 0 )
break;*/
} }
free(argstr); free(argstr);
return(n); return(n);
@ -218,18 +220,6 @@ char *LP_registerall(int32_t numnodes)
return(jprint(retjson,1)); return(jprint(retjson,1));
} }
cJSON *LP_dereference(cJSON *argjson,char *excludemethod)
{
cJSON *reqjson = 0;
if ( jstr(argjson,"method2") != 0 && strncmp(excludemethod,jstr(argjson,"method2"),strlen(excludemethod)) != 0 )
{
reqjson = jduplicate(argjson);
jdelete(reqjson,"method");
jaddstr(reqjson,"method",jstr(argjson,"method2"));
}
return(reqjson);
}
char *LP_forwardhex(void *ctx,int32_t pubsock,bits256 pubkey,char *hexstr) char *LP_forwardhex(void *ctx,int32_t pubsock,bits256 pubkey,char *hexstr)
{ {
struct LP_forwardinfo *ptr=0; uint8_t *data; int32_t datalen=0,sentbytes=0; char *msg,*retstr=0; cJSON *retjson=0,*argjson=0,*reqjson=0; struct LP_forwardinfo *ptr=0; uint8_t *data; int32_t datalen=0,sentbytes=0; char *msg,*retstr=0; cJSON *retjson=0,*argjson=0,*reqjson=0;
@ -245,7 +235,7 @@ char *LP_forwardhex(void *ctx,int32_t pubsock,bits256 pubkey,char *hexstr)
if ( reqjson != 0 ) if ( reqjson != 0 )
{ {
retstr = LP_command_process(ctx,LP_mypeer != 0 ? LP_mypeer->ipaddr : "127.0.0.1",LP_mypubsock,reqjson,0,0,LP_profitratio - 1.); retstr = LP_command_process(ctx,LP_mypeer != 0 ? LP_mypeer->ipaddr : "127.0.0.1",LP_mypubsock,reqjson,0,0,LP_profitratio - 1.);
printf("LP_forwardhex.(%s) -> (%s)\n",jprint(reqjson,0),retstr!=0?retstr:""); //printf("LP_forwardhex.(%s) -> (%s)\n",jprint(reqjson,0),retstr!=0?retstr:"");
if ( pubsock >= 0 ) if ( pubsock >= 0 )
{ {
msg = jprint(reqjson,0); msg = jprint(reqjson,0);
@ -255,16 +245,20 @@ char *LP_forwardhex(void *ctx,int32_t pubsock,bits256 pubkey,char *hexstr)
} }
else if ( (ptr= LP_forwardfind(pubkey)) != 0 ) else if ( (ptr= LP_forwardfind(pubkey)) != 0 )
{ {
if ( ptr->pushsock >= 0 )//&& ptr->hello != 0 ) if ( ptr->pushsock >= 0 )
{ {
printf("%s forwardhex.(%s)\n",ptr->pushaddr,(char *)data); printf("%s forwardhex.(%s)\n",ptr->pushaddr,(char *)data);
sentbytes = LP_send(ptr->pushsock,(char *)data,datalen,0); sentbytes = LP_send(ptr->pushsock,(char *)data,datalen,0);
} }
retjson = cJSON_CreateObject(); retjson = cJSON_CreateObject();
if ( sentbytes == datalen ) if ( sentbytes >= 0 )
{ {
jaddstr(retjson,"result","success"); jaddstr(retjson,"result","success");
jaddnum(retjson,"forwarded",sentbytes); if ( sentbytes == datalen )
jaddnum(retjson,"forwarded",sentbytes);
else if ( sentbytes == 0 )
jaddnum(retjson,"queued",sentbytes);
else jaddnum(retjson,"mismatch",sentbytes);
retstr = jprint(retjson,1); retstr = jprint(retjson,1);
} }
else else
@ -294,11 +288,12 @@ char *LP_forwardhex(void *ctx,int32_t pubsock,bits256 pubkey,char *hexstr)
return(retstr); return(retstr);
} }
int32_t LP_forward(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,bits256 pubkey,char *jsonstr,int32_t freeflag) int32_t LP_forward(void *ctx,char *myipaddr,int32_t pubsock,bits256 pubkey,char *jsonstr,int32_t freeflag)
{ {
struct LP_forwardinfo *ptr; struct LP_peerinfo *peer,*tmp; char *msg,*hexstr,*retstr; int32_t len,retval = -1; cJSON *retjson,*reqjson,*argjson; struct LP_forwardinfo *ptr; struct LP_peerinfo *peer,*tmp; char *msg,*hexstr,*retstr; int32_t len,n=0,mlen; cJSON *reqjson,*argjson;
if ( jsonstr == 0 || jsonstr[0] == 0 ) if ( jsonstr == 0 || jsonstr[0] == 0 )
return(-1); return(-1);
len = (int32_t)strlen(jsonstr) + 1;
if ( bits256_nonz(pubkey) != 0 ) if ( bits256_nonz(pubkey) != 0 )
{ {
if ( bits256_cmp(pubkey,LP_mypubkey) == 0 ) if ( bits256_cmp(pubkey,LP_mypubkey) == 0 )
@ -306,55 +301,44 @@ int32_t LP_forward(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,
printf("GOT FORWARDED.(%s)\n",myipaddr); printf("GOT FORWARDED.(%s)\n",myipaddr);
if ( (argjson= cJSON_Parse(jsonstr)) != 0 ) if ( (argjson= cJSON_Parse(jsonstr)) != 0 )
{ {
if ( (retstr= LP_command_process(ctx,myipaddr,pubsock,argjson,0,0,profitmargin)) != 0 ) if ( (retstr= LP_command_process(ctx,myipaddr,pubsock,argjson,0,0)) != 0 )
free(retstr); free(retstr);
free_json(argjson); free_json(argjson);
} }
if ( freeflag != 0 )
free(jsonstr);
return(1); return(1);
} }
else if ( IAMLP != 0 && (ptr= LP_forwardfind(pubkey)) != 0 && ptr->pushsock >= 0 && ptr->lasttime > time(NULL)-LP_KEEPALIVE ) else if ( IAMLP != 0 && (ptr= LP_forwardfind(pubkey)) != 0 && ptr->pushsock >= 0 )
{ {
printf("GOT FORWARDED.(%s) -> pushsock.%d\n",jsonstr,ptr->pushsock); printf("GOT FORWARDED.(%s) -> pushsock.%d\n",jsonstr,ptr->pushsock);
len = (int32_t)strlen(jsonstr); if ( LP_send(ptr->pushsock,jsonstr,len,freeflag) == len )
if ( LP_send(ptr->pushsock,jsonstr,(int32_t)strlen(jsonstr)+1,0) == len+1 )
return(1); return(1);
} }
} }
hexstr = malloc(len*2 + 1);
init_hexbytes_noT(hexstr,(uint8_t *)jsonstr,len);
if ( freeflag != 0 )
free(jsonstr);
reqjson = cJSON_CreateObject();
jaddstr(reqjson,"method","forwardhex");
jaddstr(reqjson,"hex",hexstr);
free(hexstr);
msg = jprint(reqjson,1);
mlen = (int32_t)strlen(msg) + 1;
HASH_ITER(hh,LP_peerinfos,peer,tmp) HASH_ITER(hh,LP_peerinfos,peer,tmp)
{ {
if ( bits256_nonz(pubkey) != 0 ) //printf("found LPnode.(%s) forward.(%s)\n",peer->ipaddr,msg);
{ if ( LP_send(peer->pushsock,msg,mlen,0) == mlen )
if ( (retstr= issue_LP_lookup(peer->ipaddr,peer->port,pubkey)) != 0 ) n++;
{ if ( n >= 8 )//sizeof(default_LPnodes)/sizeof(*default_LPnodes) )
if ( (retjson= cJSON_Parse(retstr)) != 0 ) break;
{
if ( jint(retjson,"forwarding") != 0 && peer->pushsock >= 0 )
retval = 0;
free_json(retjson);
}
free(retstr);
}
} else retval = 0;
if ( retval >= 0 && peer->pushsock >= 0 )
{
printf("found LPnode.(%s) forward.(%s)\n",peer->ipaddr,jsonstr);
len = (int32_t)strlen(jsonstr) + 1;
hexstr = malloc(len*2 + 1);
init_hexbytes_noT(hexstr,(uint8_t *)jsonstr,len);
if ( freeflag != 0 )
free(jsonstr);
reqjson = cJSON_CreateObject();
jaddstr(reqjson,"method","forwardhex");
jaddstr(reqjson,"hex",hexstr);
jaddbits256(reqjson,"pubkey",pubkey);
free(hexstr);
msg = jprint(reqjson,1);
return(LP_send(peer->pushsock,msg,(int32_t)strlen(msg)+1,1));
} else retval = -1;
} }
if ( freeflag != 0 ) if ( msg != 0 )
free(jsonstr); free(msg);
return(-1); if ( n == 0 )
return(-1);
else return(n-1);
} }
@ -363,5 +347,5 @@ char *LP_broadcasted(cJSON *argjson)
printf("RECV BROADCAST.(%s)\n",jprint(argjson,0)); printf("RECV BROADCAST.(%s)\n",jprint(argjson,0));
return(clonestr("{\"result\":\"need to update broadcast messages\"}")); return(clonestr("{\"result\":\"need to update broadcast messages\"}"));
} }
*/

59
iguana/exchanges/LP_include.h

@ -21,12 +21,16 @@
#ifndef LP_INCLUDE_H #ifndef LP_INCLUDE_H
#define LP_INCLUDE_H #define LP_INCLUDE_H
//#define LP_STRICTPEERS
#define LP_COMMAND_SENDSOCK NN_PUSH #define LP_COMMAND_SENDSOCK NN_PUSH
#define LP_COMMAND_RECVSOCK NN_PULL #define LP_COMMAND_RECVSOCK NN_PULL
#define LP_ENCRYPTED_MAXSIZE (4096 + 2 + crypto_box_NONCEBYTES + crypto_box_ZEROBYTES)
#define LP_MAXPUBKEY_ERRORS 3 #define LP_MAXPUBKEY_ERRORS 3
#define PSOCK_KEEPALIVE 3600 #define PSOCK_KEEPALIVE 3600
#define MAINLOOP_PERSEC 10 #define MAINLOOP_PERSEC 100
#define MAX_PSOCK_PORT 60000 #define MAX_PSOCK_PORT 60000
#define MIN_PSOCK_PORT 10000 #define MIN_PSOCK_PORT 10000
#define LP_MEMPOOL_TIMEINCR 10 #define LP_MEMPOOL_TIMEINCR 10
@ -38,11 +42,13 @@
#define LP_MINPEER_GOOD 20 #define LP_MINPEER_GOOD 20
#define LP_PEERGOOD_ERRORDECAY 0.9 #define LP_PEERGOOD_ERRORDECAY 0.9
#define LP_SWAPSTEP_TIMEOUT 3 #define LP_SWAPSTEP_TIMEOUT 30
#define LP_AUTOTRADE_TIMEOUT 10 #define LP_AUTOTRADE_TIMEOUT 60
#define LP_MIN_TXFEE 10000 #define LP_MIN_TXFEE 10000
#define LP_MINVOL 10 #define LP_MINVOL 10
#define LP_MINCLIENTVOL 20 #define LP_MINCLIENTVOL 20
#define LP_MINSIZE_TXFEEMULT 10
#define LP_REQUIRED_TXFEE 0.95
#define LP_DEXFEE(destsatoshis) ((destsatoshis) / INSTANTDEX_INSURANCEDIV) #define LP_DEXFEE(destsatoshis) ((destsatoshis) / INSTANTDEX_INSURANCEDIV)
#define LP_DEPOSITSATOSHIS(satoshis) ((satoshis) + (satoshis >> 3)) #define LP_DEPOSITSATOSHIS(satoshis) ((satoshis) + (satoshis >> 3))
@ -62,7 +68,7 @@
#define LP_PROPAGATION_SLACK 100 // txid ordering is not enforced, so getting extra recent txid #define LP_PROPAGATION_SLACK 100 // txid ordering is not enforced, so getting extra recent txid
#define LP_RESERVETIME 60 #define LP_RESERVETIME 60
#define LP_AVETXSIZE 200 #define LP_AVETXSIZE 256
#define LP_CACHEDURATION 60 #define LP_CACHEDURATION 60
#define BASILISK_DEFAULT_NUMCONFIRMS 1 #define BASILISK_DEFAULT_NUMCONFIRMS 1
#define DEX_SLEEP 3 #define DEX_SLEEP 3
@ -145,7 +151,7 @@ struct basilisk_swapinfo
bits256 myhash,otherhash,orderhash; bits256 myhash,otherhash,orderhash;
uint32_t statebits,otherstatebits,started,expiration,finished,dead,reftime,putduration,callduration; uint32_t statebits,otherstatebits,started,expiration,finished,dead,reftime,putduration,callduration;
int32_t bobconfirms,aliceconfirms,iambob,reclaimed,bobspent,alicespent,pad; int32_t bobconfirms,aliceconfirms,iambob,reclaimed,bobspent,alicespent,pad;
uint64_t alicesatoshis,bobsatoshis,bobinsurance,aliceinsurance; uint64_t alicesatoshis,bobsatoshis,bobinsurance,aliceinsurance,Atxfee,Btxfee;
bits256 myprivs[2],mypubs[2],otherpubs[2],pubA0,pubA1,pubB0,pubB1,privAm,pubAm,privBn,pubBn; bits256 myprivs[2],mypubs[2],otherpubs[2],pubA0,pubA1,pubB0,pubB1,privAm,pubAm,privBn,pubBn;
uint32_t crcs_mypub[2],crcs_mychoosei[2],crcs_myprivs[2],crcs_mypriv[2]; uint32_t crcs_mypub[2],crcs_mychoosei[2],crcs_myprivs[2],crcs_mypriv[2];
@ -160,7 +166,7 @@ struct basilisk_swapinfo
uint8_t userdata_bobrefund[256],userdata_bobrefundlen; uint8_t userdata_bobrefund[256],userdata_bobrefundlen;
}; };
struct LP_outpoint { bits256 spendtxid; uint64_t value,interest; int32_t spendvini,spendheight; }; struct LP_outpoint { bits256 spendtxid; uint64_t value,interest; int32_t spendvini,spendheight; char coinaddr[40]; };
struct LP_transaction struct LP_transaction
{ {
@ -169,25 +175,37 @@ struct LP_transaction
struct LP_outpoint outpoints[]; struct LP_outpoint outpoints[];
}; };
struct LP_address
{
UT_hash_handle hh;
int64_t balance;
char coinaddr[40];
};
struct iguana_info struct iguana_info
{ {
UT_hash_handle hh; UT_hash_handle hh;
portable_mutex_t txmutex; struct LP_transaction *transactions; portable_mutex_t txmutex; struct LP_transaction *transactions; struct LP_address *addresses;
uint64_t txfee; double estimatedrate,profitmargin; uint64_t txfee;
int32_t longestchain,firstrefht,firstscanht,lastscanht; uint32_t counter,inactive,lastmempool,lastgetinfo; int32_t longestchain,firstrefht,firstscanht,lastscanht,bussock; uint16_t busport;
uint8_t pubtype,p2shtype,isPoS,wiftype,taddr; uint32_t counter,inactive,lastmempool,lastgetinfo;
uint8_t pubtype,p2shtype,isPoS,wiftype,wiftaddr,taddr,noimportprivkey_flag;
char symbol[16],smartaddr[64],userpass[1024],serverport[128]; char symbol[16],smartaddr[64],userpass[1024],serverport[128];
// portfolio
double price_kmd,force,perc,goal,goalperc,relvolume;
uint64_t maxamount,kmd_equiv,balanceA,balanceB,valuesumA,valuesumB;
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; };
struct LP_utxostats { uint32_t lasttime,errors,swappending,spentflag,lastspentcheck,bestflag; }; struct LP_utxostats { uint32_t sessionid,lasttime,errors,swappending,spentflag,lastspentcheck,bestflag; };
struct LP_utxobob { struct _LP_utxoinfo utxo,deposit; }; struct LP_utxobob { struct _LP_utxoinfo utxo,deposit; };
struct LP_utxoalice { struct _LP_utxoinfo utxo,fee; }; struct LP_utxoalice { struct _LP_utxoinfo utxo,fee; };
struct LP_utxoswap { bits256 otherpubkey; void *swap; uint64_t satoshis; double profitmargin; }; struct LP_utxoswap { bits256 otherpubkey; void *swap; uint64_t satoshis; };
struct LP_utxoinfo struct LP_utxoinfo
{ {
@ -207,8 +225,7 @@ struct LP_peerinfo
{ {
UT_hash_handle hh; UT_hash_handle hh;
uint64_t ip_port; uint64_t ip_port;
double profitmargin; uint32_t ipbits,errortime,errors,numpeers,numutxos,lasttime,connected,lastutxos,lastpeers,diduquery,good,sessionid;
uint32_t ipbits,errortime,errors,numpeers,numutxos,lasttime,connected,lastutxos,lastpeers,diduquery,good;
int32_t pushsock,subsock; int32_t pushsock,subsock;
uint16_t port; uint16_t port;
char ipaddr[64]; char ipaddr[64];
@ -252,15 +269,21 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3
//double LP_query(char *method,struct LP_quoteinfo *qp,char *base,char *rel,bits256 mypub); //double LP_query(char *method,struct LP_quoteinfo *qp,char *base,char *rel,bits256 mypub);
int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys); int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys);
void LP_quotesinit(char *base,char *rel); void LP_quotesinit(char *base,char *rel);
int32_t LP_forward(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,bits256 pubkey,char *jsonstr,int32_t freeflag); int32_t LP_forward(void *ctx,char *myipaddr,int32_t pubsock,bits256 pubkey,char *jsonstr,int32_t freeflag);
int32_t LP_ismine(struct LP_utxoinfo *utxo); int32_t LP_ismine(struct LP_utxoinfo *utxo);
int32_t LP_isavailable(struct LP_utxoinfo *utxo); int32_t LP_isavailable(struct LP_utxoinfo *utxo);
struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port); struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port);
char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin); 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); void LP_availableset(struct LP_utxoinfo *utxo);
int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2,bits256 pubkey); int32_t LP_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,double profitmargin); 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); uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired);
void LP_utxo_clientpublish(struct LP_utxoinfo *utxo);
int32_t LP_coinbus(uint16_t coin_busport);
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(char *symbol,uint64_t txfee);
#endif #endif

97
iguana/exchanges/LP_messages.c

@ -0,0 +1,97 @@
/******************************************************************************
* Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
//
// LP_messages.c
// marketmaker
//
struct LP_messageinfo { struct LP_messageinfo *next,*prev; cJSON *msgjson; int32_t ind; } *LP_MSGS;
int32_t Num_messages;
void LP_gotmessage(cJSON *argjson)
{
struct LP_messageinfo *msg = calloc(1,sizeof(*msg));
msg->msgjson = jduplicate(argjson);
msg->ind = Num_messages++;
portable_mutex_lock(&LP_messagemutex);
DL_APPEND(LP_MSGS,msg);
portable_mutex_unlock(&LP_messagemutex);
}
void LP_deletemessages(int32_t firsti,int32_t num)
{
struct LP_messageinfo *msg,*tmp; int32_t lasti;
if ( num == 0 )
num = 100;
if ( firsti < 0 )
firsti = 0;
else if ( firsti >= Num_messages )
return;
lasti = firsti + num - 1;
if ( lasti < Num_messages-1 )
lasti = Num_messages - 1;
DL_FOREACH_SAFE(LP_MSGS,msg,tmp)
{
if ( msg->ind >= firsti && msg->ind <= lasti )
{
portable_mutex_lock(&LP_messagemutex);
DL_DELETE(LP_MSGS,msg);
portable_mutex_unlock(&LP_messagemutex);
free_json(msg->msgjson);
free(msg);
}
}
}
cJSON *LP_getmessages(int32_t firsti,int32_t num)
{
struct LP_messageinfo *msg,*tmp; int32_t lasti,n=0,maxi=-1,mini=-1; cJSON *retjson,*item,*array = cJSON_CreateArray();
retjson = cJSON_CreateObject();
if ( num == 0 )
num = 100;
if ( firsti < 0 )
firsti = 0;
else if ( firsti >= Num_messages )
{
jadd(retjson,"messages",array);
return(retjson);
}
lasti = firsti + num - 1;
if ( lasti < Num_messages-1 )
lasti = Num_messages - 1;
DL_FOREACH_SAFE(LP_MSGS,msg,tmp)
{
if ( msg->ind >= firsti && msg->ind <= lasti )
{
item = cJSON_CreateObject();
jaddnum(item,"ind",msg->ind);
jadd(item,"msg",jduplicate(msg->msgjson));
jaddi(array,item);
if ( mini == -1 || msg->ind < mini )
mini = msg->ind;
if ( maxi == -1 || msg->ind > maxi )
maxi = msg->ind;
n++;
}
}
jadd(retjson,"messages",array);
jaddnum(retjson,"firsti",firsti);
jaddnum(retjson,"lasti",lasti);
jaddnum(retjson,"minind",mini);
jaddnum(retjson,"maxind",maxi);
jaddnum(retjson,"num",n);
return(retjson);
}

471
iguana/exchanges/LP_nativeDEX.c

@ -13,25 +13,33 @@
* Removal or modification of this copyright notice is prohibited. * * Removal or modification of this copyright notice is prohibited. *
* * * *
******************************************************************************/ ******************************************************************************/
//alice only coins GAME UNO BTM ANC: GAME BTCD PPC RDD XZC POT EAC FTC BASH SPR WDC UNO XPM XCN BELA CHC DIME MEC NAUT MED AUR MAX DGC RIC EB3 DOT BTM GEO ANC CANN ICASH WBB SRC PTC ADZ TIPS EQT START EFL FST FJC NYC GCN
// //
// LP_nativeDEX.c // LP_nativeDEX.c
// marketmaker // marketmaker
// //
// activate orderbook timeouts // new features:
// verify bid volumes // bittrex balancing
// detect port conflicts on enable
// stats // stats
// auto-utxo creation // PoW, JS
// verify actual pricing
// autoutxo, if < 10*txfee and > 10 utxo: combine smallest utxo into dexfee; autosplit if imbalanced
// unduplicated bugs:
// swap cancel should cleanly cancel
#include <stdio.h> #include <stdio.h>
#include "LP_include.h" #include "LP_include.h"
portable_mutex_t LP_peermutex,LP_UTXOmutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex,LP_forwardmutex,LP_pubkeymutex,LP_networkmutex,LP_psockmutex,LP_coinmutex; 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;
int32_t LP_canbind; int32_t LP_canbind;
#include "LP_network.c"
struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2]; struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2];
struct LP_peerinfo *LP_peerinfos,*LP_mypeer; struct LP_peerinfo *LP_peerinfos,*LP_mypeer;
struct LP_forwardinfo *LP_forwardinfos; struct LP_forwardinfo *LP_forwardinfos;
struct iguana_info *LP_coins; struct iguana_info *LP_coins;
#include "LP_network.c"
char *activecoins[] = { "BTC", "KMD" }; char *activecoins[] = { "BTC", "KMD" };
char GLOBAL_DBDIR[] = { "DB" }; char GLOBAL_DBDIR[] = { "DB" };
@ -40,12 +48,15 @@ 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" }; // 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" }; //
uint32_t LP_deadman_switch; //uint32_t LP_deadman_switch;
uint16_t LP_fixed_pairport,LP_publicport; uint16_t LP_fixed_pairport,LP_publicport;
int32_t LP_mybussock = -1;
int32_t LP_mypubsock = -1; int32_t LP_mypubsock = -1;
int32_t USERPASS_COUNTER,IAMLP = 0; int32_t LP_mypullsock = -1;
int32_t LP_pendingswaps,LP_showwif,USERPASS_COUNTER,IAMLP = 0;
uint32_t LP_sessionid;
double LP_profitratio = 1.; double LP_profitratio = 1.;
bits256 LP_mypubkey; bits256 LP_mypub25519,LP_mypriv25519;
// stubs // stubs
@ -82,122 +93,134 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_
#include "LP_utxos.c" #include "LP_utxos.c"
#include "LP_forwarding.c" #include "LP_forwarding.c"
#include "LP_ordermatch.c" #include "LP_ordermatch.c"
#include "LP_portfolio.c"
#include "LP_messages.c"
#include "LP_commands.c" #include "LP_commands.c"
char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin) char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen)
{ {
char *retstr=0; char *retstr=0;
if ( jobj(argjson,"result") != 0 || jobj(argjson,"error") != 0 ) if ( jobj(argjson,"result") != 0 || jobj(argjson,"error") != 0 )
return(0); return(0);
if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,data,datalen,profitmargin) <= 0 ) if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,data,datalen) <= 0 )
{ {
if ( (retstr= stats_JSON(ctx,myipaddr,pubsock,profitmargin,argjson,"127.0.0.1",0)) != 0 ) if ( (retstr= stats_JSON(ctx,myipaddr,pubsock,argjson,"127.0.0.1",0)) != 0 )
{ {
//printf("%s PULL.[%d]-> (%s)\n",myipaddr != 0 ? myipaddr : "127.0.0.1",datalen,retstr); //printf("%s PULL.[%d]-> (%s)\n",myipaddr != 0 ? myipaddr : "127.0.0.1",datalen,retstr);
if ( pubsock >= 0 ) //strncmp("{\"error\":",retstr,strlen("{\"error\":")) != 0 && //if ( pubsock >= 0 ) //strncmp("{\"error\":",retstr,strlen("{\"error\":")) != 0 &&
LP_send(pubsock,retstr,(int32_t)strlen(retstr)+1,0); //LP_send(pubsock,retstr,(int32_t)strlen(retstr)+1,0);
} }
} }
return(retstr); return(retstr);
} }
char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock,double profitmargin,void *ptr,int32_t recvlen,int32_t recvsock) char *LP_decrypt(uint8_t *ptr,int32_t *recvlenp)
{ {
int32_t len,datalen=0; char *msg,*retstr=0,*jsonstr=0; cJSON *argjson,*reqjson; uint8_t decoded[LP_ENCRYPTED_MAXSIZE + crypto_box_ZEROBYTES],*nonce,*cipher; int32_t recvlen,cipherlen; char *jsonstr = 0;
if ( (datalen= is_hexstr((char *)ptr,0)) > 0 ) recvlen = *recvlenp;
nonce = &ptr[2];
cipher = &ptr[2 + crypto_box_NONCEBYTES];
cipherlen = recvlen - (2 + crypto_box_NONCEBYTES);
if ( cipherlen > 0 && cipherlen <= sizeof(decoded) )
{ {
datalen >>= 1; if ( (jsonstr= (char *)_SuperNET_decipher(nonce,cipher,decoded,cipherlen,GENESIS_PUBKEY,LP_mypriv25519)) != 0 )
jsonstr = malloc(datalen + 1);
decode_hex((void *)jsonstr,datalen,(char *)ptr);
jsonstr[datalen] = 0;
} else jsonstr = (char *)ptr;
if ( 0 && IAMLP == 0 )
printf("%s %d, datalen.%d (%s)\n",typestr,recvlen,datalen,jsonstr);
if ( (argjson= cJSON_Parse(jsonstr)) != 0 )
{
len = (int32_t)strlen(jsonstr) + 1;
portable_mutex_lock(&LP_commandmutex);
if ( jstr(argjson,"method") != 0 && strcmp(jstr(argjson,"method"),"forwardhex") == 0 )
{ {
//printf("got forwardhex\n"); recvlen = (cipherlen - crypto_box_ZEROBYTES);
if ( (retstr= LP_forwardhex(ctx,pubsock,jbits256(argjson,"pubkey"),jstr(argjson,"hex"))) != 0 ) if ( strlen(jsonstr)+1 != recvlen )
{ {
} printf("unexpected len %d vs recvlen.%d\n",(int32_t)strlen(jsonstr)+1,recvlen);
jsonstr = 0;
} else printf("decrypted (%s)\n",jsonstr);
} }
else if ( jstr(argjson,"method") != 0 && strcmp(jstr(argjson,"method"),"publish") == 0 ) } else printf("cipher.%d too big for %d\n",cipherlen,(int32_t)sizeof(decoded));
*recvlenp = recvlen;
return(jsonstr);
}
char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock,uint8_t *ptr,int32_t recvlen,int32_t recvsock)
{
static uint32_t dup,uniq;
int32_t i,len,cipherlen,datalen=0,duplicate=0,encrypted=0; char *method,*method2,*tmp,*cipherstr,*retstr=0,*jsonstr=0; cJSON *argjson; uint32_t crc32;
crc32 = calc_crc32(0,&ptr[2],recvlen-2);
if ( (crc32 & 0xff) == ptr[0] && ((crc32>>8) & 0xff) == ptr[1] )
encrypted = 1;
portable_mutex_lock(&LP_commandmutex);
i = LP_crc32find(&duplicate,-1,crc32);
if ( duplicate != 0 )
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);
if ( duplicate == 0 )
{
if ( i >= 0 )
LP_crc32find(&duplicate,i,crc32);
if ( encrypted != 0 )
jsonstr = LP_decrypt(ptr,&recvlen);
else if ( (datalen= is_hexstr((char *)ptr,0)) > 0 )
{ {
printf("got publish\n"); datalen >>= 1;
if ( jobj(argjson,"method2") != 0 ) jsonstr = malloc(datalen + 1);
jdelete(argjson,"method2"); decode_hex((void *)jsonstr,datalen,(char *)ptr);
jaddstr(argjson,"method2","broadcast"); jsonstr[datalen] = 0;
if ( pubsock >= 0 && (reqjson= LP_dereference(argjson,"publish")) != 0 ) } else jsonstr = (char *)ptr;
{ if ( jsonstr != 0 && (argjson= cJSON_Parse(jsonstr)) != 0 )
msg = jprint(reqjson,1);
LP_send(pubsock,msg,(int32_t)strlen(msg)+1,1);
}
}
else if ( (retstr= LP_command_process(ctx,myipaddr,pubsock,argjson,&((uint8_t *)ptr)[len],recvlen - len,profitmargin)) != 0 )
{ {
} uint8_t decoded[LP_ENCRYPTED_MAXSIZE + crypto_box_ZEROBYTES];
portable_mutex_unlock(&LP_commandmutex); //printf("[%s]\n",jsonstr);
if ( LP_COMMAND_RECVSOCK == NN_REP ) cipherlen = 0;
{ if ( (cipherstr= jstr(argjson,"cipher")) != 0 && (cipherlen= is_hexstr(cipherstr,0)) > 32 && cipherlen <= sizeof(decoded)*2 )
if ( retstr != 0 )
{ {
if ( strcmp("PULL",typestr) == 0 ) method2 = jstr(argjson,"method2");
if ( (method= jstr(argjson,"method")) != 0 && (strcmp(method,"encrypted") == 0 ||(method2 != 0 && strcmp(method2,"encrypted") == 0)) )
{ {
printf("%d got REQ.(%s) -> (%s)\n",recvsock,jprint(argjson,0),retstr); cipherlen >>= 1;
LP_send(recvsock,retstr,(int32_t)strlen(retstr)+1,0); decode_hex(decoded,cipherlen,cipherstr);
} crc32 = calc_crc32(0,&decoded[2],cipherlen-2);
if ( (tmp= LP_decrypt(decoded,&cipherlen)) != 0 )
{
jsonstr = tmp;
free_json(argjson);
argjson = cJSON_Parse(jsonstr);
recvlen = cipherlen;
encrypted = 1;
if ( (crc32 & 0xff) == decoded[0] && ((crc32>>8) & 0xff) == decoded[1] )
{
i = LP_crc32find(&duplicate,-1,crc32);
if ( duplicate == 0 && i >= 0 )
LP_crc32find(&duplicate,i,crc32);
}
printf("%02x %02x %08x duplicate.%d decrypted.(%s)\n",decoded[0],decoded[1],crc32,duplicate,jsonstr);
}
else
{
printf("packet not for this node %u\n",crc32);
}
} else printf("error (%s) method is %s\n",jsonstr,method);
} }
else if ( strcmp("PULL",typestr) == 0 ) if ( jsonstr != 0 && argjson != 0 )
{ {
printf("%d got REQ.(%s) -> null\n",recvsock,jprint(argjson,0)); len = (int32_t)strlen(jsonstr) + 1;
LP_send(recvsock,"{\"result\":null}",(int32_t)strlen("{\"result\":null}")+1,0); if ( (retstr= LP_command_process(ctx,myipaddr,pubsock,argjson,&((uint8_t *)ptr)[len],recvlen - len)) != 0 )
{
}
free_json(argjson);
} }
} }
free_json(argjson); } //else printf("DUPLICATE.(%s)\n",(char *)ptr);
} else printf("error parsing(%s)\n",jsonstr); portable_mutex_unlock(&LP_commandmutex);
if ( (void *)jsonstr != ptr ) if ( jsonstr != 0 && (void *)jsonstr != (void *)ptr && encrypted == 0 )
free(jsonstr); free(jsonstr);
if ( ptr != 0 ) if ( ptr != 0 )
nn_freemsg(ptr), ptr = 0; nn_freemsg(ptr), ptr = 0;
return(retstr); return(retstr);
} }
int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsock,int32_t pullsock,double profitmargin) void LP_utxo_spentcheck(int32_t pubsock,struct LP_utxoinfo *utxo)
{
void *ptr; int32_t recvlen=-1,nonz = 0;
*retstrp = 0;
if ( pullsock >= 0 )
{
while ( (recvlen= nn_recv(pullsock,&ptr,NN_MSG,0)) > 0 )
{
nonz++;
*retstrp = LP_process_message(ctx,"PULL",myipaddr,pubsock,profitmargin,ptr,recvlen,pullsock);
}
}
return(nonz);
}
int32_t LP_subsock_check(void *ctx,char *myipaddr,int32_t pubsock,int32_t sock,double profitmargin)
{
int32_t recvlen,nonz = 0; void *ptr; char *retstr;
if ( sock >= 0 )
{
while ( (recvlen= nn_recv(sock,&ptr,NN_MSG,0)) > 0 )
{
nonz++;
if ( (retstr= LP_process_message(ctx,"SUB",myipaddr,pubsock,profitmargin,ptr,recvlen,sock)) != 0 )
free(retstr);
}
}
return(nonz);
}
void LP_utxo_spentcheck(int32_t pubsock,struct LP_utxoinfo *utxo,double profitmargin)
{ {
struct _LP_utxoinfo u; char str[65]; uint32_t now = (uint32_t)time(NULL); 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); //printf("%s lag.%d\n",bits256_str(str,utxo->txid),now-utxo->lastspentcheck);
if ( utxo->T.spentflag == 0 && now > utxo->T.lastspentcheck+60 ) if ( utxo->T.spentflag == 0 && now > utxo->T.lastspentcheck+60 )
{ {
@ -216,13 +239,13 @@ void LP_utxo_spentcheck(int32_t pubsock,struct LP_utxoinfo *utxo,double profitma
} }
} }
void LP_myutxo_updates(void *ctx,int32_t pubsock,char *passphrase,double profitmargin) void LP_myutxo_updates(void *ctx,int32_t pubsock,char *passphrase)
{ {
//LP_utxopurge(0); not good to disrupt existing pointers //LP_utxopurge(0); not good to disrupt existing pointers
LP_privkey_updates(ctx,pubsock,passphrase,0); LP_privkey_updates(ctx,pubsock,passphrase,0);
} }
int32_t LP_peer_utxosquery(struct LP_peerinfo *mypeer,uint16_t myport,int32_t pubsock,struct LP_peerinfo *peer,uint32_t now,double profitmargin,int32_t interval) int32_t 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; int32_t lastn,n = -1;
if ( peer->lastutxos < now-interval ) if ( peer->lastutxos < now-interval )
@ -234,16 +257,75 @@ int32_t LP_peer_utxosquery(struct LP_peerinfo *mypeer,uint16_t myport,int32_t pu
{ {
peer->lastutxos = now; peer->lastutxos = now;
//printf("query utxos from %s\n",peer->ipaddr); //printf("query utxos from %s\n",peer->ipaddr);
n = LP_utxosquery(mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,profitmargin); 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); } //else printf("LP_peer_utxosquery skip.(%s) %u\n",peer->ipaddr,peer->lastutxos);
return(n); return(n);
} }
int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int32_t pubsock,char *pushaddr,uint16_t pushport,int32_t pullsock,uint16_t myport,char *passphrase,double profitmargin) 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;
if ( sock >= 0 )
{
while ( nonz < 1000 && recvlen > 0 )
{
memset(&pfd,0,sizeof(pfd));
pfd.fd = sock;
pfd.events = NN_POLLIN;
if ( nn_poll(&pfd,1,1) != 1 )
break;
if ( (recvlen= nn_recv(sock,&ptr,NN_MSG,0)) > 0 )
{
nonz++;
if ( (retstr= LP_process_message(ctx,typestr,myipaddr,pubsock,ptr,recvlen,sock)) != 0 )
free(retstr);
}
}
}
return(nonz);
}
void command_rpcloop(void *myipaddr)
{
int32_t nonz = 0; char *origipaddr; struct LP_peerinfo *peer,*tmp; void *ctx; //struct iguana_info *coin,*ctmp;
ctx = bitcoin_ctx();
if ( (origipaddr= myipaddr) == 0 )
origipaddr = "127.0.0.1";
while ( 1 )
{
nonz = 0;
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
if ( peer->errors >= LP_MAXPEER_ERRORS )
{
if ( (rand() % 10000) == 0 )
peer->errors--;
else continue;
}
//printf("check %s pubsock.%d\n",peer->ipaddr,peer->subsock);
nonz += LP_sock_check("PULL",ctx,origipaddr,LP_mypubsock,peer->subsock);
}
/*HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht
{
if ( coin->inactive != 0 )
continue;
if ( coin->bussock >= 0 )
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);
//if ( LP_mybussock >= 0 )
// nonz += LP_sock_check("BUS",ctx,origipaddr,-1,LP_mybussock);
if ( nonz == 0 )
usleep(10000);
}
}
int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int32_t pubsock,char *pushaddr,uint16_t myport,char *passphrase)
{ {
static uint32_t counter,lastforward,numpeers; static uint32_t counter,numpeers,lastresync; //lastforward
struct LP_utxoinfo *utxo,*utmp; struct iguana_info *coin,*ctmp; char *retstr,*origipaddr; struct LP_peerinfo *peer,*tmp; uint32_t now; int32_t nonz = 0,n=0,lastn=-1; 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;
now = (uint32_t)time(NULL); now = (uint32_t)time(NULL);
if ( (origipaddr= myipaddr) == 0 ) if ( (origipaddr= myipaddr) == 0 )
origipaddr = "127.0.0.1"; origipaddr = "127.0.0.1";
@ -251,90 +333,88 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
myipaddr = "127.0.0.1"; myipaddr = "127.0.0.1";
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d peers\n",counter,LP_canbind); //if ( LP_canbind == 0 ) printf("counter.%d canbind.%d peers\n",counter,LP_canbind);
numpeers = LP_numpeers(); numpeers = LP_numpeers();
mostutxos = 0;
mostpeer = 0;
HASH_ITER(hh,LP_peerinfos,peer,tmp) HASH_ITER(hh,LP_peerinfos,peer,tmp)
{ {
if ( peer->errors >= LP_MAXPEER_ERRORS ) if ( peer->errors >= LP_MAXPEER_ERRORS )
{ {
if ( (rand() % 10000) == 0 ) if ( (rand() % 10000) == 0 )
{
peer->errors--; peer->errors--;
else continue; 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() % 10000) == 0) )
{ {
if ( IAMLP != 0 ) //if ( IAMLP != 0 )
printf("numpeers.%d updatepeer.%s lag.%d\n",numpeers,peer->ipaddr,now-peer->lastpeers); // printf("numpeers.%d updatepeer.%s lag.%d\n",numpeers,peer->ipaddr,now-peer->lastpeers);
peer->lastpeers = now; peer->lastpeers = now;
if ( IAMLP != 0 && peer->numpeers != numpeers ) //if ( IAMLP != 0 && peer->numpeers != numpeers )
printf("%s num.%d vs %d\n",peer->ipaddr,peer->numpeers,numpeers); // printf("%s num.%d vs %d\n",peer->ipaddr,peer->numpeers,numpeers);
if ( strcmp(peer->ipaddr,myipaddr) != 0 ) if ( strcmp(peer->ipaddr,myipaddr) != 0 )
LP_peersquery(mypeer,pubsock,peer->ipaddr,peer->port,myipaddr,myport,profitmargin); 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;
}
}
} }
if ( peer->diduquery == 0 ) if ( peer->diduquery == 0 )
{ {
if ( lastn != n || n < 20 ) if ( lastn != n || n < 20 )
{ {
lastn = n; lastn = n;
n = LP_peer_utxosquery(mypeer,myport,pubsock,peer,now,profitmargin,60); n = LP_peer_utxosquery(mypeer,myport,pubsock,peer,now,60,100);
} }
LP_peer_pricesquery(peer->ipaddr,peer->port); LP_peer_pricesquery(peer->ipaddr,peer->port);
peer->diduquery = now; peer->diduquery = now;
} }
nonz += LP_subsock_check(ctx,origipaddr,pubsock,peer->subsock,profitmargin); if ( peer->numutxos > mostutxos )
}
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d forwarding\n",counter,LP_canbind);
if ( (counter % 600) == 20 )
{
LP_myutxo_updates(ctx,pubsock,passphrase,profitmargin);
if ( lastforward < now-3600 )
{ {
if ( (retstr= LP_registerall(0)) != 0 ) mostutxos = peer->numutxos;
free(retstr); mostpeer = peer;
LP_forwarding_register(LP_mypubkey,pushaddr,pushport,10);
lastforward = now;
} }
} }
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d utxos\n",counter,LP_canbind); //printf("numutxos vs mine.%d\n",LP_mypeer != 0 ? LP_mypeer->numutxos : -1);
if ( (counter % 600) == 60 ) if ( LP_mypeer != 0 && mostpeer != 0 && ((LP_mypeer->numutxos < mostutxos && time(NULL) > lastresync+10) || time(NULL) > lastresync+60) )
{ {
//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);
}
if ( (counter % 6000) == 10 )
{
LP_myutxo_updates(ctx,pubsock,passphrase);
HASH_ITER(hh,LP_utxoinfos[0],utxo,utmp) HASH_ITER(hh,LP_utxoinfos[0],utxo,utmp)
{ {
LP_utxo_spentcheck(pubsock,utxo,profitmargin); LP_utxo_spentcheck(pubsock,utxo);
} }
HASH_ITER(hh,LP_utxoinfos[1],utxo,utmp) HASH_ITER(hh,LP_utxoinfos[1],utxo,utmp)
{ {
//char str[65]; LP_utxo_spentcheck(pubsock,utxo);
LP_utxo_spentcheck(pubsock,utxo,profitmargin); if ( LP_isunspent(utxo) > 0 && utxo->T.lasttime == 0 && LP_ismine(utxo) > 0 )
if ( utxo->T.lasttime == 0 ) {
char str[65]; printf("publish mybob %s\n",bits256_str(str,utxo->payment.txid));
LP_utxo_clientpublish(utxo); LP_utxo_clientpublish(utxo);
//else if ( strcmp(utxo->coin,"HUSH") == 0 ) }
// printf("lasttime set %s\n",bits256_str(str,utxo->payment.txid));
}
}
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d swapentry\n",counter,LP_canbind);
if ( (counter % 6000) == 5999 )
{
if ( (retstr= basilisk_swapentry(0,0)) != 0 )
{
//printf("SWAPS.(%s)\n",retstr);
free(retstr);
}
}
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d pullsock check\n",counter,LP_canbind);
nonz += LP_pullsock_check(ctx,&retstr,myipaddr,pubsock,pullsock,profitmargin);
if ( retstr != 0 )
free(retstr);
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d hellos\n",counter,LP_canbind);
if ( IAMLP != 0 && (counter % 600) == 42 )
LP_hellos();
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d\n",counter,LP_canbind);
if ( LP_canbind == 0 && (counter % (PSOCK_KEEPALIVE*MAINLOOP_PERSEC/2)) == 13 )
{
char keepalive[128];
sprintf(keepalive,"{\"method\":\"keepalive\"}");
//printf("send keepalive to %s pullsock.%d\n",pushaddr,pullsock);
if ( LP_send(pullsock,keepalive,(int32_t)strlen(keepalive)+1,0) < 0 )
{
//LP_deadman_switch = 0;
} }
} }
HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht
@ -367,9 +447,9 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
printf("detected %s firstrefht.%d < firstscanht.%d\n",coin->symbol,coin->firstrefht,coin->firstscanht); printf("detected %s firstrefht.%d < firstscanht.%d\n",coin->symbol,coin->firstrefht,coin->firstscanht);
coin->lastscanht = coin->firstscanht = coin->firstrefht; coin->lastscanht = coin->firstscanht = coin->firstrefht;
} }
if ( coin->lastscanht == coin->longestchain ) if ( coin->lastscanht == coin->longestchain+1 )
continue; continue;
else if ( coin->lastscanht > coin->longestchain ) else if ( coin->lastscanht > coin->longestchain+1 )
{ {
printf("detected chain rewind lastscanht.%d vs longestchain.%d, first.%d ref.%d\n",coin->lastscanht,coin->longestchain,coin->firstscanht,coin->firstrefht); printf("detected chain rewind lastscanht.%d vs longestchain.%d, first.%d ref.%d\n",coin->lastscanht,coin->longestchain,coin->firstscanht,coin->firstrefht);
LP_undospends(coin,coin->longestchain-1); LP_undospends(coin,coin->longestchain-1);
@ -379,7 +459,7 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
coin->lastscanht = coin->firstscanht; coin->lastscanht = coin->firstscanht;
continue; continue;
} }
printf("%s ref.%d scan.%d to %d, longest.%d\n",coin->symbol,coin->firstrefht,coin->firstscanht,coin->lastscanht,coin->longestchain); //printf("%s ref.%d scan.%d to %d, longest.%d\n",coin->symbol,coin->firstrefht,coin->firstscanht,coin->lastscanht,coin->longestchain);
if ( LP_blockinit(coin,coin->lastscanht) < 0 ) if ( LP_blockinit(coin,coin->lastscanht) < 0 )
{ {
printf("blockinit.%s %d error\n",coin->symbol,coin->lastscanht); printf("blockinit.%s %d error\n",coin->symbol,coin->lastscanht);
@ -388,6 +468,14 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
coin->lastscanht++; coin->lastscanht++;
break; break;
} }
if ( (counter % 6000) == 60 )
{
if ( (retstr= basilisk_swapentry(0,0)) != 0 )
{
//printf("SWAPS.(%s)\n",retstr);
free(retstr);
}
}
counter++; counter++;
return(nonz); return(nonz);
} }
@ -415,12 +503,12 @@ void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins,char *passphrase)
LP_privkey_updates(ctx,pubsock,passphrase,1); LP_privkey_updates(ctx,pubsock,passphrase,1);
} }
void LP_initpeers(int32_t pubsock,struct LP_peerinfo *mypeer,char *myipaddr,uint16_t myport,char *seednode,double profitmargin) void LP_initpeers(int32_t pubsock,struct LP_peerinfo *mypeer,char *myipaddr,uint16_t myport,char *seednode)
{ {
int32_t i,j; uint32_t r; int32_t i,j; uint32_t r;
if ( IAMLP != 0 ) if ( IAMLP != 0 )
{ {
LP_mypeer = mypeer = LP_addpeer(mypeer,pubsock,myipaddr,myport,0,0,profitmargin,0,0); LP_mypeer = mypeer = LP_addpeer(mypeer,pubsock,myipaddr,myport,0,0,0,0,LP_sessionid);
if ( myipaddr == 0 || mypeer == 0 ) if ( myipaddr == 0 || mypeer == 0 )
{ {
printf("couldnt get myipaddr or null mypeer.%p\n",mypeer); printf("couldnt get myipaddr or null mypeer.%p\n",mypeer);
@ -430,11 +518,11 @@ void LP_initpeers(int32_t pubsock,struct LP_peerinfo *mypeer,char *myipaddr,uint
{ {
for (i=0; i<sizeof(default_LPnodes)/sizeof(*default_LPnodes); i++) for (i=0; i<sizeof(default_LPnodes)/sizeof(*default_LPnodes); i++)
{ {
if ( (rand() % 100) > 25 ) //if ( (rand() % 100) > 25 )
continue; // continue;
LP_peersquery(mypeer,pubsock,default_LPnodes[i],myport,mypeer->ipaddr,myport,profitmargin); LP_peersquery(mypeer,pubsock,default_LPnodes[i],myport,mypeer->ipaddr,myport);
} }
} else LP_peersquery(mypeer,pubsock,seednode,myport,mypeer->ipaddr,myport,profitmargin); } else LP_peersquery(mypeer,pubsock,seednode,myport,mypeer->ipaddr,myport);
} }
else else
{ {
@ -449,15 +537,16 @@ void LP_initpeers(int32_t pubsock,struct LP_peerinfo *mypeer,char *myipaddr,uint
for (j=0; j<sizeof(default_LPnodes)/sizeof(*default_LPnodes); j++) for (j=0; j<sizeof(default_LPnodes)/sizeof(*default_LPnodes); j++)
{ {
i = (r + j) % (sizeof(default_LPnodes)/sizeof(*default_LPnodes)); i = (r + j) % (sizeof(default_LPnodes)/sizeof(*default_LPnodes));
LP_peersquery(mypeer,pubsock,default_LPnodes[i],myport,"127.0.0.1",myport,profitmargin); LP_peersquery(mypeer,pubsock,default_LPnodes[i],myport,"127.0.0.1",myport);
} }
} else LP_peersquery(mypeer,pubsock,seednode,myport,"127.0.0.1",myport,profitmargin); } else LP_peersquery(mypeer,pubsock,seednode,myport,"127.0.0.1",myport);
} }
} }
void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profitmargin,char *passphrase,int32_t amclient,char *userhome,cJSON *argjson) void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybusport,char *passphrase,int32_t amclient,char *userhome,cJSON *argjson)
{ {
char *myipaddr=0,*retstr; long filesize,n; int32_t timeout,pullsock=-1,pubsock=-1; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128],bindaddr[128]; void *ctx = bitcoin_ctx(); char *myipaddr=0; long filesize,n; int32_t timeout,pubsock=-1; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128],bindaddr[128]; void *ctx = bitcoin_ctx();
LP_showwif = juint(argjson,"wif");
if ( passphrase == 0 || passphrase[0] == 0 ) if ( passphrase == 0 || passphrase[0] == 0 )
{ {
printf("jeezy says we cant use the nullstring as passphrase and I agree\n"); printf("jeezy says we cant use the nullstring as passphrase and I agree\n");
@ -471,7 +560,6 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profit
exit(-1); exit(-1);
} }
#endif #endif
LP_profitratio += profitmargin;
OS_randombytes((void *)&n,sizeof(n)); OS_randombytes((void *)&n,sizeof(n));
if ( jobj(argjson,"gui") != 0 ) if ( jobj(argjson,"gui") != 0 )
safecopy(LP_gui,jstr(argjson,"gui"),sizeof(LP_gui)); safecopy(LP_gui,jstr(argjson,"gui"),sizeof(LP_gui));
@ -511,11 +599,10 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profit
portable_mutex_init(&LP_psockmutex); portable_mutex_init(&LP_psockmutex);
portable_mutex_init(&LP_coinmutex); portable_mutex_init(&LP_coinmutex);
portable_mutex_init(&LP_pubkeymutex); portable_mutex_init(&LP_pubkeymutex);
if ( profitmargin == 0. || profitmargin == 0.01 ) portable_mutex_init(&LP_messagemutex);
{ portable_mutex_init(&LP_portfoliomutex);
profitmargin = 0.01 + (double)(rand() % 100)/100000; LP_sessionid = (uint32_t)time(NULL);
printf("default profit margin %f\n",profitmargin); printf("getting myipaddr sessionid.%u\n",LP_sessionid);
}
if ( system("curl -s4 checkip.amazonaws.com > /tmp/myipaddr") == 0 ) if ( system("curl -s4 checkip.amazonaws.com > /tmp/myipaddr") == 0 )
{ {
if ( (myipaddr= OS_filestr(&filesize,"/tmp/myipaddr")) != 0 && myipaddr[0] != 0 ) if ( (myipaddr= OS_filestr(&filesize,"/tmp/myipaddr")) != 0 && myipaddr[0] != 0 )
@ -548,12 +635,16 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profit
printf(">>>>>>>>> myipaddr.%s (%s) pullsock.%d\n",myipaddr,subaddr,pubsock); printf(">>>>>>>>> myipaddr.%s (%s) pullsock.%d\n",myipaddr,subaddr,pubsock);
LP_mypubsock = pubsock; LP_mypubsock = pubsock;
} }
LP_initpeers(pubsock,mypeer,myipaddr,myport,jstr(argjson,"seednode"),profitmargin); printf("got %s, initpeers\n",myipaddr);
pullsock = LP_initpublicaddr(ctx,&mypullport,pushaddr,myipaddr,mypullport,0); LP_initpeers(pubsock,mypeer,myipaddr,myport,jstr(argjson,"seednode"));
printf("get public socket\n");
LP_mypullsock = LP_initpublicaddr(ctx,&mypullport,pushaddr,myipaddr,mypullport,0);
strcpy(LP_publicaddr,pushaddr); strcpy(LP_publicaddr,pushaddr);
LP_publicport = mypullport; LP_publicport = mypullport;
LP_deadman_switch = (uint32_t)time(NULL); LP_mybussock = LP_coinbus(mybusport);
printf("canbind.%d my command address is (%s) pullsock.%d pullport.%u\n",LP_canbind,pushaddr,pullsock,mypullport); //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"),passphrase);
if ( IAMLP != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_psockloop,(void *)&myipaddr) != 0 ) if ( IAMLP != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_psockloop,(void *)&myipaddr) != 0 )
{ {
@ -565,28 +656,28 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profit
printf("error launching stats rpcloop for port.%u\n",myport); printf("error launching stats rpcloop for port.%u\n",myport);
exit(-1); exit(-1);
} }
if ( (retstr= basilisk_swapentry(0,0)) != 0 ) if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)command_rpcloop,(void *)&myipaddr) != 0 )
free(retstr); {
printf("error launching stats rpcloop for port.%u\n",myport);
exit(-1);
}
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)queue_loop,(void *)&myipaddr) != 0 )
{
printf("error launching stats rpcloop for port.%u\n",myport);
exit(-1);
}
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)prices_loop,(void *)&myipaddr) != 0 )
{
printf("error launching stats rpcloop for port.%u\n",myport);
exit(-1);
}
//if ( (retstr= basilisk_swapentry(0,0)) != 0 )
// free(retstr);
while ( 1 ) while ( 1 )
{ {
//fprintf(stderr,"."); //fprintf(stderr,".");
if ( LP_mainloop_iter(ctx,myipaddr,mypeer,pubsock,pushaddr,mypullport,pullsock,myport,passphrase,profitmargin) == 0 ) if ( LP_mainloop_iter(ctx,myipaddr,mypeer,pubsock,pushaddr,myport,passphrase) == 0 )
usleep(1000000 / MAINLOOP_PERSEC); usleep(1000000 / MAINLOOP_PERSEC);
if ( LP_canbind == 0 )
{
//printf("check deadman %u vs %u\n",LP_deadman_switch,(uint32_t)time(NULL));
if ( LP_deadman_switch < time(NULL)-PSOCK_KEEPALIVE )
{
printf("DEAD man's switch %u activated at %u lag.%d, register forwarding again\n",LP_deadman_switch,(uint32_t)time(NULL),(uint32_t)(time(NULL) - LP_deadman_switch));
if ( pullsock >= 0 )
nn_close(pullsock);
pullsock = LP_initpublicaddr(ctx,&mypullport,pushaddr,myipaddr,mypullport,0);
LP_deadman_switch = (uint32_t)time(NULL);
strcpy(LP_publicaddr,pushaddr);
LP_publicport = mypullport;
LP_forwarding_register(LP_mypubkey,pushaddr,mypullport,MAX_PSOCK_PORT);
}
}
} }
} }

410
iguana/exchanges/LP_network.c

@ -30,13 +30,13 @@ uint16_t Numpsocks,Psockport = MIN_PSOCK_PORT;
char *nanomsg_transportname(int32_t bindflag,char *str,char *ipaddr,uint16_t port) char *nanomsg_transportname(int32_t bindflag,char *str,char *ipaddr,uint16_t port)
{ {
sprintf(str,"tcp://%s:%u",bindflag == 0 ? ipaddr : "*",port); sprintf(str,"tcp://%s:%u",bindflag == 0 ? ipaddr : "*",port); // ws is worse
return(str); return(str);
} }
int32_t LP_send(int32_t sock,void *msg,int32_t sendlen,int32_t freeflag) int32_t _LP_send(int32_t sock,void *msg,int32_t sendlen,int32_t freeflag)
{ {
int32_t sentbytes,i; struct nn_pollfd pfd; int32_t sentbytes;
if ( sock < 0 ) if ( sock < 0 )
{ {
printf("LP_send.(%s) to illegal socket\n",(char *)msg); printf("LP_send.(%s) to illegal socket\n",(char *)msg);
@ -44,31 +44,293 @@ int32_t LP_send(int32_t sock,void *msg,int32_t sendlen,int32_t freeflag)
free(msg); free(msg);
return(-1); return(-1);
} }
//len = (int32_t)strlen(msg) + 1; if ( (sentbytes= nn_send(sock,msg,sendlen,0)) != sendlen )
for (i=0; i<1000; i++) // 1000 * (1 ms + 1000 us) = 2 seconds printf("LP_send sent %d instead of %d\n",sentbytes,sendlen);
//else printf("SENT.(%s)\n",msg);
if ( freeflag != 0 )
free(msg);
return(sentbytes);
}
int32_t LP_sockcheck(int32_t sock)
{
struct nn_pollfd pfd;
pfd.fd = sock;
pfd.events = NN_POLLOUT;
if ( nn_poll(&pfd,1,1) > 0 )
return(1);
else return(-1);
}
struct LP_queue
{
struct LP_queue *next,*prev;
int32_t sock,peerind,msglen;
uint32_t starttime,crc32;
uint8_t msg[];
} *LP_Q;
int32_t LP_Qenqueued,LP_Qerrors,LP_Qfound;
void _LP_sendqueueadd(uint32_t crc32,int32_t sock,uint8_t *msg,int32_t msglen,int32_t peerind)
{
struct LP_queue *ptr;
ptr = calloc(1,sizeof(*ptr) + msglen);
ptr->crc32 = crc32;
ptr->sock = sock;
ptr->peerind = peerind;
ptr->msglen = msglen;
memcpy(ptr->msg,msg,msglen);
DL_APPEND(LP_Q,ptr);
LP_Qenqueued++;
//printf("Q.%p: peerind.%d msglen.%d\n",ptr,peerind,msglen);
}
int32_t LP_crc32find(int32_t *duplicatep,int32_t ind,uint32_t crc32)
{
static uint32_t crcs[8192]; static unsigned long dup,total;
int32_t i;
*duplicatep = 0;
if ( ind < 0 )
{ {
pfd.fd = sock; total++;
pfd.events = NN_POLLOUT; for (i=0; i<sizeof(crcs)/sizeof(*crcs); i++)
//portable_mutex_lock(&LP_networkmutex);
if ( nn_poll(&pfd,1,1) > 0 )
{ {
if ( (sentbytes= nn_send(sock,msg,sendlen,0)) != sendlen ) if ( crc32 == crcs[i] )
printf("LP_send sent %d instead of %d\n",sentbytes,sendlen); {
//else printf("SENT.(%s)\n",msg); if ( i > 0 )
if ( freeflag != 0 ) {
free(msg); crcs[i] = crcs[i >> 1];
//portable_mutex_unlock(&LP_networkmutex); crcs[i >> 1] = crc32;
return(sentbytes); dup++;
//printf("duplicate %u in slot %d -> slot %d (%lu / %lu)\n",crc32,i,i>>1,dup,total);
}
*duplicatep = 1;
break;
}
else if ( crcs[i] == 0 )
break;
}
if ( i >= sizeof(crcs)/sizeof(*crcs) )
i = (rand() % (sizeof(crcs)/sizeof(*crcs)));
return(i);
}
else
{
crcs[ind] = crc32;
return(ind);
}
}
int32_t LP_peerindsock(int32_t *peerindp)
{
struct LP_peerinfo *peer,*tmp; int32_t peerind = 0;
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
peerind++;
if ( peer->errors < LP_MAXPEER_ERRORS && peer->pushsock >= 0 )
{
if ( peerind < *peerindp )
continue;
*peerindp = peerind;
//printf("peerind.%d -> sock %d\n",peerind,peer->pushsock);
return(peer->pushsock);
} }
//portable_mutex_unlock(&LP_networkmutex);
usleep(1000);
} }
printf("error LP_send sock.%d, i.%d timeout.(%s) %s\n",sock,i,(char *)msg,nn_strerror(nn_errno()));
if ( freeflag != 0 )
free(msg);
return(-1); return(-1);
} }
void queue_loop(void *ignore)
{
struct LP_queue *ptr,*tmp; int32_t sentbytes,nonz,flag,duplicate,n=0;
while ( 1 )
{
nonz = 0;
//printf("LP_Q.%p next.%p prev.%p\n",LP_Q,LP_Q!=0?LP_Q->next:0,LP_Q!=0?LP_Q->prev:0);
n = 0;
DL_FOREACH_SAFE(LP_Q,ptr,tmp)
{
n++;
flag = 0;
if ( ptr->sock >= 0 )
{
if ( LP_sockcheck(ptr->sock) > 0 )
{
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);
ptr->sock = -1;
if ( ptr->peerind > 0 )
ptr->starttime = (uint32_t)time(NULL);
else flag = 1;
}
}
else if ( time(NULL) > ptr->starttime+13 )
{
LP_crc32find(&duplicate,-1,ptr->crc32);
if ( duplicate > 0 )
{
LP_Qfound++;
if ( (LP_Qfound % 10) == 0 )
printf("found.%u Q.%d err.%d match.%d\n",ptr->crc32,LP_Qenqueued,LP_Qerrors,LP_Qfound);
flag = 1;
}
else
{
printf("couldnt find.%u peerind.%d Q.%d err.%d match.%d\n",ptr->crc32,ptr->peerind,LP_Qenqueued,LP_Qerrors,LP_Qfound);
ptr->peerind++;
if ( (ptr->sock= LP_peerindsock(&ptr->peerind)) < 0 )
{
printf("%d no more peers to try at peerind.%d %p Q_LP.%p\n",n,ptr->peerind,ptr,LP_Q);
flag = 1;
LP_Qerrors++;
}
}
}
if ( flag != 0 )
{
nonz++;
portable_mutex_lock(&LP_networkmutex);
DL_DELETE(LP_Q,ptr);
portable_mutex_unlock(&LP_networkmutex);
free(ptr);
ptr = 0;
}
}
//if ( n != 0 )
// printf("LP_Q.[%d]\n",n);
if ( nonz == 0 )
usleep(500000);
}
}
void _LP_queuesend(uint32_t crc32,int32_t sock0,int32_t sock1,uint8_t *msg,int32_t msglen,int32_t needack)
{
int32_t sentbytes,peerind = 0;
if ( sock0 >= 0 || sock1 >= 0 )
{
if ( sock0 >= 0 && LP_sockcheck(sock0) > 0 )
{
if ( (sentbytes= nn_send(sock0,msg,msglen,0)) != msglen )
printf("_LP_queuesend0 sent %d instead of %d\n",sentbytes,msglen);
else
{
//printf("Q sent %u\n",crc32);
sock0 = -1;
}
}
if ( sock1 >= 0 && LP_sockcheck(sock1) > 0 )
{
if ( (sentbytes= nn_send(sock1,msg,msglen,0)) != msglen )
printf("_LP_queuesend1 sent %d instead of %d\n",sentbytes,msglen);
else sock1 = -1;
}
if ( sock0 < 0 && sock1 < 0 )
return;
}
else
{
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];
if ( pubsock >= 0 )
{
//socks[0] = socks[1] = -1;
//if ( rel != 0 && rel[0] != 0 && (coin= LP_coinfind(rel)) != 0 && coin->bussock >= 0 )
// socks[flag++] = coin->bussock;
//if ( base != 0 && base[0] != 0 && (coin= LP_coinfind(base)) != 0 && coin->bussock >= 0 )
// socks[flag++] = coin->bussock;
//if ( flag == 0 && pubsock >= 0 )
_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);
}
// first 2 bytes == (crc32 & 0xffff) if encrypted, then nonce is next crypto_box_NONCEBYTES
// GENESIS_PRIVKEY is always the sender
void LP_broadcast_finish(int32_t pubsock,char *base,char *rel,uint8_t *msg,cJSON *argjson,uint32_t crc32)
{
int32_t msglen;
msg = (void *)jprint(argjson,0);
msglen = (int32_t)strlen((char *)msg) + 1;
if ( crc32 == 0 )
crc32 = calc_crc32(0,&msg[2],msglen - 2);
if ( IAMLP == 0 )
{
free(msg);
jdelete(argjson,"method");
jaddstr(argjson,"method","broadcast");
msg = (void *)jprint(argjson,0);
msglen = (int32_t)strlen((char *)msg) + 1;
LP_queuesend(crc32,-1,base,rel,msg,msglen);
} else LP_queuesend(crc32,pubsock,base,rel,msg,msglen);
free(msg);
}
void LP_broadcast_message(int32_t pubsock,char *base,char *rel,bits256 destpub25519,char *msgstr)
{
uint8_t encoded[LP_ENCRYPTED_MAXSIZE],space[sizeof(encoded)],*msg,*nonce,*cipher; int32_t encrypted=0,msglen; uint32_t crc32=0; cJSON *argjson; char *methodstr,method[64],cipherstr[LP_ENCRYPTED_MAXSIZE*2+1];
msglen = (int32_t)strlen(msgstr) + 1;
msg = (void *)msgstr;
if ( bits256_nonz(destpub25519) != 0 )
{
nonce = &encoded[2];
OS_randombytes(nonce,crypto_box_NONCEBYTES);
cipher = &encoded[2 + crypto_box_NONCEBYTES];
msglen = _SuperNET_cipher(nonce,&encoded[2 + crypto_box_NONCEBYTES],msg,msglen,destpub25519,GENESIS_PRIVKEY,space);
msglen += crypto_box_NONCEBYTES;
crc32 = calc_crc32(0,&encoded[2],msglen);
encoded[0] = crc32 & 0xff;
encoded[1] = (crc32 >> 8) & 0xff;
msg = encoded;
msglen += 2;
encrypted = 1;
//printf("msgstr.(%s)\n",msgstr);
free(msgstr), msgstr = 0;
}
if ( encrypted == 0 )
{
if ( (argjson= cJSON_Parse(msgstr)) != 0 )
{
if ( (methodstr= jstr(argjson,"method")) != 0 && strlen(methodstr) <= sizeof(method) )
{
strcpy(method,methodstr);
jdelete(argjson,"method");
if ( jobj(argjson,"method2") != 0 )
jdelete(argjson,"method2");
jaddstr(argjson,"method2",method);
jaddstr(argjson,"method",method);
//printf("CRC32.%u (%s)\n",crc32,(char *)msg);
LP_broadcast_finish(pubsock,base,rel,msg,argjson,0);
} // else printf("no valid method in (%s)\n",msgstr);
free_json(argjson);
} else printf("couldnt parse (%s)\n",msgstr);
}
else
{
argjson = cJSON_CreateObject();
init_hexbytes_noT(cipherstr,msg,msglen);
jaddstr(argjson,"cipher",cipherstr);
jaddstr(argjson,"method2","encrypted");
jaddstr(argjson,"method","encrypted");
LP_broadcast_finish(pubsock,base,rel,msg,argjson,crc32);
free_json(argjson);
}
if ( msgstr != 0 )
free(msgstr);
}
uint32_t LP_swapsend(int32_t pairsock,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t datalen,uint32_t nextbits,uint32_t crcs[2]) uint32_t LP_swapsend(int32_t pairsock,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t datalen,uint32_t nextbits,uint32_t crcs[2])
{ {
uint8_t *buf; int32_t sentbytes,offset=0,i; uint8_t *buf; int32_t sentbytes,offset=0,i;
@ -94,10 +356,10 @@ uint32_t LP_swapsend(int32_t pairsock,struct basilisk_swap *swap,uint32_t msgbit
return(nextbits); return(nextbits);
} }
void LP_psockloop(void *_ptr) void LP_psockloop(void *_ptr) // printouts seem to be needed for forwarding to work
{ {
static struct nn_pollfd *pfds; static struct nn_pollfd *pfds;
int32_t i,n,nonz,iter,retval,size=0,sentbytes,sendsock = -1; uint32_t now; struct psock *ptr=0; void *buf=0; char keepalive[512];//,*myipaddr = _ptr; int32_t i,n,nonz,iter,retval,sentbytes,size=0,sendsock = -1; uint32_t now; struct psock *ptr=0; void *buf=0; char keepalive[512];
while ( 1 ) while ( 1 )
{ {
now = (uint32_t)time(NULL); now = (uint32_t)time(NULL);
@ -105,15 +367,8 @@ void LP_psockloop(void *_ptr)
{ {
if ( size > 0 ) if ( size > 0 )
{ {
if ( (sentbytes= LP_send(sendsock,buf,size,0)) > 0 ) if ( (sentbytes= nn_send(sendsock,buf,size,0)) != size ) // need tight loop
{ printf("LP_psockloop sent %d instead of %d\n",sentbytes,size);
//printf("PSOCKS (%d %d %d) (%s) -> %d/%d bytes %s\n",ptr->publicsock,ptr->sendsock,sendsock,(char *)buf,size,sentbytes,ptr->sendaddr);
}
else
{
ptr->errors++;
printf("send error.%d to %s\n",ptr->errors,ptr->sendaddr);
}
if ( buf != 0 ) if ( buf != 0 )
{ {
if ( buf != keepalive ) if ( buf != keepalive )
@ -150,7 +405,7 @@ void LP_psockloop(void *_ptr)
} }
else if ( (pfds[n].revents & POLLIN) != 0 ) else if ( (pfds[n].revents & POLLIN) != 0 )
{ {
//printf("publicsock.%d %s has pollin\n",ptr->publicsock,ptr->publicaddr); printf("publicsock.%d %s has pollin\n",ptr->publicsock,ptr->publicaddr);
if ( (size= nn_recv(ptr->publicsock,&buf,NN_MSG,0)) > 0 ) if ( (size= nn_recv(ptr->publicsock,&buf,NN_MSG,0)) > 0 )
{ {
ptr->lasttime = now; ptr->lasttime = now;
@ -201,7 +456,7 @@ void LP_psockloop(void *_ptr)
if ( retval != 0 ) if ( retval != 0 )
printf("nn_poll retval.%d\n",retval); printf("nn_poll retval.%d\n",retval);
break; break;
} // else printf("num pfds.%d retval.%d\n",n,retval); } else printf("num pfds.%d retval.%d\n",n,retval);
} }
} }
//free(pfds); //free(pfds);
@ -232,11 +487,14 @@ void LP_psockloop(void *_ptr)
else if ( now > ptr->lastping+PSOCK_KEEPALIVE/2 && ptr->errors < 3 ) else if ( now > ptr->lastping+PSOCK_KEEPALIVE/2 && ptr->errors < 3 )
{ {
ptr->lastping = now; ptr->lastping = now;
sendsock = ptr->sendsock; if ( 0 )
sprintf(keepalive,"{\"method\":\"keepalive\",\"endpoint\":\"%s\"}",ptr->sendaddr); {
size = (int32_t)strlen(keepalive) + 1; sendsock = ptr->sendsock;
buf = keepalive; sprintf(keepalive,"{\"method\":\"keepalive\",\"endpoint\":\"%s\"}",ptr->sendaddr);
printf("send keepalive.(%s)\n",keepalive); size = (int32_t)strlen(keepalive) + 1;
buf = keepalive;
printf("send keepalive.(%s)\n",keepalive);
}
break; break;
} }
} }
@ -287,7 +545,7 @@ int32_t LP_psockmark(char *publicaddr)
char *LP_psock(char *myipaddr,int32_t ispaired) char *LP_psock(char *myipaddr,int32_t ispaired)
{ {
char pushaddr[128],subaddr[128]; uint16_t i,publicport,subport,maxiters=100; int32_t timeout,maxsize,pullsock=-1,pubsock=-1; cJSON *retjson=0; char pushaddr[128],subaddr[128]; uint16_t i,publicport,subport,maxiters=100; int32_t timeout,pullsock=-1,pubsock=-1; cJSON *retjson=0;
retjson = cJSON_CreateObject(); retjson = cJSON_CreateObject();
publicport = Psockport++; publicport = Psockport++;
subport = Psockport++; subport = Psockport++;
@ -306,12 +564,11 @@ char *LP_psock(char *myipaddr,int32_t ispaired)
{ {
timeout = 1; timeout = 1;
nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
timeout = 1;
nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout));
if ( ispaired != 0 ) if ( ispaired != 0 )
{ {
maxsize = 1024 * 1024; //maxsize = 1024 * 1024;
nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVBUF,&maxsize,sizeof(maxsize)); //nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVBUF,&maxsize,sizeof(maxsize));
} }
//if ( ispaired != 0 ) //if ( ispaired != 0 )
{ {
@ -354,36 +611,42 @@ char *LP_psock(char *myipaddr,int32_t ispaired)
both are combined in LP_psock_get both are combined in LP_psock_get
*/ */
char *issue_LP_psock(char *destip,uint16_t destport,int32_t ispaired)
{
char url[512],*retstr;
sprintf(url,"http://%s:%u/api/stats/psock?ispaired=%d",destip,destport,ispaired);
//return(LP_issue_curl("psock",destip,destport,url));
retstr = issue_curlt(url,LP_HTTP_TIMEOUT*3);
printf("issue_LP_psock got (%s) from %s\n",retstr,destip);
return(retstr);
}
int32_t nn_tests(void *ctx,int32_t pullsock,char *pushaddr,int32_t nnother) uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired)
{ {
int32_t sock,n,m,timeout,retval = -1; char msg[512],*retstr; uint16_t publicport = 0; char *retstr,*addr; cJSON *retjson; struct LP_peerinfo *peer,*tmp;
printf("nn_tests.(%s)\n",pushaddr); HASH_ITER(hh,LP_peerinfos,peer,tmp)
if ( (sock= nn_socket(AF_SP,nnother)) >= 0 )
{ {
if ( nn_connect(sock,pushaddr) < 0 ) connectaddr[0] = publicaddr[0] = 0;
printf("connect error %s\n",nn_strerror(nn_errno())); if ( peer->errors < LP_MAXPEER_ERRORS && (retstr= issue_LP_psock(peer->ipaddr,peer->port,ispaired)) != 0 )
else
{ {
sleep(3); if ( (retjson= cJSON_Parse(retstr)) != 0 )
timeout = 1;
nn_setsockopt(sock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
sprintf(msg,"{\"method\":\"nn_tests\",\"ipaddr\":\"%s\"}",pushaddr);
n = LP_send(sock,msg,(int32_t)strlen(msg)+1,0);
sleep(3);
LP_pullsock_check(ctx,&retstr,"127.0.0.1",-1,pullsock,0.);
sprintf(msg,"{\"method\":\"nn_tests2\",\"ipaddr\":\"%s\"}",pushaddr);
m = LP_send(pullsock,msg,(int32_t)strlen(msg)+1,0);
printf(">>>>>>>>>>>>>>>>>>>>>> sent %d+%d bytes -> pullsock.%d retstr.(%s)\n",n,m,pullsock,retstr!=0?retstr:"");
if ( retstr != 0 )
{ {
free(retstr); printf("from %s:%u (%s)\n",peer->ipaddr,peer->port,retstr);
retval = 0; if ( (addr= jstr(retjson,"publicaddr")) != 0 )
safecopy(publicaddr,addr,128);
if ( (addr= jstr(retjson,"connectaddr")) != 0 )
safecopy(connectaddr,addr,128);
if ( publicaddr[0] != 0 && connectaddr[0] != 0 )
publicport = juint(retjson,"publicport");
free_json(retjson);
} }
} printf("got.(%s) connect.%s public.%s\n",retstr,connectaddr,publicaddr);
nn_close(sock); free(retstr);
} else printf("error psock from %s:%u\n",peer->ipaddr,peer->port);
if ( publicport != 0 )
break;
} }
return(retval); return(publicport);
} }
int32_t LP_initpublicaddr(void *ctx,uint16_t *mypullportp,char *publicaddr,char *myipaddr,uint16_t mypullport,int32_t ispaired) int32_t LP_initpublicaddr(void *ctx,uint16_t *mypullportp,char *publicaddr,char *myipaddr,uint16_t mypullport,int32_t ispaired)
@ -404,6 +667,11 @@ int32_t LP_initpublicaddr(void *ctx,uint16_t *mypullportp,char *publicaddr,char
else else
{ {
*mypullportp = 0; *mypullportp = 0;
if ( ispaired == 0 )
{
strcpy(publicaddr,"127.0.0.1");
return(-1);
}
while ( *mypullportp == 0 ) while ( *mypullportp == 0 )
{ {
if ( (*mypullportp= LP_psock_get(connectaddr,publicaddr,ispaired)) != 0 ) if ( (*mypullportp= LP_psock_get(connectaddr,publicaddr,ispaired)) != 0 )
@ -434,17 +702,17 @@ int32_t LP_initpublicaddr(void *ctx,uint16_t *mypullportp,char *publicaddr,char
} }
timeout = 1; timeout = 1;
nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout));
timeout = 1;
nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
//maxsize = 2 * 1024 * 1024; //maxsize = 2 * 1024 * 1024;
//nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVBUF,&maxsize,sizeof(maxsize)); //nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVBUF,&maxsize,sizeof(maxsize));
if ( nntype == NN_SUB ) if ( nntype == NN_SUB )
nn_setsockopt(pullsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); nn_setsockopt(pullsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0);
} }
if ( LP_canbind != 0 || ispaired != 0 || nn_tests(ctx,pullsock,publicaddr,NN_PUSH) >= 0 ) //if ( LP_canbind != 0 || ispaired != 0 || nn_tests(ctx,pullsock,publicaddr,NN_PUSH) >= 0 )
break; // break;
printf("nn_tests failed, try again\n"); //printf("nn_tests failed, try again\n");
sleep(3); //sleep(3);
break;
if ( pullsock >= 0 ) if ( pullsock >= 0 )
nn_close(pullsock); nn_close(pullsock);
} }

357
iguana/exchanges/LP_ordermatch.c

@ -19,6 +19,43 @@
// marketmaker // marketmaker
// //
uint64_t LP_txfeecalc(char *symbol,uint64_t txfee)
{
struct iguana_info *coin;
if ( strcmp(symbol,"BTC") == 0 )
{
if ( txfee == 0 && (txfee= LP_getestimatedrate(symbol) * LP_AVETXSIZE) < LP_MIN_TXFEE )
txfee = LP_MIN_TXFEE;
}
else if ( (coin= LP_coinfind(symbol)) != 0 )
txfee = coin->txfee;
if ( txfee < LP_MIN_TXFEE )
txfee = LP_MIN_TXFEE;
return(txfee);
}
void LP_txfees(uint64_t *txfeep,uint64_t *desttxfeep,char *base,char *rel)
{
*txfeep = LP_txfeecalc(base,0);
*desttxfeep = LP_txfeecalc(rel,0);
}
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)
{
uint64_t destsatoshis,satoshis;
a_value -= (desttxfee + 1);
destsatoshis = ((b_satoshis - txfee) * price);
if ( destsatoshis > a_value )
destsatoshis = a_value;
if ( maxdestsatoshis != 0 && destsatoshis > maxdestsatoshis-desttxfee-1 )
destsatoshis = maxdestsatoshis-desttxfee-1;
satoshis = (destsatoshis / price + 0.49) - txfee;
*destsatoshisp = destsatoshis;
*satoshisp = satoshis;
if ( satoshis > 0 )
return((double)destsatoshis / satoshis);
else return(0.);
}
struct basilisk_request *LP_requestinit(struct basilisk_request *rp,bits256 srchash,bits256 desthash,char *src,uint64_t srcsatoshis,char *dest,uint64_t destsatoshis,uint32_t timestamp,uint32_t quotetime,int32_t DEXselector) struct basilisk_request *LP_requestinit(struct basilisk_request *rp,bits256 srchash,bits256 desthash,char *src,uint64_t srcsatoshis,char *dest,uint64_t destsatoshis,uint32_t timestamp,uint32_t quotetime,int32_t DEXselector)
{ {
@ -120,15 +157,15 @@ int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson)
return(0); return(0);
} }
int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char *destcoin,double price,uint64_t destsatoshis) int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char *destcoin,double price,uint64_t satoshis,uint64_t destsatoshis)
{ {
memset(qp,0,sizeof(*qp)); memset(qp,0,sizeof(*qp));
if ( qp->timestamp == 0 ) if ( qp->timestamp == 0 )
qp->timestamp = (uint32_t)time(NULL); qp->timestamp = (uint32_t)time(NULL);
safecopy(qp->destcoin,destcoin,sizeof(qp->destcoin)); safecopy(qp->destcoin,destcoin,sizeof(qp->destcoin));
if ( (qp->txfee= LP_getestimatedrate(utxo->coin)*LP_AVETXSIZE) < LP_MIN_TXFEE ) LP_txfees(&qp->txfee,&qp->desttxfee,utxo->coin,qp->destcoin);
qp->txfee = LP_MIN_TXFEE; qp->satoshis = satoshis;//(destsatoshis / price) + 0.49;
qp->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 ( utxo->iambob == 0 || qp->txfee >= qp->satoshis || qp->txfee >= utxo->deposit.value || utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis) )
{ {
printf("quoteinit error.(%d %d %d %d) %.8f vs %.8f\n",utxo->iambob == 0,qp->txfee >= qp->satoshis,qp->txfee >= utxo->deposit.value,utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis),dstr(utxo->deposit.value),dstr(LP_DEPOSITSATOSHIS(qp->satoshis))); 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)));
@ -138,9 +175,6 @@ int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char *
qp->vout = utxo->payment.vout; qp->vout = utxo->payment.vout;
qp->txid2 = utxo->deposit.txid; qp->txid2 = utxo->deposit.txid;
qp->vout2 = utxo->deposit.vout; qp->vout2 = utxo->deposit.vout;
qp->destsatoshis = destsatoshis;
if ( (qp->desttxfee= LP_getestimatedrate(qp->destcoin) * LP_AVETXSIZE) < LP_MIN_TXFEE )
qp->desttxfee = LP_MIN_TXFEE;
if ( qp->desttxfee >= qp->destsatoshis ) if ( qp->desttxfee >= qp->destsatoshis )
{ {
printf("quoteinit desttxfee %.8f < %.8f destsatoshis\n",dstr(qp->desttxfee),dstr(qp->destsatoshis)); printf("quoteinit desttxfee %.8f < %.8f destsatoshis\n",dstr(qp->desttxfee),dstr(qp->destsatoshis));
@ -167,7 +201,7 @@ char *LP_quotereceived(cJSON *argjson)
{ {
struct LP_cacheinfo *ptr; double price; struct LP_quoteinfo Q; struct LP_cacheinfo *ptr; double price; struct LP_quoteinfo Q;
LP_quoteparse(&Q,argjson); LP_quoteparse(&Q,argjson);
price = (double)(Q.destsatoshis + Q.desttxfee) / (Q.satoshis + Q.txfee); price = (double)Q.destsatoshis / Q.satoshis;
if ( (ptr= LP_cacheadd(Q.srccoin,Q.destcoin,Q.txid,Q.vout,price,&Q)) != 0 ) if ( (ptr= LP_cacheadd(Q.srccoin,Q.destcoin,Q.txid,Q.vout,price,&Q)) != 0 )
{ {
ptr->Q = Q; ptr->Q = Q;
@ -176,27 +210,17 @@ char *LP_quotereceived(cJSON *argjson)
} else return(clonestr("{\"error\":\"nullptr\"}")); } else return(clonestr("{\"error\":\"nullptr\"}"));
} }
char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,char *base,char *rel,double price) char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *rel,double price)
{ {
bits256 zero; char *msg; cJSON *reqjson = cJSON_CreateObject(); bits256 zero; char *msg; cJSON *reqjson = cJSON_CreateObject();
jaddbits256(reqjson,"pubkey",LP_mypubkey); memset(zero.bytes,0,sizeof(zero));
jaddbits256(reqjson,"pubkey",LP_mypub25519);
jaddstr(reqjson,"base",base); jaddstr(reqjson,"base",base);
jaddstr(reqjson,"rel",rel); jaddstr(reqjson,"rel",rel);
jaddnum(reqjson,"price",price); jaddnum(reqjson,"price",price);
if ( pubsock >= 0 ) jaddstr(reqjson,"method","postprice");
{ msg = jprint(reqjson,1);
jaddstr(reqjson,"method","postprice"); LP_broadcast_message(pubsock,base,rel,zero,msg);
//printf("%d pricepings.(%s)\n",pubsock,jprint(reqjson,0));
msg = jprint(reqjson,1);
LP_send(pubsock,msg,(int32_t)strlen(msg)+1,1);
}
else
{
jaddstr(reqjson,"method","forward");
jaddstr(reqjson,"method2","postprice");
memset(zero.bytes,0,sizeof(zero));
LP_forward(ctx,myipaddr,pubsock,profitmargin,zero,jprint(reqjson,1),1);
}
return(clonestr("{\"result\":\"success\"}")); return(clonestr("{\"result\":\"success\"}"));
} }
@ -234,14 +258,14 @@ int32_t LP_quote_checkmempool(struct LP_quoteinfo *qp)
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 **autxop,struct LP_utxoinfo **butxop,struct LP_quoteinfo *qp,int32_t iambob)
{ {
double qprice; uint64_t srcvalue,srcvalue2,destvalue,destvalue2; double qprice; uint64_t txfee,desttxfee,srcvalue,srcvalue2,destvalue,destvalue2;
*autxop = *butxop = 0; *autxop = *butxop = 0;
if ( LP_iseligible(&srcvalue,&srcvalue2,1,qp->srccoin,qp->txid,qp->vout,qp->satoshis,qp->txid2,qp->vout2,qp->srchash) == 0 ) if ( LP_iseligible(&srcvalue,&srcvalue2,1,qp->srccoin,qp->txid,qp->vout,qp->satoshis,qp->txid2,qp->vout2) == 0 )
{ {
printf("bob not eligible\n"); printf("bob not eligible\n");
return(-2); return(-2);
} }
if ( LP_iseligible(&destvalue,&destvalue2,0,qp->destcoin,qp->desttxid,qp->destvout,qp->destsatoshis,qp->feetxid,qp->feevout,qp->desthash) == 0 ) if ( 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); 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); return(-3);
@ -269,17 +293,20 @@ double LP_quote_validate(struct LP_utxoinfo **autxop,struct LP_utxoinfo **butxop
return(-11); return(-11);
} }
qprice = ((double)qp->destsatoshis / qp->satoshis); qprice = ((double)qp->destsatoshis / qp->satoshis);
if ( qp->satoshis < (srcvalue / LP_MINVOL) ) if ( qp->satoshis < (srcvalue / LP_MINVOL) || srcvalue < qp->txfee*LP_MINSIZE_TXFEEMULT )
{ {
printf("utxo payment %.8f is less than half covered by Q %.8f\n",dstr(srcvalue),dstr(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); return(-12);
} }
if ( qp->destsatoshis < (destvalue / LP_MINCLIENTVOL) ) if ( qp->destsatoshis < (destvalue / LP_MINCLIENTVOL) || destvalue < qp->desttxfee*LP_MINSIZE_TXFEEMULT )
{ {
printf("destsatoshis %.8f is less than half of value %.8f\n",dstr(qp->destsatoshis),dstr(destvalue)); 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(-13);
} }
printf("qprice %.8f <- %.8f/%.8f txfees.(%.8f %.8f)\n",qprice,dstr(qp->destsatoshis),dstr(qp->satoshis),dstr(qp->txfee),dstr(qp->desttxfee)); LP_txfees(&txfee,&desttxfee,qp->srccoin,qp->destcoin);
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);
return(qprice); return(qprice);
} }
@ -295,7 +322,7 @@ int32_t LP_arrayfind(cJSON *array,bits256 txid,int32_t vout)
return(-1); return(-1);
} }
double LP_query(void *ctx,char *myipaddr,int32_t mypubsock,double profitmargin,char *method,struct LP_quoteinfo *qp) 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; char *msg; int32_t i,flag = 0; double price = 0.; struct LP_utxoinfo *utxo;
if ( strcmp(method,"request") == 0 ) if ( strcmp(method,"request") == 0 )
@ -311,27 +338,18 @@ double LP_query(void *ctx,char *myipaddr,int32_t mypubsock,double profitmargin,c
reqjson = LP_quotejson(qp); reqjson = LP_quotejson(qp);
if ( bits256_nonz(qp->desthash) != 0 ) if ( bits256_nonz(qp->desthash) != 0 )
flag = 1; flag = 1;
//printf("QUERY.(%s)\n",jprint(reqjson,0)); jaddbits256(reqjson,"pubkey",qp->srchash);
if ( IAMLP != 0 ) jaddstr(reqjson,"method",method);
{ msg = jprint(reqjson,1);
jaddstr(reqjson,"method",method); printf("QUERY.(%s)\n",msg);
msg = jprint(reqjson,1); LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,qp->srchash,msg);
LP_send(LP_mypubsock,msg,(int32_t)strlen(msg)+1,1);
}
else
{
jaddstr(reqjson,"method2",method);
jaddstr(reqjson,"method","forward");
jaddbits256(reqjson,"pubkey",qp->srchash);
LP_forward(ctx,myipaddr,mypubsock,profitmargin,qp->srchash,jprint(reqjson,1),1);
}
for (i=0; i<30; i++) for (i=0; i<30; i++)
{ {
if ( (price= LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout)) > SMALLVAL ) if ( (price= LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout)) > SMALLVAL )
{ {
if ( flag == 0 || bits256_nonz(qp->desthash) != 0 ) if ( flag == 0 || bits256_nonz(qp->desthash) != 0 )
{ {
//printf("break out of loop.%d price %.8f\n",i,price); printf("break out of loop.%d price %.8f %s/%s\n",i,price,qp->srccoin,qp->destcoin);
break; break;
} }
} }
@ -342,7 +360,7 @@ double LP_query(void *ctx,char *myipaddr,int32_t mypubsock,double profitmargin,c
int32_t LP_nanobind(void *ctx,char *pairstr) int32_t LP_nanobind(void *ctx,char *pairstr)
{ {
int32_t i,timeout,r,pairsock = -1; uint16_t mypullport; char bindaddr[128]; int32_t i,r,pairsock = -1; uint16_t mypullport; char bindaddr[128];
if ( LP_canbind != 0 ) if ( LP_canbind != 0 )
{ {
if ( (pairsock= nn_socket(AF_SP,NN_PAIR)) < 0 ) if ( (pairsock= nn_socket(AF_SP,NN_PAIR)) < 0 )
@ -358,9 +376,9 @@ int32_t LP_nanobind(void *ctx,char *pairstr)
nanomsg_transportname(1,bindaddr,LP_myipaddr,r); nanomsg_transportname(1,bindaddr,LP_myipaddr,r);
if ( nn_bind(pairsock,bindaddr) >= 0 ) if ( nn_bind(pairsock,bindaddr) >= 0 )
{ {
timeout = 100; //timeout = 1;
nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); //nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); //nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout));
printf("nanobind %s to %d\n",pairstr,pairsock); printf("nanobind %s to %d\n",pairstr,pairsock);
return(pairsock); return(pairsock);
} else printf("error binding to %s for %s\n",bindaddr,pairstr); } else printf("error binding to %s for %s\n",bindaddr,pairstr);
@ -372,10 +390,10 @@ int32_t LP_nanobind(void *ctx,char *pairstr)
return(pairsock); return(pairsock);
} }
int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJSON *argjson,char *myipaddr,char *base,char *rel,double profitmargin,double price,struct LP_quoteinfo *qp) 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; char pairstr[512],*msg; cJSON *retjson; bits256 privkey; int32_t pair=-1,retval = -1,DEXselector = 0; struct basilisk_swap *swap; struct iguana_info *coin;
printf("LP_connectstartbob.(%s) with.(%s) %s\n",myipaddr,jprint(argjson,0),LP_myipaddr); printf("LP_connectstartbob.(%s) with.(%s) %s\n",LP_myipaddr,jprint(argjson,0),LP_myipaddr);
qp->quotetime = (uint32_t)time(NULL); qp->quotetime = (uint32_t)time(NULL);
if ( (coin= LP_coinfind(utxo->coin)) == 0 ) if ( (coin= LP_coinfind(utxo->coin)) == 0 )
{ {
@ -383,11 +401,11 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ
return(-1); return(-1);
} }
privkey = LP_privkey(utxo->coinaddr,coin->taddr); privkey = LP_privkey(utxo->coinaddr,coin->taddr);
if ( bits256_nonz(privkey) != 0 && qp->quotetime >= qp->timestamp-3 && qp->quotetime <= utxo->T.swappending && bits256_cmp(LP_mypubkey,qp->srchash) == 0 ) if ( bits256_nonz(privkey) != 0 && qp->quotetime >= qp->timestamp-3 && qp->quotetime <= utxo->T.swappending && bits256_cmp(LP_mypub25519,qp->srchash) == 0 )
{ {
if ( (pair= LP_nanobind(ctx,pairstr)) >= 0 ) if ( (pair= LP_nanobind(ctx,pairstr)) >= 0 )
{ {
LP_requestinit(&qp->R,qp->srchash,qp->desthash,base,qp->satoshis,rel,qp->destsatoshis,qp->timestamp,qp->quotetime,DEXselector); LP_requestinit(&qp->R,qp->srchash,qp->desthash,base,qp->satoshis-qp->txfee,rel,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector);
swap = LP_swapinit(1,0,privkey,&qp->R,qp); swap = LP_swapinit(1,0,privkey,&qp->R,qp);
swap->N.pair = pair; swap->N.pair = pair;
utxo->S.swap = swap; utxo->S.swap = swap;
@ -399,23 +417,16 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ
jaddstr(retjson,"pair",pairstr); jaddstr(retjson,"pair",pairstr);
jaddnum(retjson,"requestid",qp->R.requestid); jaddnum(retjson,"requestid",qp->R.requestid);
jaddnum(retjson,"quoteid",qp->R.quoteid); jaddnum(retjson,"quoteid",qp->R.quoteid);
char str[65]; printf("BOB pubsock.%d sends to (%s)\n",pubsock,bits256_str(str,utxo->S.otherpubkey)); char str[65]; printf("BOB pubsock.%d binds to %d (%s)\n",pubsock,pair,bits256_str(str,utxo->S.otherpubkey));
if ( pubsock >= 0 ) msg = jprint(retjson,1);
{ LP_broadcast_message(pubsock,base,rel,utxo->S.otherpubkey,msg);
msg = jprint(retjson,0);
LP_send(pubsock,msg,(int32_t)strlen(msg)+1,1);
}
jdelete(retjson,"method");
jaddstr(retjson,"method2","connected");
jaddstr(retjson,"method","forward");
LP_forward(ctx,myipaddr,pubsock,profitmargin,utxo->S.otherpubkey,jprint(retjson,1),1);
retval = 0; retval = 0;
} else printf("error launching swaploop\n"); } else printf("error launching swaploop\n");
} else printf("couldnt bind to any port %s\n",pairstr); } else printf("couldnt bind to any port %s\n",pairstr);
} }
else else
{ {
printf("dest %.8f vs required %.8f (%d %d %d %d %d)\n",dstr(qp->destsatoshis),dstr(price*(utxo->S.satoshis-qp->txfee)),bits256_nonz(privkey) != 0 ,qp->timestamp == utxo->T.swappending-LP_RESERVETIME,qp->quotetime >= qp->timestamp-3,qp->quotetime < utxo->T.swappending,bits256_cmp(LP_mypubkey,qp->srchash) == 0); 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);
} }
if ( retval < 0 ) if ( retval < 0 )
{ {
@ -428,33 +439,39 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ
char *LP_connectedalice(cJSON *argjson) // alice char *LP_connectedalice(cJSON *argjson) // alice
{ {
cJSON *retjson; double bid,ask,price,qprice; int32_t timeout,pairsock = -1; char *pairstr; int32_t DEXselector = 0; struct LP_utxoinfo *autxo,*butxo; struct LP_quoteinfo Q; struct basilisk_swap *swap; struct iguana_info *coin; 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;
if ( LP_quoteparse(&Q,argjson) < 0 ) if ( LP_quoteparse(&Q,argjson) < 0 )
clonestr("{\"error\":\"cant parse quote\"}"); clonestr("{\"error\":\"cant parse quote\"}");
if ( bits256_cmp(Q.desthash,LP_mypubkey) != 0 ) if ( bits256_cmp(Q.desthash,LP_mypub25519) != 0 )
return(clonestr("{\"result\",\"update stats\"}")); return(clonestr("{\"result\",\"update stats\"}"));
printf("CONNECTED.(%s)\n",jprint(argjson,0)); printf("CONNECTED.(%s)\n",jprint(argjson,0));
if ( (qprice= LP_quote_validate(&autxo,&butxo,&Q,0)) <= SMALLVAL ) if ( (qprice= LP_quote_validate(&autxo,&butxo,&Q,0)) <= SMALLVAL )
{ {
LP_availableset(autxo); LP_availableset(autxo);
LP_pendingswaps--;
printf("quote validate error %.0f\n",qprice); printf("quote validate error %.0f\n",qprice);
return(clonestr("{\"error\":\"quote validation error\"}")); return(clonestr("{\"error\":\"quote validation error\"}"));
} }
if ( (price= LP_myprice(&bid,&ask,Q.destcoin,Q.srccoin)) <= SMALLVAL || ask <= SMALLVAL ) if ( LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin) <= SMALLVAL || bid <= SMALLVAL )
{ {
printf("this node has no price for %s/%s (%.8f %.8f)\n",Q.destcoin,Q.srccoin,bid,ask); printf("this node has no price for %s/%s (%.8f %.8f)\n",Q.destcoin,Q.srccoin,bid,ask);
LP_availableset(autxo); LP_availableset(autxo);
LP_pendingswaps--;
return(clonestr("{\"error\":\"no price set\"}")); return(clonestr("{\"error\":\"no price set\"}"));
} }
price = 1. / ask; printf("%s/%s bid %.8f ask %.8f\n",Q.srccoin,Q.destcoin,bid,ask);
if ( qprice > price+0.00000001 ) //if ( (price= ask) == 0. )
price = bid;
/*if ( SATOSHIDEN*qprice > (SATOSHIDEN * price) * 1.001 + 10 )
{ {
printf("qprice %.8f too big vs %.8f\n",qprice,price); printf("qprice %.8f too big vs %.8f\n",qprice,price);
LP_availableset(autxo); LP_availableset(autxo);
LP_pendingswaps--;
return(clonestr("{\"error\":\"quote price too expensive\"}")); return(clonestr("{\"error\":\"quote price too expensive\"}"));
} }*/
if ( (coin= LP_coinfind(Q.destcoin)) == 0 ) if ( (coin= LP_coinfind(Q.destcoin)) == 0 )
{ {
LP_pendingswaps--;
return(clonestr("{\"error\":\"cant get alicecoin\"}")); return(clonestr("{\"error\":\"cant get alicecoin\"}"));
} }
Q.privkey = LP_privkey(Q.destaddr,coin->taddr); Q.privkey = LP_privkey(Q.destaddr,coin->taddr);
@ -465,10 +482,10 @@ char *LP_connectedalice(cJSON *argjson) // alice
jaddstr(retjson,"error","couldnt create pairsock"); jaddstr(retjson,"error","couldnt create pairsock");
else if ( nn_connect(pairsock,pairstr) >= 0 ) else if ( nn_connect(pairsock,pairstr) >= 0 )
{ {
timeout = 100; //timeout = 1;
nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); //nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); //nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout));
LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis,Q.destcoin,Q.destsatoshis,Q.timestamp,Q.quotetime,DEXselector); LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-Q.txfee,Q.destcoin,Q.destsatoshis-Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector);
swap = LP_swapinit(0,0,Q.privkey,&Q.R,&Q); swap = LP_swapinit(0,0,Q.privkey,&Q.R,&Q);
swap->N.pair = pairsock; swap->N.pair = pairsock;
autxo->S.swap = swap; autxo->S.swap = swap;
@ -485,6 +502,7 @@ char *LP_connectedalice(cJSON *argjson) // alice
printf("connected result.(%s)\n",jprint(retjson,0)); printf("connected result.(%s)\n",jprint(retjson,0));
if ( jobj(retjson,"error") != 0 ) if ( jobj(retjson,"error") != 0 )
LP_availableset(autxo); LP_availableset(autxo);
else LP_pendingswaps++;
return(jprint(retjson,1)); return(jprint(retjson,1));
} }
else else
@ -495,14 +513,14 @@ char *LP_connectedalice(cJSON *argjson) // alice
} }
} }
int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin) 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; cJSON *retjson; double qprice,price,bid,ask; struct LP_utxoinfo *autxo,*butxo; int32_t retval = -1; struct LP_quoteinfo Q;
if ( (method= jstr(argjson,"method")) != 0 && (strcmp(method,"request") == 0 ||strcmp(method,"connect") == 0) ) if ( (method= jstr(argjson,"method")) != 0 && (strcmp(method,"request") == 0 ||strcmp(method,"connect") == 0) )
{ {
//printf("TRADECOMMAND.(%s)\n",jprint(argjson,0)); printf("TRADECOMMAND.(%s)\n",jprint(argjson,0));
retval = 1; retval = 1;
if ( LP_quoteparse(&Q,argjson) == 0 && bits256_cmp(LP_mypubkey,Q.srchash) == 0 ) if ( LP_quoteparse(&Q,argjson) == 0 && bits256_cmp(LP_mypub25519,Q.srchash) == 0 )
{ {
if ( (price= LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin)) <= SMALLVAL || ask <= SMALLVAL ) if ( (price= LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin)) <= SMALLVAL || ask <= SMALLVAL )
{ {
@ -515,7 +533,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
printf("quote validate error %.0f\n",qprice); printf("quote validate error %.0f\n",qprice);
return(-4); return(-4);
} }
if ( qprice < price-0.00000001 ) if ( qprice < (price - 0.00000001) * 0.9999 )
{ {
printf("(%.8f %.8f) quote price %.8f too low vs %.8f for %s/%s\n",bid,ask,qprice,price,Q.srccoin,Q.destcoin); printf("(%.8f %.8f) quote price %.8f too low vs %.8f for %s/%s\n",bid,ask,qprice,price,Q.srccoin,Q.destcoin);
return(-5); return(-5);
@ -535,24 +553,17 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
jaddbits256(retjson,"desthash",butxo->S.otherpubkey); jaddbits256(retjson,"desthash",butxo->S.otherpubkey);
jaddbits256(retjson,"pubkey",butxo->S.otherpubkey); jaddbits256(retjson,"pubkey",butxo->S.otherpubkey);
jaddstr(retjson,"method","reserved"); jaddstr(retjson,"method","reserved");
if ( pubsock >= 0 ) msg = jprint(retjson,1);
{ printf("set swappending.%u accept qprice %.8f, min %.8f\n(%s)",butxo->T.swappending,qprice,price,msg);
msg = jprint(retjson,0); LP_broadcast_message(pubsock,Q.srccoin,Q.destcoin,butxo->S.otherpubkey,msg);
LP_send(pubsock,msg,(int32_t)strlen(msg)+1,1);
}
jdelete(retjson,"method");
jaddstr(retjson,"method2","reserved");
jaddstr(retjson,"method","forward");
LP_forward(ctx,myipaddr,pubsock,profitmargin,butxo->S.otherpubkey,jprint(retjson,1),1);
butxo->T.lasttime = (uint32_t)time(NULL); butxo->T.lasttime = (uint32_t)time(NULL);
printf("set swappending.%u accept qprice %.8f, min %.8f\n",butxo->T.swappending,qprice,price);
} else printf("warning swappending.%u swap.%p\n",butxo->T.swappending,butxo->S.swap); } else printf("warning swappending.%u swap.%p\n",butxo->T.swappending,butxo->S.swap);
} }
else if ( strcmp(method,"connect") == 0 ) // bob else if ( strcmp(method,"connect") == 0 ) // bob
{ {
retval = 4; retval = 4;
if ( butxo->T.swappending != 0 && butxo->S.swap == 0 ) if ( butxo->T.swappending != 0 && butxo->S.swap == 0 )
LP_connectstartbob(ctx,pubsock,butxo,argjson,myipaddr,Q.srccoin,Q.destcoin,profitmargin,qprice,&Q); LP_connectstartbob(ctx,pubsock,butxo,argjson,Q.srccoin,Q.destcoin,qprice,&Q);
else printf("pend.%u swap %p when connect came in (%s)\n",butxo->T.swappending,butxo->S.swap,jprint(argjson,0)); else printf("pend.%u swap %p when connect came in (%s)\n",butxo->T.swappending,butxo->S.swap,jprint(argjson,0));
} }
} }
@ -560,19 +571,16 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
return(retval); return(retval);
} }
struct LP_utxoinfo *LP_bestutxo(double *ordermatchpricep,int64_t *bestdestsatoshisp,struct LP_utxoinfo *autxo,char *base,double maxprice,int32_t duration,int64_t txfee,int64_t desttxfee) 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; bits256 txid,pubkey; char *obookstr; cJSON *orderbook,*asks,*item; struct LP_utxoinfo *butxo,*bestutxo = 0; int32_t i,vout,numasks; double bestmetric=0.,metric,vol,price,bestprice = 0.; struct LP_pubkeyinfo *pubp; 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.; *ordermatchpricep = 0.;
*bestdestsatoshisp = 0; *bestsatoshisp = *bestdestsatoshisp = 0;
if ( duration <= 0 ) if ( duration <= 0 )
duration = LP_ORDERBOOK_DURATION; duration = LP_ORDERBOOK_DURATION;
if ( maxprice <= 0. || LP_priceinfofind(base) == 0 ) if ( maxprice <= 0. || LP_priceinfofind(base) == 0 )
return(0); return(0);
if ( (desttxfee= LP_getestimatedrate(autxo->coin) * LP_AVETXSIZE) < LP_MIN_TXFEE ) LP_txfees(&txfee,&desttxfee,base,autxo->coin);
desttxfee = LP_MIN_TXFEE;
if ( (txfee= LP_getestimatedrate(base) * LP_AVETXSIZE) < LP_MIN_TXFEE )
txfee = LP_MIN_TXFEE;
if ( (obookstr= LP_orderbook(base,autxo->coin,duration)) != 0 ) if ( (obookstr= LP_orderbook(base,autxo->coin,duration)) != 0 )
{ {
if ( (orderbook= cJSON_Parse(obookstr)) != 0 ) if ( (orderbook= cJSON_Parse(obookstr)) != 0 )
@ -582,13 +590,14 @@ struct LP_utxoinfo *LP_bestutxo(double *ordermatchpricep,int64_t *bestdestsatosh
for (i=0; i<numasks; i++) for (i=0; i<numasks; i++)
{ {
item = jitem(asks,i); item = jitem(asks,i);
if ( (price= jdouble(item,"price")) > SMALLVAL && price <= maxprice ) price = jdouble(item,"price");
if ( LP_pricevalid(price) > 0 && price <= maxprice )
{ {
price *= 1.0001; //price *= 1.0001;
if ( price > maxprice ) //if ( price > maxprice )
price = maxprice; // price = maxprice;
pubkey = jbits256(item,"pubkey"); pubkey = jbits256(item,"pubkey");
if ( bits256_cmp(pubkey,LP_mypubkey) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 && pubp->numerrors < LP_MAXPUBKEY_ERRORS ) if ( bits256_cmp(pubkey,LP_mypub25519) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 && pubp->numerrors < LP_MAXPUBKEY_ERRORS )
{ {
if ( bestprice == 0. ) // assumes price ordered asks if ( bestprice == 0. ) // assumes price ordered asks
bestprice = price; bestprice = price;
@ -597,35 +606,82 @@ struct LP_utxoinfo *LP_bestutxo(double *ordermatchpricep,int64_t *bestdestsatosh
vout = jint(item,"vout"); vout = jint(item,"vout");
vol = jdouble(item,"volume"); vol = jdouble(item,"volume");
metric = price / bestprice; 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 ( (butxo= LP_utxofind(1,txid,vout)) != 0 && (long long)(vol*SATOSHIDEN) == butxo->S.satoshis && LP_isavailable(butxo) > 0 && LP_ismine(butxo) == 0 && butxo->T.bestflag == 0 )
{ {
destsatoshis = ((butxo->S.satoshis - txfee) * price); if ( LP_iseligible(&val,&val2,butxo->iambob,butxo->coin,butxo->payment.txid,butxo->payment.vout,butxo->S.satoshis,butxo->deposit.txid,butxo->deposit.vout) > 0 )
if ( destsatoshis > autxo->payment.value-desttxfee-1 )
destsatoshis = autxo->payment.value-desttxfee-1;
satoshis = (destsatoshis / price + 0.0000000049) - txfee;
if ( metric < 1.2 && destsatoshis > desttxfee && destsatoshis-desttxfee > (autxo->payment.value / LP_MINCLIENTVOL) && satoshis-txfee > (butxo->S.satoshis / LP_MINVOL) && satoshis <= butxo->payment.value-txfee )
{ {
printf("value %.8f price %.8f/%.8f best %.8f destsatoshis %.8f * metric %.8f -> (%f)\n",dstr(autxo->payment.value),price,bestprice,bestmetric,dstr(destsatoshis),metric,dstr(destsatoshis) * metric * metric * metric); destsatoshis = ((butxo->S.satoshis - txfee) * price);
metric = dstr(destsatoshis) * metric * metric * metric; satoshis = (destsatoshis / price + 0.49) - txfee;
if ( bestmetric == 0. || metric < bestmetric ) 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++)
{ {
bestutxo = butxo; if ( (qprice= LP_qprice_calc(&destsatoshis,&satoshis,(price*(100.+j))/100.,butxo->S.satoshis,txfee,autxo->payment.value,maxdestsatoshis,desttxfee)) > price+SMALLVAL )
*ordermatchpricep = price; break;
*bestdestsatoshisp = destsatoshis;
bestmetric = metric;
printf("set best!\n");
} }
} else printf("skip.(%d %d %d %d %d) metric %f destsatoshis %.8f value %.8f destvalue %.8f txfees %.8f %.8f sats %.8f\n",metric < 1.2,destsatoshis > desttxfee,destsatoshis-desttxfee > (autxo->payment.value / LP_MINCLIENTVOL),satoshis-txfee > (butxo->S.satoshis / LP_MINVOL),satoshis < butxo->payment.value-txfee,metric,dstr(destsatoshis),dstr(butxo->S.satoshis),dstr(autxo->payment.value),dstr(txfee),dstr(desttxfee),dstr(satoshis)); //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 else
{ {
if ( butxo != 0 ) 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("%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); 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);
//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 )
} }
} else printf("self trading or blacklisted peer\n"); } else printf("self trading or blacklisted peer\n");
} else break; }
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_json(orderbook);
@ -634,6 +690,9 @@ struct LP_utxoinfo *LP_bestutxo(double *ordermatchpricep,int64_t *bestdestsatosh
} }
if ( bestutxo == 0 || *ordermatchpricep == 0. || *bestdestsatoshisp == 0 ) if ( bestutxo == 0 || *ordermatchpricep == 0. || *bestdestsatoshisp == 0 )
return(0); return(0);
bestutxo->T.bestflag = 1;
int32_t changed;
LP_mypriceset(&changed,autxo->coin,base,1. / *ordermatchpricep);
return(bestutxo); return(bestutxo);
} }
@ -647,47 +706,43 @@ char *LP_bestfit(char *rel,double relvolume)
return(jprint(LP_utxojson(autxo),1)); return(jprint(LP_utxojson(autxo),1));
} }
char *LP_ordermatch(char *base,int64_t txfee,double maxprice,char *rel,bits256 txid,int32_t vout,bits256 feetxid,int32_t feevout,int64_t desttxfee,int32_t duration) 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 bestdestsatoshis = 0; double ordermatchprice = 0.; struct LP_utxoinfo *autxo,*bestutxo; struct LP_quoteinfo Q; int64_t bestsatoshis=0,bestdestsatoshis = 0; double ordermatchprice = 0.; struct LP_utxoinfo *autxo,*bestutxo;
if ( desttxfee == 0 && (desttxfee= LP_getestimatedrate(rel) * LP_AVETXSIZE) < LP_MIN_TXFEE ) txfee = LP_txfeecalc(base,txfee);
desttxfee = LP_MIN_TXFEE; desttxfee = LP_txfeecalc(rel,desttxfee);
if ( txfee == 0 && (txfee= LP_getestimatedrate(base) * LP_AVETXSIZE) < LP_MIN_TXFEE )
txfee = LP_MIN_TXFEE;
if ( (autxo= LP_utxopairfind(0,txid,vout,feetxid,feevout)) == 0 ) if ( (autxo= LP_utxopairfind(0,txid,vout,feetxid,feevout)) == 0 )
return(clonestr("{\"error\":\"cant find alice utxopair\"}")); return(clonestr("{\"error\":\"cant find alice utxopair\"}"));
if ( (bestutxo= LP_bestutxo(&ordermatchprice,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) 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\"}")); return(clonestr("{\"error\":\"cant find ordermatch utxo\"}"));
if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestdestsatoshis) < 0 ) if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestsatoshis,bestdestsatoshis) < 0 )
return(clonestr("{\"error\":\"cant set ordermatch quote\"}")); return(clonestr("{\"error\":\"cant set ordermatch quote\"}"));
if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,LP_mypubkey,autxo->coinaddr) < 0 ) 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(clonestr("{\"error\":\"cant set ordermatch quote info\"}"));
return(jprint(LP_quotejson(&Q),1)); return(jprint(LP_quotejson(&Q),1));
} }
char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,double profitmargin,struct LP_quoteinfo *qp,double maxprice,int32_t timeout,int32_t duration) 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; char *retstr; cJSON *bestitem=0; int32_t DEXselector=0; uint32_t expiration; double price; struct LP_pubkeyinfo *pubp; struct LP_utxoinfo *bobutxo,*aliceutxo; cJSON *bestitem=0; int32_t DEXselector=0; uint32_t expiration; double price; struct LP_pubkeyinfo *pubp;
if ( (aliceutxo= LP_utxopairfind(0,qp->desttxid,qp->destvout,qp->feetxid,qp->feevout)) == 0 ) 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); 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\"}")); return(clonestr("{\"error\":\"cant find alice utxopair\"}"));
} }
printf("aliceutxo.%p\n",aliceutxo);
if ( (bobutxo= LP_utxopairfind(1,qp->txid,qp->vout,qp->txid2,qp->vout2)) == 0 ) if ( (bobutxo= LP_utxopairfind(1,qp->txid,qp->vout,qp->txid2,qp->vout2)) == 0 )
return(clonestr("{\"error\":\"cant find bob utxopair\"}")); return(clonestr("{\"error\":\"cant find bob utxopair\"}"));
printf("bobutxo.%p\n",bobutxo);
bobutxo->T.bestflag = (uint32_t)time(NULL); bobutxo->T.bestflag = (uint32_t)time(NULL);
if ( (retstr= LP_registerall(0)) != 0 ) //if ( (retstr= LP_registerall(0)) != 0 )
free(retstr); // free(retstr);
price = LP_query(ctx,myipaddr,mypubsock,profitmargin,"request",qp); price = LP_query(ctx,myipaddr,mypubsock,"request",qp);
bestitem = LP_quotejson(qp); bestitem = LP_quotejson(qp);
if ( price > SMALLVAL ) if ( LP_pricevalid(price) > 0 )
{ {
if ( price <= maxprice ) if ( price <= maxprice )
{ {
price = LP_query(ctx,myipaddr,mypubsock,profitmargin,"connect",qp); price = LP_query(ctx,myipaddr,mypubsock,"connect",qp);
LP_requestinit(&qp->R,qp->srchash,qp->desthash,bobutxo->coin,qp->satoshis,qp->destcoin,qp->destsatoshis,qp->timestamp,qp->quotetime,DEXselector); 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);
expiration = (uint32_t)time(NULL) + timeout; expiration = (uint32_t)time(NULL) + timeout;
while ( time(NULL) < expiration ) while ( time(NULL) < expiration )
{ {
@ -724,9 +779,9 @@ char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,double profitmargin,st
return(jprint(bestitem,0)); return(jprint(bestitem,0));
} }
char *LP_autotrade(void *ctx,char *myipaddr,int32_t mypubsock,double profitmargin,char *base,char *rel,double maxprice,double relvolume,int32_t timeout,int32_t duration) char *LP_autotrade(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel,double maxprice,double relvolume,int32_t timeout,int32_t duration)
{ {
int64_t desttxfee,txfee,bestdestsatoshis=0; struct LP_utxoinfo *autxo,*bestutxo = 0; double ordermatchprice=0.; struct LP_quoteinfo Q; 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 ) if ( duration <= 0 )
duration = LP_ORDERBOOK_DURATION; duration = LP_ORDERBOOK_DURATION;
if ( timeout <= 0 ) if ( timeout <= 0 )
@ -735,21 +790,23 @@ char *LP_autotrade(void *ctx,char *myipaddr,int32_t mypubsock,double profitmargi
return(clonestr("{\"error\":\"invalid parameter\"}")); return(clonestr("{\"error\":\"invalid parameter\"}"));
if ( (autxo= LP_utxo_bestfit(rel,SATOSHIDEN * relvolume)) == 0 ) if ( (autxo= LP_utxo_bestfit(rel,SATOSHIDEN * relvolume)) == 0 )
return(clonestr("{\"error\":\"cant find utxo that is big enough\"}")); return(clonestr("{\"error\":\"cant find utxo that is big enough\"}"));
if ( (desttxfee= LP_getestimatedrate(rel) * LP_AVETXSIZE) < LP_MIN_TXFEE ) LP_txfees(&txfee,&desttxfee,base,rel);
desttxfee = LP_MIN_TXFEE; if ( (bestutxo= LP_bestutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,SATOSHIDEN*relvolume)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 )
if ( (txfee= LP_getestimatedrate(base) * LP_AVETXSIZE) < LP_MIN_TXFEE )
txfee = LP_MIN_TXFEE;
if ( (bestutxo= LP_bestutxo(&ordermatchprice,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 )
{ {
printf("bestutxo.%p ordermatchprice %.8f bestdestsatoshis %.8f\n",bestutxo,ordermatchprice,dstr(bestdestsatoshis)); printf("bestutxo.%p ordermatchprice %.8f bestdestsatoshis %.8f\n",bestutxo,ordermatchprice,dstr(bestdestsatoshis));
return(clonestr("{\"error\":\"cant find ordermatch utxo\"}")); return(clonestr("{\"error\":\"cant find ordermatch utxo\"}"));
} }
if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestdestsatoshis) < 0 ) if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestsatoshis,bestdestsatoshis) < 0 )
return(clonestr("{\"error\":\"cant set ordermatch quote\"}")); return(clonestr("{\"error\":\"cant set ordermatch quote\"}"));
if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,LP_mypubkey,autxo->coinaddr) < 0 ) 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(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)); printf("do quote.(%s)\n",jprint(LP_quotejson(&Q),1));
return(LP_trade(ctx,myipaddr,mypubsock,profitmargin,&Q,maxprice,timeout,duration)); return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration));
} }

94
iguana/exchanges/LP_peers.c

@ -33,7 +33,13 @@ cJSON *LP_peerjson(struct LP_peerinfo *peer)
cJSON *item = cJSON_CreateObject(); cJSON *item = cJSON_CreateObject();
jaddstr(item,"ipaddr",peer->ipaddr); jaddstr(item,"ipaddr",peer->ipaddr);
jaddnum(item,"port",peer->port); jaddnum(item,"port",peer->port);
jaddnum(item,"profit",peer->profitmargin); if ( strcmp(peer->ipaddr,LP_myipaddr) == 0 )
{
jaddnum(item,"session",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); return(item);
} }
@ -48,26 +54,32 @@ char *LP_peers()
return(jprint(peersjson,1)); return(jprint(peersjson,1));
} }
struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char *ipaddr,uint16_t port,uint16_t pushport,uint16_t subport,double profitmargin,int32_t numpeers,int32_t numutxos) struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char *ipaddr,uint16_t port,uint16_t pushport,uint16_t subport,int32_t numpeers,int32_t numutxos,uint32_t sessionid)
{ {
uint32_t ipbits; int32_t maxsize,pushsock,subsock,timeout; char checkip[64],pushaddr[64],subaddr[64]; struct LP_peerinfo *peer = 0; uint32_t ipbits; int32_t pushsock,subsock,timeout; char checkip[64],pushaddr[64],subaddr[64]; struct LP_peerinfo *peer = 0;
#ifdef LP_STRICTPEERS
if ( strncmp("5.9.253",ipaddr,strlen("5.9.253")) != 0 )
return(0);
#endif
ipbits = (uint32_t)calc_ipbits(ipaddr); ipbits = (uint32_t)calc_ipbits(ipaddr);
expand_ipbits(checkip,ipbits); expand_ipbits(checkip,ipbits);
if ( strcmp(checkip,ipaddr) == 0 ) if ( strcmp(checkip,ipaddr) == 0 )
{ {
if ( (peer= LP_peerfind(ipbits,port)) != 0 ) if ( (peer= LP_peerfind(ipbits,port)) != 0 )
{ {
if ( profitmargin != 0. ) /*if ( numpeers > peer->numpeers )
peer->profitmargin = profitmargin;
if ( numpeers > peer->numpeers )
peer->numpeers = numpeers; peer->numpeers = numpeers;
if ( numutxos > peer->numutxos ) if ( numutxos > peer->numutxos )
peer->numutxos = numutxos; peer->numutxos = numutxos;
if ( peer->sessionid == 0 )
peer->sessionid = sessionid;*/
} }
else else
{ {
printf("LPaddpeer %s\n",ipaddr);
peer = calloc(1,sizeof(*peer)); peer = calloc(1,sizeof(*peer));
if ( strcmp(peer->ipaddr,LP_myipaddr) == 0 )
peer->sessionid = LP_sessionid;
else peer->sessionid = sessionid;
peer->pushsock = peer->subsock = pushsock = subsock = -1; peer->pushsock = peer->subsock = pushsock = subsock = -1;
strcpy(peer->ipaddr,ipaddr); strcpy(peer->ipaddr,ipaddr);
if ( pushport != 0 && subport != 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 ) if ( pushport != 0 && subport != 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 )
@ -75,10 +87,10 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char
nanomsg_transportname(0,pushaddr,peer->ipaddr,pushport); nanomsg_transportname(0,pushaddr,peer->ipaddr,pushport);
if ( nn_connect(pushsock,pushaddr) >= 0 ) if ( nn_connect(pushsock,pushaddr) >= 0 )
{ {
timeout = 100; timeout = 1;
nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
maxsize = 2 * 1024 * 1024; //maxsize = 2 * 1024 * 1024;
nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDBUF,&maxsize,sizeof(maxsize)); //nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDBUF,&maxsize,sizeof(maxsize));
printf("connected to push.(%s) %d\n",pushaddr,pushsock); printf("connected to push.(%s) %d\n",pushaddr,pushsock);
peer->connected = (uint32_t)time(NULL); peer->connected = (uint32_t)time(NULL);
peer->pushsock = pushsock; peer->pushsock = pushsock;
@ -101,7 +113,7 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char
printf("error connecting to push.(%s)\n",pushaddr); printf("error connecting to push.(%s)\n",pushaddr);
} }
} else printf("%s pushport.%u subport.%u pushsock.%d\n",ipaddr,pushport,subport,pushsock); } else printf("%s pushport.%u subport.%u pushsock.%d\n",ipaddr,pushport,subport,pushsock);
peer->profitmargin = profitmargin; //peer->profitmargin = profitmargin;
peer->ipbits = ipbits; peer->ipbits = ipbits;
peer->port = port; peer->port = port;
peer->ip_port = ((uint64_t)port << 32) | ipbits; peer->ip_port = ((uint64_t)port << 32) | ipbits;
@ -113,16 +125,60 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char
printf("_LPaddpeer %s -> numpeers.%d mypubsock.%d other.(%d %d)\n",ipaddr,mypeer->numpeers,mypubsock,numpeers,numutxos); printf("_LPaddpeer %s -> numpeers.%d mypubsock.%d other.(%d %d)\n",ipaddr,mypeer->numpeers,mypubsock,numpeers,numutxos);
} else peer->numpeers = 1; // will become mypeer } else peer->numpeers = 1; // will become mypeer
portable_mutex_unlock(&LP_peermutex); portable_mutex_unlock(&LP_peermutex);
if ( mypubsock >= 0 ) if ( IAMLP != 0 && mypubsock >= 0 )
{ {
char *msg = jprint(LP_peerjson(peer),1); struct iguana_info *coin,*ctmp; bits256 zero; char *msg,busaddr[64];
LP_send(mypubsock,msg,(int32_t)strlen(msg)+1,1); msg = jprint(LP_peerjson(peer),1);
memset(zero.bytes,0,sizeof(zero));
//LP_send(mypubsock,msg,(int32_t)strlen(msg)+1,1);
LP_broadcast_message(mypubsock,"","",zero,msg);
if ( 0 )
{
HASH_ITER(hh,LP_coins,coin,ctmp)
{
if ( coin->bussock >= 0 )
{
nanomsg_transportname(0,busaddr,peer->ipaddr,coin->busport);
nn_connect(coin->bussock,busaddr);
}
}
}
} }
} }
} else printf("LP_addpeer: checkip.(%s) vs (%s)\n",checkip,ipaddr); } else printf("LP_addpeer: checkip.(%s) vs (%s)\n",checkip,ipaddr);
return(peer); return(peer);
} }
int32_t LP_coinbus(uint16_t coin_busport)
{
struct LP_peerinfo *peer,*tmp; char busaddr[64]; int32_t timeout,bussock = -1;
return(-1);
if ( IAMLP != 0 && LP_mypeer != 0 && (bussock= nn_socket(AF_SP,NN_BUS)) >= 0 )
{
timeout = 1;
nn_setsockopt(bussock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
nn_setsockopt(bussock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout));
nanomsg_transportname(0,busaddr,LP_mypeer->ipaddr,coin_busport);
if ( nn_bind(bussock,busaddr) < 0 )
{
printf("error binding to coin_busport.%s\n",busaddr);
nn_close(bussock);
}
else
{
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
if ( LP_mypeer->port != peer->port || strcmp(LP_mypeer->ipaddr,peer->ipaddr) != 0 )
{
nanomsg_transportname(0,busaddr,peer->ipaddr,coin_busport);
nn_connect(bussock,busaddr);
}
}
}
}
return(bussock);
}
int32_t LP_peersparse(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now) int32_t LP_peersparse(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now)
{ {
struct LP_peerinfo *peer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; struct LP_peerinfo *peer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0;
@ -142,7 +198,7 @@ int32_t LP_peersparse(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipa
argipbits = (uint32_t)calc_ipbits(argipaddr); argipbits = (uint32_t)calc_ipbits(argipaddr);
if ( (peer= LP_peerfind(argipbits,argport)) == 0 ) if ( (peer= LP_peerfind(argipbits,argport)) == 0 )
{ {
peer = LP_addpeer(mypeer,mypubsock,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos")); peer = LP_addpeer(mypeer,mypubsock,argipaddr,argport,pushport,subport,jint(item,"numpeers"),jint(item,"numutxos"),juint(item,"session"));
} }
if ( peer != 0 ) if ( peer != 0 )
{ {
@ -158,11 +214,11 @@ int32_t LP_peersparse(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipa
return(n); return(n);
} }
void LP_peersquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *myipaddr,uint16_t myport,double myprofit) void LP_peersquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *myipaddr,uint16_t myport)
{ {
char *retstr; struct LP_peerinfo *peer,*tmp; uint32_t now,flag = 0; char *retstr; struct LP_peerinfo *peer,*tmp; uint32_t now,flag = 0;
peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport);
if ( (retstr= issue_LP_getpeers(destipaddr,destport,myipaddr,myport,myprofit,mypeer!=0?mypeer->numpeers:0,mypeer!=0?mypeer->numutxos:0)) != 0 ) if ( (retstr= issue_LP_getpeers(destipaddr,destport,myipaddr,myport,mypeer!=0?mypeer->numpeers:0,mypeer!=0?mypeer->numutxos:0)) != 0 )
{ {
//printf("got.(%s)\n",retstr); //printf("got.(%s)\n",retstr);
now = (uint32_t)time(NULL); now = (uint32_t)time(NULL);
@ -174,9 +230,9 @@ void LP_peersquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr
{ {
if ( peer->lasttime != now ) if ( peer->lasttime != now )
{ {
printf("{%s:%u %.6f}.%d ",peer->ipaddr,peer->port,peer->profitmargin,peer->lasttime - now); printf("{%s:%u}.%d ",peer->ipaddr,peer->port,peer->lasttime - now);
flag++; flag++;
if ( (retstr= issue_LP_notify(destipaddr,destport,peer->ipaddr,peer->port,peer->profitmargin,peer->numpeers,0)) != 0 ) if ( (retstr= issue_LP_notify(destipaddr,destport,peer->ipaddr,peer->port,peer->numpeers,0,peer->sessionid)) != 0 )
free(retstr); free(retstr);
} }
} }

577
iguana/exchanges/LP_portfolio.c

@ -0,0 +1,577 @@
/******************************************************************************
* Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
//
// LP_portfolio.c
// marketmaker
//
char LP_portfolio_base[16],LP_portfolio_rel[16];
double LP_portfolio_relvolume;
cJSON *LP_portfolio_entry(struct iguana_info *coin)
{
cJSON *item = cJSON_CreateObject();
jaddstr(item,"coin",coin->symbol);
jaddstr(item,"address",coin->smartaddr);
jaddnum(item,"amount",dstr(coin->maxamount));
jaddnum(item,"price",coin->price_kmd);
jaddnum(item,"kmd_equiv",dstr(coin->kmd_equiv));
jaddnum(item,"perc",coin->perc);
jaddnum(item,"goal",coin->goal);
jaddnum(item,"goalperc",coin->goalperc);
jaddnum(item,"relvolume",coin->relvolume);
jaddnum(item,"force",coin->force);
jaddnum(item,"balanceA",dstr(coin->balanceA));
jaddnum(item,"valuesumA",dstr(coin->valuesumA));
if ( coin->valuesumA != 0 )
jaddnum(item,"aliceutil",100. * (double)coin->balanceA/coin->valuesumA);
jaddnum(item,"balanceB",dstr(coin->balanceB));
jaddnum(item,"valuesumB",dstr(coin->valuesumB));
jaddnum(item,"balance",dstr(coin->maxamount));
if ( coin->valuesumB != 0 )
jaddnum(item,"bobutil",100. * (double)coin->balanceB/coin->valuesumB);
return(item);
}
uint64_t LP_balance(uint64_t *valuep,int32_t iambob,char *symbol,char *coinaddr)
{
cJSON *array,*item; int32_t i,n; uint64_t valuesum,satoshisum,value;
valuesum = satoshisum = 0;
if ( (array= LP_listunspent(symbol,coinaddr)) != 0 )
{
if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
value = SATOSHIDEN * jdouble(item,"amount");
if ( value == 0 )
value = SATOSHIDEN * jdouble(item,"value");
valuesum += value;
}
}
free_json(array);
}
if ( (array= LP_inventory(symbol,iambob)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 && is_cJSON_Array(array) != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
//valuesum += j64bits(item,"value") + j64bits(item,"value2");
satoshisum += j64bits(item,"satoshis");
}
}
free_json(array);
}
*valuep = valuesum;
return(satoshisum);
}
char *LP_portfolio()
{
double maxval = 0.,minval = 0.,goalsum = 0.; uint64_t kmdsum = 0; int32_t iter; cJSON *retjson,*array; struct iguana_info *coin,*tmp,*sellcoin = 0,*buycoin = 0;
array = cJSON_CreateArray();
retjson = cJSON_CreateObject();
for (iter=0; iter<2; iter++)
{
HASH_ITER(hh,LP_coins,coin,tmp)
{
if ( coin->inactive != 0 )
continue;
if ( iter == 0 )
{
LP_privkey_init(-1,coin,LP_mypriv25519,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 )
coin->price_kmd = LP_price(coin->symbol,"KMD");
else coin->price_kmd = 1.;
coin->maxamount = coin->valuesumA;
if ( coin->valuesumB > coin->maxamount )
coin->maxamount = coin->valuesumB;
coin->kmd_equiv = coin->maxamount * coin->price_kmd;
kmdsum += coin->kmd_equiv;
goalsum += coin->goal;
}
else
{
coin->relvolume = 0.;
if ( kmdsum > SMALLVAL )
coin->perc = 100. * coin->kmd_equiv / kmdsum;
if ( goalsum > SMALLVAL && coin->goal > SMALLVAL )
{
coin->goalperc = 100. * coin->goal / goalsum;
if ( (coin->force= (coin->goalperc - coin->perc)) < 0. )
{
coin->force *= -coin->force;
if ( coin->price_kmd > SMALLVAL )
coin->relvolume = (dstr(coin->maxamount) * (coin->perc - coin->goalperc)) / 100.;
} else coin->force *= coin->force;
if ( coin->force > maxval )
{
maxval = coin->force;
buycoin = coin;
}
if ( coin->force < minval )
{
minval = coin->force;
sellcoin = coin;
}
} else coin->goalperc = coin->force = 0.;
jaddi(array,LP_portfolio_entry(coin));
}
}
}
jaddstr(retjson,"result","success");
jaddnum(retjson,"kmd_equiv",dstr(kmdsum));
if ( buycoin != 0 )
{
jaddstr(retjson,"buycoin",buycoin->symbol);
jaddnum(retjson,"buyforce",maxval);
}
if ( sellcoin != 0 )
{
jaddstr(retjson,"sellcoin",sellcoin->symbol);
jaddnum(retjson,"sellforce",minval);
}
if ( LP_portfolio_relvolume > SMALLVAL )
{
jaddstr(retjson,"base",LP_portfolio_base);
jaddstr(retjson,"rel",LP_portfolio_rel);
jaddnum(retjson,"relvolume",LP_portfolio_relvolume);
}
jadd(retjson,"portfolio",array);
return(jprint(retjson,1));
}
char *LP_portfolio_goal(char *symbol,double goal)
{
struct iguana_info *coin,*tmp; int32_t iter,n = 0; double kmdbtc = 50.;
if ( strcmp(symbol,"*") == 0 )
{
for (iter=0; iter<2; iter++)
{
HASH_ITER(hh,LP_coins,coin,tmp)
{
if ( coin->inactive != 0 )
continue;
if ( iter == 0 )
coin->goal = 0;
if ( coin->inactive == 0 && strcmp(coin->symbol,"KMD") != 0 && strcmp(coin->symbol,"BTC") != 0 )
{
if ( iter == 0 )
n++;
else coin->goal = (100. - kmdbtc) / n;
}
}
if ( n == 0 )
break;
}
if ( (coin= LP_coinfind("KMD")) != 0 && coin->inactive == 0 )
coin->goal = kmdbtc * 0.5;
if ( (coin= LP_coinfind("BTC")) != 0 && coin->inactive == 0 )
coin->goal = kmdbtc * 0.5;
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);
return(LP_portfolio());
} else return(clonestr("{\"error\":\"cant set goal for inactive coin\"}"));
}
int32_t LP_autoprices;
/*int32_t LP_autofill(char *base,char *rel,double maxprice,double totalrelvolume)
{
struct LP_priceinfo *basepp,*relpp;
if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
basepp->maxprices[relpp->ind] = maxprice;
basepp->relvols[relpp->ind] = totalrelvolume;
LP_autofills++;
return(0);
}
return(-1);
}*/
int32_t LP_autoprice(char *base,char *rel,double minprice,double margin,char *type)
{
struct LP_priceinfo *basepp,*relpp;
if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
basepp->minprices[relpp->ind] = minprice;
basepp->margins[relpp->ind] = margin;
LP_autoprices++;
return(0);
}
return(-1);
}
void LP_autopriceset(void *ctx,int32_t dir,struct LP_priceinfo *relpp,struct LP_priceinfo *basepp,double price)
{
double margin,minprice,oppomargin; int32_t changed;
margin = basepp->margins[relpp->ind];
oppomargin = relpp->margins[basepp->ind];
if ( margin != 0. || oppomargin != 0. )
{
if ( margin == 0. )
margin = oppomargin;
//printf("min %.8f %s/%s %.8f dir.%d margin %.8f (%.8f %.8f)\n",basepp->minprices[relpp->ind],relpp->symbol,basepp->symbol,price,dir,margin,1. / (price * (1. - margin)),(price * (1. + margin)));
if ( dir > 0 )
price = 1. / (price * (1. - margin));
else price = (price * (1. + margin));
if ( (minprice= basepp->minprices[relpp->ind]) == 0. || price >= minprice )
{
LP_mypriceset(&changed,relpp->symbol,basepp->symbol,price);
//printf("changed.%d\n",changed);
if ( changed != 0 )
LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,relpp->symbol,basepp->symbol,price);
}
}
}
double LP_pricesparse(void *ctx,int32_t trexflag,char *retstr,struct LP_priceinfo *btcpp)
{
//{"success":true,"message":"","result":[{"MarketName":"BTC-KMD","High":0.00040840,"Low":0.00034900,"Volume":328042.46061669,"Last":0.00037236,"BaseVolume":123.36439511,"TimeStamp":"2017-07-15T13:50:21.87","Bid":0.00035721,"Ask":0.00037069,"OpenBuyOrders":343,"OpenSellOrders":1690,"PrevDay":0.00040875,"Created":"2017-02-11T23:04:01.853"},
//{"TradePairId":4762,"Label":"WAVES/BTC","AskPrice":0.00099989,"BidPrice":0.00097350,"Low":0.00095000,"High":0.00108838,"Volume":6501.24403100,"LastPrice":0.00098028,"BuyVolume":1058994.86554882,"SellVolume":2067.87377158,"Change":-7.46,"Open":0.00105926,"Close":0.00098028,"BaseVolume":6.52057452,"BuyBaseVolume":2.33098660,"SellBaseVolume":1167.77655709},
int32_t i,j,n,iter; double price,kmdbtc,bid,ask,nxtkmd=0.; struct LP_priceinfo *coinpp,*refpp; char symbol[16],*name,*refcoin; cJSON *retjson,*array,*item;
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
//printf("got.(%s)\n",retstr);
kmdbtc = 0.;
refcoin = "BTC";
refpp = btcpp;
if ( (array= jarray(&n,retjson,trexflag != 0 ? "result" : "Data")) != 0 )
{
for (iter=0; iter<2; iter++)
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( (name= jstr(item,trexflag != 0 ? "MarketName" : "Label")) != 0 )
{
symbol[0] = 0;
if ( trexflag != 0 )
{
if ( strncmp("BTC-",name,4) == 0 )
{
name += 4;
strcpy(symbol,name);
}
}
else
{
for (j=0; j<sizeof(symbol)-1; j++)
if ( (symbol[j]= name[j]) == '/' )
break;
symbol[j] = 0;
if ( strcmp(name+j+1,"BTC") != 0 )
continue;
}
if ( symbol[0] != 0 )
{
//printf("%s\n",jprint(item,0));
bid = jdouble(item,trexflag != 0 ? "Bid" : "BidPrice");
ask = jdouble(item,trexflag != 0 ? "Ask" : "AskPrice");
if ( iter == 1 && kmdbtc > SMALLVAL && strcmp(symbol,"NXT") == 0 )
nxtkmd = 0.5 * (bid + ask) / kmdbtc;
if ( (coinpp= LP_priceinfofind(symbol)) != 0 )
{
coinpp->high[trexflag] = jdouble(item,"High");
coinpp->low[trexflag] = jdouble(item,"Low");
//coinpp->volume = jdouble(item,"Volume");
//coinpp->btcvolume = jdouble(item,"BaseVolume");
coinpp->last[trexflag] = jdouble(item,trexflag != 0 ? "Last" : "LastPrice");
coinpp->bid[trexflag] = bid;
coinpp->ask[trexflag] = ask;
//coinpp->prevday = jdouble(item,"PrevDay");
//printf("iter.%d trexflag.%d %s high %.8f, low %.8f, last %.8f hbla.(%.8f %.8f)\n",iter,trexflag,symbol,coinpp->high[trexflag],coinpp->low[trexflag],coinpp->last[trexflag],coinpp->bid[trexflag],coinpp->ask[trexflag]);
if ( coinpp->bid[trexflag] > SMALLVAL && coinpp->ask[trexflag] > SMALLVAL )
{
price = 0.5 * (coinpp->bid[trexflag] + coinpp->ask[trexflag]);
if ( iter == 0 )
{
if ( strcmp(symbol,"KMD") == 0 )
kmdbtc = price;
}
else
{
if ( strcmp(symbol,"KMD") == 0 )
continue;
//printf("(%s/%s) iter.%d trexflag.%d %s %.8f %.8f\n",refpp->symbol,coinpp->symbol,iter,trexflag,symbol,price,price/kmdbtc);
price /= kmdbtc;
}
if ( trexflag == 0 && coinpp->bid[1] > SMALLVAL && coinpp->ask[1] > SMALLVAL )
{
//printf("have trex: iter.%d trexflag.%d %s %.8f %.8f\n",iter,trexflag,symbol,coinpp->bid[1],coinpp->ask[1]);
continue;
}
LP_autopriceset(ctx,1,refpp,coinpp,price);
LP_autopriceset(ctx,-1,coinpp,refpp,price);
}
}
}
}
}
refcoin = "KMD";
if ( kmdbtc == 0. || (refpp= LP_priceinfofind("KMD")) == 0 )
break;
}
}
free_json(retjson);
}
return(nxtkmd);
}
static char *assetids[][3] =
{
{ "12071612744977229797", "UNITY", "10000" },
{ "15344649963748848799", "DEX", "1" },
{ "6883271355794806507", "PANGEA", "10000" },
{ "17911762572811467637", "JUMBLR", "10000" },
{ "17083334802666450484", "BET", "10000" },
{ "13476425053110940554", "CRYPTO", "1000" },
{ "6932037131189568014", "HODL", "1" },
{ "3006420581923704757", "SHARK", "10000" },
{ "17571711292785902558", "BOTS", "1" },
{ "10524562908394749924", "MGW", "1" },
};
void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp)
{
char *retstr; cJSON *retjson,*bid,*ask; uint64_t bidsatoshis,asksatoshis; int32_t i; double nxtkmd,price; struct LP_priceinfo *kmdpp,*fiatpp,*nxtpp;
if ( (retstr= issue_curlt("https://bittrex.com/api/v1.1/public/getmarketsummaries",LP_HTTP_TIMEOUT*10)) == 0 )
{
printf("trex error getting marketsummaries\n");
sleep(60);
return;
}
nxtkmd = LP_pricesparse(ctx,1,retstr,btcpp);
free(retstr);
if ( (retstr= issue_curlt("https://www.cryptopia.co.nz/api/GetMarkets",LP_HTTP_TIMEOUT*10)) == 0 )
{
printf("cryptopia error getting marketsummaries\n");
sleep(60);
return;
}
LP_pricesparse(ctx,0,retstr,btcpp);
free(retstr);
if ( (kmdpp= LP_priceinfofind("KMD")) != 0 )
{
for (i=0; i<32; i++)
{
if ( (fiatpp= LP_priceinfofind(CURRENCIES[i])) != 0 )
{
if ( (retjson= LP_paxprice(CURRENCIES[i])) != 0 )
{
//printf("(%s %.8f %.8f) ",CURRENCIES[i],jdouble(retjson,"price"),jdouble(retjson,"invprice"));
price = jdouble(retjson,"price");
LP_autopriceset(ctx,1,kmdpp,fiatpp,price);
LP_autopriceset(ctx,-1,fiatpp,kmdpp,price);
free_json(retjson);
}
}
}
}
if ( nxtkmd > SMALLVAL )
{
for (i=0; i<sizeof(assetids)/sizeof(*assetids); i++)
{
if ( (nxtpp= LP_priceinfofind(assetids[i][1])) != 0 )
{
price = 0.;
bidsatoshis = asksatoshis = 0;
if ( (retjson= LP_assethbla(assetids[i][0])) != 0 )
{
if ( (bid= jobj(retjson,"bid")) != 0 && (ask= jobj(retjson,"ask")) != 0 )
{
bidsatoshis = j64bits(bid,"priceNQT") * atoi(assetids[i][2]);
asksatoshis = j64bits(ask,"priceNQT") * atoi(assetids[i][2]);
if ( bidsatoshis != 0 && asksatoshis != 0 )
price = 0.5 * dstr(bidsatoshis + asksatoshis) * nxtkmd;
}
LP_autopriceset(ctx,1,kmdpp,nxtpp,price);
LP_autopriceset(ctx,-1,nxtpp,kmdpp,price);
//printf("%s %s -> (%s) nxtkmd %.8f %.8f %.8f\n",assetids[i][1],assetids[i][0],jprint(retjson,0),nxtkmd,0.5*dstr(bidsatoshis + asksatoshis),price);
free_json(retjson);
}
}
}
}
}
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 *retstr2; double bid,ask,maxprice; uint32_t requestid,quoteid,iter,i; cJSON *retjson2;
requestid = quoteid = 0;
LP_myprice(&bid,&ask,buy->symbol,sell->symbol);
maxprice = ask;
if ( setbaserel != 0 )
{
strcpy(LP_portfolio_base,"");
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);
if ( LP_pricevalid(maxprice) > 0 )
{
relvolume = sell->relvolume;
for (iter=0; iter<2; iter++)
{
if ( relvolume < dstr(LP_MIN_TXFEE) )
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 ( (retjson2= cJSON_Parse(retstr2)) != 0 )
{
if ( (requestid= juint(retjson2,"requestid")) != 0 && (quoteid= juint(retjson2,"quoteid")) != 0 )
{
}
free_json(retjson2);
}
printf("%s relvolume %.8f LP_autotrade.(%s)\n",sell->symbol,relvolume,retstr2);
free(retstr2);
}
if ( requestid != 0 && quoteid != 0 )
break;
} else printf("cant find alice %.8f %s\n",relvolume,sell->symbol);
if ( iter == 0 )
{
for (i=0; i<100; i++)
{
relvolume *= .99;
if ( LP_utxo_bestfit(sell->symbol,SATOSHIDEN * relvolume) != 0 )
{
printf("i.%d relvolume %.8f from %.8f\n",i,relvolume,sell->relvolume);
break;
}
}
}
}
}
else if ( setbaserel != 0 )
{
strcpy(LP_portfolio_base,buy->symbol);
strcpy(LP_portfolio_rel,sell->symbol);
LP_portfolio_relvolume = sell->relvolume;
}
*requestidp = requestid;
*quoteidp = quoteid;
if ( requestid != 0 && quoteid != 0 )
return(0);
else return(-1);
}
struct LP_portfoliotrade { double metric; char buycoin[16],sellcoin[16]; };
int32_t LP_portfolio_order(struct LP_portfoliotrade *trades,int32_t max,cJSON *array)
{
int32_t i,j,m,n = 0; cJSON *item; struct LP_portfoliotrade coins[256];
memset(coins,0,sizeof(coins));
if ( (m= cJSON_GetArraySize(array)) > 0 )
{
for (i=j=0; i<m && i<sizeof(coins)/sizeof(*coins); i++)
{
item = jitem(array,i);
safecopy(coins[j].buycoin,jstr(item,"coin"),sizeof(coins[j].buycoin));
coins[j].metric = jdouble(item,"force");
if ( fabs(coins[j].metric) > SMALLVAL && coins[j].buycoin[0] != 0 )
j++;
}
if ( (m= j) > 1 )
{
for (i=n=0; i<m-1; i++)
for (j=i+1; j<m; j++)
if ( coins[i].metric*coins[j].metric < 0. )
{
if ( coins[i].metric > 0. )
{
trades[n].metric = (coins[i].metric - coins[j].metric);
strcpy(trades[n].buycoin,coins[i].buycoin);
strcpy(trades[n].sellcoin,coins[j].buycoin);
printf("buy %s %f, sell %s %f -> %f\n",trades[n].buycoin,coins[i].metric,trades[n].sellcoin,coins[j].metric,trades[n].metric);
}
else
{
trades[n].metric = (coins[j].metric - coins[i].metric);
strcpy(trades[n].buycoin,coins[j].buycoin);
strcpy(trades[n].sellcoin,coins[i].buycoin);
printf("buy %s %f, sell %s %f -> %f\n",trades[n].buycoin,coins[j].metric,trades[n].sellcoin,coins[i].metric,trades[n].metric);
}
n++;
if ( n >= max )
break;
}
revsortds((void *)trades,n,sizeof(*trades));
for (i=0; i<n; i++)
printf("%d: buy %s, sell %s -> %f\n",i,trades[i].buycoin,trades[i].sellcoin,trades[i].metric);
}
}
return(n);
}
void prices_loop(void *ignore)
{
char *retstr; cJSON *retjson,*array; char *buycoin,*sellcoin; struct iguana_info *buy,*sell; uint32_t requestid,quoteid; int32_t i,n,m; struct LP_portfoliotrade trades[256]; struct LP_priceinfo *btcpp; void *ctx = bitcoin_ctx();
while ( 1 )
{
if ( (btcpp= LP_priceinfofind("BTC")) == 0 )
{
sleep(60);
continue;
}
if ( LP_autoprices != 0 )
LP_autoprice_iter(ctx,btcpp);
if ( (retstr= LP_portfolio()) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
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 )
{
array = jarray(&m,retjson,"portfolio");
if ( array != 0 && (n= LP_portfolio_order(trades,(int32_t)(sizeof(trades)/sizeof(*trades)),array)) > 0 )
{
for (i=0; i<n; i++)
{
if ( strcmp(trades[i].buycoin,buycoin) != 0 || strcmp(trades[i].sellcoin,sellcoin) != 0 )
{
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 )
break;
}
}
}
}
}
free_json(retjson);
}
free(retstr);
}
sleep(60);
}
}

328
iguana/exchanges/LP_prices.c

@ -26,9 +26,14 @@ struct LP_priceinfo
char symbol[16]; char symbol[16];
uint64_t coinbits; uint64_t coinbits;
int32_t ind,pad; int32_t ind,pad;
double diagval; double diagval,high[2],low[2],last[2],bid[2],ask[2]; //volume,btcvolume,prevday; // mostly bittrex info
double relvals[LP_MAXPRICEINFOS]; double relvals[LP_MAXPRICEINFOS];
double myprices[LP_MAXPRICEINFOS]; double myprices[LP_MAXPRICEINFOS];
double minprices[LP_MAXPRICEINFOS]; // autoprice
double margins[LP_MAXPRICEINFOS];
//double maxprices[LP_MAXPRICEINFOS]; // autofill of base/rel
//double relvols[LP_MAXPRICEINFOS];
FILE *fps[LP_MAXPRICEINFOS];
} LP_priceinfos[LP_MAXPRICEINFOS]; } LP_priceinfos[LP_MAXPRICEINFOS];
int32_t LP_numpriceinfos; int32_t LP_numpriceinfos;
@ -49,6 +54,13 @@ struct LP_pubkeyinfo
uint32_t timestamp,istrusted,numerrors; uint32_t timestamp,istrusted,numerrors;
} *LP_pubkeyinfos; } *LP_pubkeyinfos;
int32_t LP_pricevalid(double price)
{
if ( price > SMALLVAL && isnan(price) == 0 && price < SATOSHIDEN )
return(1);
else return(0);
}
struct LP_priceinfo *LP_priceinfofind(char *symbol) struct LP_priceinfo *LP_priceinfofind(char *symbol)
{ {
int32_t i; struct LP_priceinfo *pp; uint64_t coinbits; int32_t i; struct LP_priceinfo *pp; uint64_t coinbits;
@ -167,7 +179,8 @@ cJSON *LP_pubkeyjson(struct LP_pubkeyinfo *pubp)
base = LP_priceinfos[baseid].symbol; base = LP_priceinfos[baseid].symbol;
for (relid=0; relid<LP_numpriceinfos; relid++) for (relid=0; relid<LP_numpriceinfos; relid++)
{ {
if ( (price= pubp->matrix[baseid][relid]) > SMALLVAL ) price = pubp->matrix[baseid][relid];
if ( LP_pricevalid(price) > 0 )
{ {
item = cJSON_CreateArray(); item = cJSON_CreateArray();
jaddistr(item,base); jaddistr(item,base);
@ -197,7 +210,7 @@ char *LP_prices()
void LP_prices_parse(cJSON *obj) void LP_prices_parse(cJSON *obj)
{ {
struct LP_pubkeyinfo *pubp; struct LP_priceinfo *basepp; uint32_t timestamp; bits256 pubkey; cJSON *asks,*item; int32_t i,n,relid; char *base,*rel; double askprice; struct LP_pubkeyinfo *pubp; struct LP_priceinfo *basepp,*relpp; uint32_t timestamp; bits256 pubkey; cJSON *asks,*item; int32_t i,n,relid; char *base,*rel; double askprice;
pubkey = jbits256(obj,"pubkey"); pubkey = jbits256(obj,"pubkey");
if ( bits256_nonz(pubkey) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 ) if ( bits256_nonz(pubkey) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 )
{ {
@ -210,10 +223,18 @@ void LP_prices_parse(cJSON *obj)
base = jstri(item,0); base = jstri(item,0);
rel = jstri(item,1); rel = jstri(item,1);
askprice = jdoublei(item,2); askprice = jdoublei(item,2);
if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 ) if ( LP_pricevalid(askprice) > 0 )
{ {
char str[65]; printf("%s %s/%s (%d/%d) %.8f\n",bits256_str(str,pubkey),base,rel,basepp->ind,relid,askprice); if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 )
pubp->matrix[basepp->ind][relid] = askprice; {
char str[65]; printf("%s %s/%s (%d/%d) %.8f\n",bits256_str(str,pubkey),base,rel,basepp->ind,relid,askprice);
pubp->matrix[basepp->ind][relid] = askprice;
if ( (relpp= LP_priceinfofind(rel)) != 0 )
{
dxblend(&basepp->relvals[relpp->ind],askprice,0.9);
dxblend(&relpp->relvals[basepp->ind],1. / askprice,0.9);
}
}
} }
} }
} }
@ -247,8 +268,10 @@ double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,i
(*qp) = ptr->Q; (*qp) = ptr->Q;
if ( ptr->price == 0. && ptr->Q.satoshis != 0 ) if ( ptr->price == 0. && ptr->Q.satoshis != 0 )
{ {
printf("LP_pricecache: null ptr->price? ");
ptr->price = (double)ptr->Q.destsatoshis / ptr->Q.satoshis; 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("found %s/%s %.8f\n",base,rel,ptr->price); //printf("found %s/%s %.8f\n",base,rel,ptr->price);
return(ptr->price); return(ptr->price);
@ -260,12 +283,15 @@ double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,i
void LP_priceinfoupdate(char *base,char *rel,double price) void LP_priceinfoupdate(char *base,char *rel,double price)
{ {
struct LP_priceinfo *basepp,*relpp; struct LP_priceinfo *basepp,*relpp;
if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) if ( LP_pricevalid(price) > 0 )
{ {
//dxblend(&basepp->relvals[relpp->ind],price,0.9); if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
//dxblend(&relpp->relvals[basepp->ind],1. / price,0.9); {
basepp->relvals[relpp->ind] = price; //dxblend(&basepp->relvals[relpp->ind],price,0.9);
relpp->relvals[basepp->ind] = 1. / price; //dxblend(&relpp->relvals[basepp->ind],1. / price,0.9);
basepp->relvals[relpp->ind] = price;
relpp->relvals[basepp->ind] = 1. / price;
}
} }
} }
@ -275,9 +301,11 @@ double LP_myprice(double *bidp,double *askp,char *base,char *rel)
*bidp = *askp = 0.; *bidp = *askp = 0.;
if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{ {
if ( (*askp= basepp->myprices[relpp->ind]) > SMALLVAL ) *askp = basepp->myprices[relpp->ind];
if ( LP_pricevalid(*askp) > 0 )
{ {
if ( (val= relpp->myprices[basepp->ind]) > SMALLVAL ) val = relpp->myprices[basepp->ind];
if ( LP_pricevalid(val) > 0 )
{ {
*bidp = 1. / val; *bidp = 1. / val;
return((*askp + *bidp) * 0.5); return((*askp + *bidp) * 0.5);
@ -290,7 +318,8 @@ double LP_myprice(double *bidp,double *askp,char *base,char *rel)
} }
else else
{ {
if ( (val= relpp->myprices[basepp->ind]) > SMALLVAL ) val = relpp->myprices[basepp->ind];
if ( LP_pricevalid(val) > 0 )
{ {
*bidp = 1. / val; *bidp = 1. / val;
*askp = 0.; *askp = 0.;
@ -325,14 +354,18 @@ char *LP_myprices()
return(jprint(array,1)); return(jprint(array,1));
} }
int32_t LP_mypriceset(char *base,char *rel,double price) int32_t LP_mypriceset(int32_t *changedp,char *base,char *rel,double price)
{ {
struct LP_priceinfo *basepp,*relpp; struct LP_pubkeyinfo *pubp; struct LP_priceinfo *basepp,*relpp; struct LP_pubkeyinfo *pubp;
if ( base != 0 && rel != 0 && price > SMALLVAL && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) *changedp = 0;
if ( base != 0 && rel != 0 && LP_pricevalid(price) > 0 && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{ {
if ( fabs(basepp->myprices[relpp->ind] - price) > SMALLVAL )
*changedp = 1;
basepp->myprices[relpp->ind] = price; // ask 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 //relpp->myprices[basepp->ind] = (1. / price); // bid
if ( (pubp= LP_pubkeyadd(LP_mypubkey)) != 0 ) if ( (pubp= LP_pubkeyadd(LP_mypub25519)) != 0 )
{ {
pubp->matrix[basepp->ind][relpp->ind] = price; pubp->matrix[basepp->ind][relpp->ind] = price;
//pubp->matrix[relpp->ind][basepp->ind] = (1. / price); //pubp->matrix[relpp->ind][basepp->ind] = (1. / price);
@ -425,24 +458,27 @@ struct LP_cacheinfo *LP_cacheadd(char *base,char *rel,bits256 txid,int32_t vout,
char str[65]; struct LP_cacheinfo *ptr=0; char str[65]; struct LP_cacheinfo *ptr=0;
if ( base == 0 || rel == 0 ) if ( base == 0 || rel == 0 )
return(0); return(0);
if ( (ptr= LP_cachefind(base,rel,txid,vout)) == 0 ) if ( LP_pricevalid(price) > 0 )
{ {
ptr = calloc(1,sizeof(*ptr)); if ( (ptr= LP_cachefind(base,rel,txid,vout)) == 0 )
if ( LP_cachekey(ptr->key,base,rel,txid,vout) == sizeof(ptr->key) )
{ {
portable_mutex_lock(&LP_cachemutex); ptr = calloc(1,sizeof(*ptr));
HASH_ADD(hh,LP_cacheinfos,key,sizeof(ptr->key),ptr); if ( LP_cachekey(ptr->key,base,rel,txid,vout) == sizeof(ptr->key) )
portable_mutex_unlock(&LP_cachemutex); {
} else printf("LP_cacheadd keysize mismatch?\n"); portable_mutex_lock(&LP_cachemutex);
HASH_ADD(hh,LP_cacheinfos,key,sizeof(ptr->key),ptr);
portable_mutex_unlock(&LP_cachemutex);
} else printf("LP_cacheadd keysize mismatch?\n");
}
ptr->Q = *qp;
ptr->timestamp = (uint32_t)time(NULL);
if ( price != ptr->price )
{
ptr->price = price;
LP_priceinfoupdate(base,rel,price);
printf("updated %s/v%d %s/%s %llu price %.8f\n",bits256_str(str,txid),vout,base,rel,(long long)qp->satoshis,price);
} else ptr->price = price;
} }
ptr->Q = *qp;
ptr->timestamp = (uint32_t)time(NULL);
if ( price != ptr->price )
{
ptr->price = price;
LP_priceinfoupdate(base,rel,price);
printf("updated %s/v%d %s/%s %llu price %.8f\n",bits256_str(str,txid),vout,base,rel,(long long)qp->satoshis,price);
} else ptr->price = price;
return(ptr); return(ptr);
} }
@ -475,7 +511,7 @@ static int _cmp_orderbook(const void *a,const void *b)
cJSON *LP_orderbookjson(struct LP_orderbookentry *op) cJSON *LP_orderbookjson(struct LP_orderbookentry *op)
{ {
cJSON *item = cJSON_CreateObject(); cJSON *item = cJSON_CreateObject();
if ( op->price > SMALLVAL ) if ( LP_pricevalid(op->price) > 0 )
{ {
jaddnum(item,"price",op->price); jaddnum(item,"price",op->price);
jaddnum(item,"volume",dstr(op->basesatoshis)); jaddnum(item,"volume",dstr(op->basesatoshis));
@ -513,35 +549,9 @@ int32_t LP_orderbookfind(struct LP_orderbookentry **array,int32_t num,bits256 tx
return(-1); return(-1);
} }
int32_t LP_utxo_clientpublish(struct LP_utxoinfo *utxo)
{
struct LP_peerinfo *peer,*tmp; cJSON *retjson; char *retstr; int32_t n = 0;
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
if ( (retstr= issue_LP_notifyutxo(peer->ipaddr,peer->port,utxo)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( jobj(retjson,"error") == 0 )
{
//if ( strcmp("HUSH",utxo->coin) == 0 )
// printf("clientpublish %s (%s)\n",peer->ipaddr,retstr);
utxo->T.lasttime = (uint32_t)time(NULL);
n++;
}
free_json(retjson);
}
free(retstr);
}
//if ( utxo->T.lasttime != 0 )
// return(0);
}
return(n);
}
int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *rel,struct LP_orderbookentry *(**arrayp),int32_t num,int32_t cachednum,int32_t duration) 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; 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;
if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 ) if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 )
baseid = basepp->ind; baseid = basepp->ind;
else return(num); else return(num);
@ -558,6 +568,8 @@ int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *
{ {
if ( LP_orderbookfind(*arrayp,cachednum,utxo->payment.txid,utxo->payment.vout) < 0 ) 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 ) if ( polarity > 0 )
basesatoshis = utxo->S.satoshis; basesatoshis = utxo->S.satoshis;
else basesatoshis = utxo->S.satoshis * price; else basesatoshis = utxo->S.satoshis * price;
@ -566,7 +578,7 @@ int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *
{ {
*arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1)); *arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1));
(*arrayp)[num++] = op; (*arrayp)[num++] = op;
if ( bits256_cmp(utxo->pubkey,LP_mypubkey) == 0 && utxo->T.lasttime == 0 ) if ( LP_ismine(utxo) > 0 && utxo->T.lasttime == 0 )
LP_utxo_clientpublish(utxo); LP_utxo_clientpublish(utxo);
} }
} }
@ -595,13 +607,13 @@ char *LP_orderbook(char *base,char *rel,int32_t duration)
qsort(bids,numbids,sizeof(*bids),_cmp_orderbook); qsort(bids,numbids,sizeof(*bids),_cmp_orderbook);
if ( numasks > 1 ) if ( numasks > 1 )
{ {
for (i=0; i<numasks; i++) //for (i=0; i<numasks; i++)
printf("%.8f ",asks[i]->price); // printf("%.8f ",asks[i]->price);
printf(" -> "); //printf(" -> ");
qsort(asks,numasks,sizeof(*asks),_cmp_orderbook); qsort(asks,numasks,sizeof(*asks),_cmp_orderbook);
for (i=0; i<numasks; i++) //for (i=0; i<numasks; i++)
printf("%.8f ",asks[i]->price); // printf("%.8f ",asks[i]->price);
printf("sorted asks.%d\n",numasks); //printf("sorted asks.%d\n",numasks);
} }
for (i=0; i<numbids; i++) for (i=0; i<numbids; i++)
{ {
@ -639,12 +651,12 @@ char *LP_pricestr(char *base,char *rel,double origprice)
if ( origprice > SMALLVAL && origprice < price ) if ( origprice > SMALLVAL && origprice < price )
price = origprice; price = origprice;
} }
if ( price > SMALLVAL ) if ( LP_pricevalid(price) > 0 )
{ {
retjson = cJSON_CreateObject(); retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success"); jaddstr(retjson,"result","success");
jaddstr(retjson,"method","postprice"); jaddstr(retjson,"method","postprice");
jaddbits256(retjson,"pubkey",LP_mypubkey); jaddbits256(retjson,"pubkey",LP_mypub25519);
jaddstr(retjson,"base",base); jaddstr(retjson,"base",base);
jaddstr(retjson,"rel",rel); jaddstr(retjson,"rel",rel);
jaddnum(retjson,"price",price); jaddnum(retjson,"price",price);
@ -659,21 +671,179 @@ void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveas
LP_priceinfoupdate(base,rel,price); LP_priceinfoupdate(base,rel,price);
} }
void LP_pricefname(char *fname,char *base,char *rel)
{
sprintf(fname,"%s/PRICES/%s_%s",GLOBAL_DBDIR,base,rel);
OS_compatible_path(fname);
}
void LP_priceitemadd(cJSON *retarray,uint32_t timestamp,double avebid,double aveask,double highbid,double lowask)
{
cJSON *item = cJSON_CreateArray();
jaddinum(item,timestamp);
jaddinum(item,avebid);
jaddinum(item,aveask);
jaddinum(item,highbid);
jaddinum(item,lowask);
jaddi(retarray,item);
}
cJSON *LP_pricearray(char *base,char *rel,uint32_t firsttime,uint32_t lasttime,int32_t timescale)
{
cJSON *retarray; char askfname[1024],bidfname[1024]; uint64_t bidprice64,askprice64; uint32_t bidnow,asknow,bidi,aski,lastbidi,lastaski; int32_t numbids,numasks; double bidemit,askemit,bidsum,asksum,bid,ask,highbid,lowbid,highask,lowask,bidemit2,askemit2; FILE *askfp=0,*bidfp=0;
if ( timescale <= 0 )
timescale = 60;
if ( lasttime == 0 )
lasttime = (uint32_t)-1;
LP_pricefname(askfname,base,rel);
LP_pricefname(bidfname,rel,base);
retarray = cJSON_CreateArray();
lastbidi = lastaski = 0;
numbids = numasks = 0;
bidsum = asksum = askemit = bidemit = highbid = lowbid = highask = lowask = 0.;
if ( (bidfp= fopen(bidfname,"rb")) != 0 && (askfp= fopen(askfname,"rb")) != 0 )
{
while ( bidfp != 0 || askfp != 0 )
{
bidi = aski = 0;
bidemit = askemit = bidemit2 = askemit2 = 0.;
if ( bidfp != 0 && fread(&bidnow,1,sizeof(bidnow),bidfp) == sizeof(bidnow) && fread(&bidprice64,1,sizeof(bidprice64),bidfp) == sizeof(bidprice64) )
{
//printf("bidnow.%u %.8f\n",bidnow,dstr(bidprice64));
if ( bidnow != 0 && bidprice64 != 0 && bidnow >= firsttime && bidnow <= lasttime )
{
bidi = bidnow / timescale;
if ( bidi != lastbidi )
{
if ( bidsum != 0. && numbids != 0 )
{
bidemit = bidsum / numbids;
bidemit2 = highbid;
}
bidsum = highbid = lowbid = 0.;
numbids = 0;
}
if ( (bid= 1. / dstr(bidprice64)) != 0. )
{
if ( bid > highbid )
highbid = bid;
if ( lowbid == 0. || bid < lowbid )
lowbid = bid;
bidsum += bid;
numbids++;
//printf("bidi.%u num.%d %.8f [%.8f %.8f]\n",bidi,numbids,bid,lowbid,highbid);
}
}
} else fclose(bidfp), bidfp = 0;
if ( askfp != 0 && fread(&asknow,1,sizeof(asknow),askfp) == sizeof(asknow) && fread(&askprice64,1,sizeof(askprice64),askfp) == sizeof(askprice64) )
{
//printf("asknow.%u %.8f\n",asknow,dstr(askprice64));
if ( asknow != 0 && askprice64 != 0 && asknow >= firsttime && asknow <= lasttime )
{
aski = asknow / timescale;
if ( aski != lastaski )
{
if ( asksum != 0. && numasks != 0 )
{
askemit = asksum / numasks;
askemit2 = lowask;
}
asksum = highask = lowask = 0.;
numasks = 0;
}
if ( (ask= dstr(askprice64)) != 0. )
{
if ( ask > highask )
highask = ask;
if ( lowask == 0. || ask < lowask )
lowask = ask;
asksum += ask;
numasks++;
//printf("aski.%u num.%d %.8f [%.8f %.8f]\n",aski,numasks,ask,lowask,highask);
}
}
} else fclose(askfp), askfp = 0;
if ( bidemit != 0. || askemit != 0. )
{
if ( bidemit != 0. && askemit != 0. && lastbidi == lastaski )
{
LP_priceitemadd(retarray,lastbidi * timescale,bidemit,askemit,bidemit2,askemit2);
highbid = lowbid = highask = lowask = 0.;
}
else
{
if ( bidemit != 0. )
{
printf("bidonly %.8f %.8f\n",bidemit,highbid);
LP_priceitemadd(retarray,lastbidi * timescale,bidemit,0.,bidemit2,0.);
highbid = lowbid = 0.;
}
if ( askemit != 0. )
{
printf("askonly %.8f %.8f\n",askemit,lowask);
LP_priceitemadd(retarray,lastaski * timescale,0.,askemit,0.,askemit2);
highask = lowask = 0.;
}
}
}
if ( bidi != 0 )
lastbidi = bidi;
if ( aski != 0 )
lastaski = aski;
}
} else printf("couldnt open either %s %p or %s %p\n",bidfname,bidfp,askfname,askfp);
if ( bidfp != 0 )
fclose(bidfp);
if ( askfp != 0 )
fclose(askfp);
return(retarray);
}
void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price) void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price)
{ {
struct LP_priceinfo *basepp,*relpp; struct LP_pubkeyinfo *pubp; char str[65]; struct LP_priceinfo *basepp,*relpp; uint32_t now; uint64_t price64; struct LP_pubkeyinfo *pubp; char str[65],fname[512]; FILE *fp;
if ( price > SMALLVAL && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) //printf("check PRICEFEED UPDATE.(%s/%s) %.8f %s\n",base,rel,price,bits256_str(str,pubkey));
if ( LP_pricevalid(price) > 0 && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{ {
printf("PRICEFEED UPDATE.(%s/%s) %.8f %s\n",base,rel,price,bits256_str(str,pubkey)); if ( (fp= basepp->fps[relpp->ind]) == 0 )
{
LP_pricefname(fname,base,rel);
fp = basepp->fps[relpp->ind] = OS_appendfile(fname);
}
if ( fp != 0 )
{
now = (uint32_t)time(NULL);
price64 = price * SATOSHIDEN;
fwrite(&now,1,sizeof(now),fp);
fwrite(&price64,1,sizeof(price64),fp);
fflush(fp);
}
if ( (fp= relpp->fps[basepp->ind]) == 0 )
{
sprintf(fname,"%s/PRICES/%s_%s",GLOBAL_DBDIR,rel,base);
fp = relpp->fps[basepp->ind] = OS_appendfile(fname);
}
if ( fp != 0 )
{
now = (uint32_t)time(NULL);
price64 = (1. / price) * SATOSHIDEN;
fwrite(&now,1,sizeof(now),fp);
fwrite(&price64,1,sizeof(price64),fp);
fflush(fp);
}
if ( (pubp= LP_pubkeyadd(pubkey)) != 0 ) if ( (pubp= LP_pubkeyadd(pubkey)) != 0 )
{ {
pubp->matrix[basepp->ind][relpp->ind] = price; 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);
{
pubp->matrix[basepp->ind][relpp->ind] = price;
dxblend(&basepp->relvals[relpp->ind],price,0.9);
dxblend(&relpp->relvals[basepp->ind],1. / price,0.9);
}
pubp->timestamp = (uint32_t)time(NULL); pubp->timestamp = (uint32_t)time(NULL);
} else printf("error creating pubkey entry\n"); } else printf("error creating pubkey entry\n");
} else printf("error finding %s/%s %.8f\n",base,rel,price); }
else if ( (rand() % 100) == 0 )
printf("error finding %s/%s %.8f\n",base,rel,price);
} }

98
iguana/exchanges/LP_remember.c

@ -93,7 +93,7 @@ void basilisk_dontforget(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx
sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid), OS_compatible_path(fname); sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid), OS_compatible_path(fname);
if ( (fp= fopen(fname,"wb")) != 0 ) if ( (fp= fopen(fname,"wb")) != 0 )
{ {
fprintf(fp,"{\"src\":\"%s\",\"srcamount\":%.8f,\"dest\":\"%s\",\"destamount\":%.8f,\"requestid\":%u,\"quoteid\":%u,\"iambob\":%d,\"state\":%u,\"otherstate\":%u,\"expiration\":%u,\"dlocktime\":%u,\"plocktime\":%u",swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount),swap->I.req.requestid,swap->I.req.quoteid,swap->I.iambob,swap->I.statebits,swap->I.otherstatebits,swap->I.expiration,swap->bobdeposit.I.locktime,swap->bobpayment.I.locktime); fprintf(fp,"{\"src\":\"%s\",\"srcamount\":%.8f,\"dest\":\"%s\",\"destamount\":%.8f,\"requestid\":%u,\"quoteid\":%u,\"iambob\":%d,\"state\":%u,\"otherstate\":%u,\"expiration\":%u,\"dlocktime\":%u,\"plocktime\":%u,\"Atxfee\":%llu,\"Btxfee\":%llu",swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount),swap->I.req.requestid,swap->I.req.quoteid,swap->I.iambob,swap->I.statebits,swap->I.otherstatebits,swap->I.expiration,swap->bobdeposit.I.locktime,swap->bobpayment.I.locktime,(long long)swap->I.Atxfee,(long long)swap->I.Btxfee);
if ( memcmp(zeroes,swap->I.secretAm,20) != 0 ) if ( memcmp(zeroes,swap->I.secretAm,20) != 0 )
{ {
init_hexbytes_noT(secretAmstr,swap->I.secretAm,20); init_hexbytes_noT(secretAmstr,swap->I.secretAm,20);
@ -264,12 +264,14 @@ bits256 basilisk_swap_spendupdate(char *symbol,int32_t *sentflags,bits256 *txids
{ {
//printf("ALICE spent.(%s) -> %s\n",bits256_str(str,txid),destaddr); //printf("ALICE spent.(%s) -> %s\n",bits256_str(str,txid),destaddr);
sentflags[alicespent] = 1; sentflags[alicespent] = 1;
sentflags[bobspent] = 0;
txids[alicespent] = spendtxid; txids[alicespent] = spendtxid;
} }
else if ( bobaddr != 0 && strcmp(destaddr,bobaddr) == 0 ) else if ( bobaddr != 0 && strcmp(destaddr,bobaddr) == 0 )
{ {
//printf("BOB spent.(%s) -> %s\n",bits256_str(str,txid),destaddr); //printf("BOB spent.(%s) -> %s\n",bits256_str(str,txid),destaddr);
sentflags[bobspent] = 1; sentflags[bobspent] = 1;
sentflags[alicespent] = 0;
txids[bobspent] = spendtxid; txids[bobspent] = spendtxid;
} }
else else
@ -278,11 +280,13 @@ bits256 basilisk_swap_spendupdate(char *symbol,int32_t *sentflags,bits256 *txids
if ( aliceaddr != 0 ) if ( aliceaddr != 0 )
{ {
sentflags[bobspent] = 1; sentflags[bobspent] = 1;
sentflags[alicespent] = 0;
txids[bobspent] = spendtxid; txids[bobspent] = spendtxid;
} }
else if ( bobaddr != 0 ) else if ( bobaddr != 0 )
{ {
sentflags[alicespent] = 1; sentflags[alicespent] = 1;
sentflags[bobspent] = 0;
txids[alicespent] = spendtxid; txids[alicespent] = spendtxid;
} }
} }
@ -365,13 +369,43 @@ int32_t basilisk_swap_isfinished(int32_t iambob,bits256 *txids,int32_t *sentflag
return(0); return(0);
} }
uint32_t LP_extract(uint32_t requestid,uint32_t quoteid,char *rootfname,char *field)
{
char fname[1024],*filestr,*redeemstr; long fsize; int32_t len; uint32_t t=0; cJSON *json; uint8_t redeem[1024];
if ( strcmp(field,"dlocktime") == 0 )
sprintf(fname,"%s.bobdeposit",rootfname);
else if ( strcmp(field,"plocktime") == 0 )
sprintf(fname,"%s.bobpayment",rootfname);
if ( (filestr= OS_filestr(&fsize,fname)) != 0 )
{
if ( (json= cJSON_Parse(filestr)) != 0 )
{
if ( (redeemstr= jstr(json,"redeem")) != 0 && (len= (int32_t)strlen(redeemstr)) <= sizeof(redeem)*2 )
{
len >>= 1;
decode_hex(redeem,len,redeemstr);
t = redeem[5];
t = (t << 8) | redeem[4];
t = (t << 8) | redeem[3];
t = (t << 8) | redeem[2];
//printf("extracted timestamp.%u\n",t);
}
}
free(filestr);
}
return(t);
}
cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requestid,uint32_t quoteid) cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requestid,uint32_t quoteid)
{ {
static void *ctx; static void *ctx;
FILE *fp; int32_t sentflags[sizeof(txnames)/sizeof(*txnames)],i,n,j,len,needflag,secretstart,redeemlen,addflag,origfinishedflag = 0,finishedflag = 0,iambob = -1; int64_t srcamount,destamount=0,value,values[sizeof(txnames)/sizeof(*txnames)]; uint8_t secretAm[20],secretAm256[32],secretBn[20],secretBn256[32],pubkey33[33],redeemscript[1024],userdata[1024]; uint32_t plocktime,dlocktime,expiration=0,r,q,state,otherstate; char *secretstr,*srcstr,*deststr,str[65],src[64],dest[64],fname[512],*fstr,*dest33,*symbol,*txname,*Adest,*Bdest,*AAdest,*ABdest,destaddr[64],Adestaddr[64],alicepaymentaddr[64],bobpaymentaddr[64],bobdepositaddr[64],alicecoin[64],bobcoin[64],*txbytes[sizeof(txnames)/sizeof(*txnames)]; long fsize; cJSON *txobj,*item,*sentobj,*array; bits256 checktxid,txid,pubA0,pubB0,pubB1,privAm,privBn,paymentspent,Apaymentspent,depositspent,zero,privkey,rev,myprivs[2],txids[sizeof(txnames)/sizeof(*txnames)],signedtxid; struct iguana_info *bob=0,*alice=0; uint64_t txfee = 10000; FILE *fp; int32_t sentflags[sizeof(txnames)/sizeof(*txnames)],i,n,j,Predeemlen,Dredeemlen,len,needflag,secretstart,redeemlen,addflag,origfinishedflag = 0,finishedflag = 0,iambob = -1; int64_t srcamount,destamount=0,value,values[sizeof(txnames)/sizeof(*txnames)]; uint8_t secretAm[20],secretAm256[32],secretBn[20],secretBn256[32],pubkey33[33],Predeemscript[1024],Dredeemscript[1024],redeemscript[1024],userdata[1024]; uint32_t plocktime,dlocktime,expiration=0,r,q,state,otherstate; char *secretstr,*srcstr,*deststr,str[65],src[64],dest[64],fname[512],*fstr,*dest33,*rstr,*symbol,*txname,*Adest,*Bdest,*AAdest,*ABdest,destaddr[64],Adestaddr[64],alicepaymentaddr[64],bobpaymentaddr[64],bobdepositaddr[64],alicecoin[64],bobcoin[64],*txbytes[sizeof(txnames)/sizeof(*txnames)]; long fsize; cJSON *txobj,*item,*sentobj,*array; bits256 checktxid,txid,pubA0,pubB0,pubB1,privAm,privBn,paymentspent,Apaymentspent,depositspent,zero,privkey,rev,myprivs[2],txids[sizeof(txnames)/sizeof(*txnames)],signedtxid; struct iguana_info *bob=0,*alice=0; uint64_t Atxfee=0,Btxfee=0;
if ( ctx == 0 ) if ( ctx == 0 )
ctx = bitcoin_ctx(); ctx = bitcoin_ctx();
bobpaymentaddr[0] = bobdepositaddr[0] = alicepaymentaddr[0] = 0; bobpaymentaddr[0] = bobdepositaddr[0] = alicepaymentaddr[0] = 0;
memset(Predeemscript,0,sizeof(Predeemscript));
memset(Dredeemscript,0,sizeof(Dredeemscript));
Predeemlen = Dredeemlen = 0;
memset(values,0,sizeof(values)); memset(values,0,sizeof(values));
memset(txids,0,sizeof(txids)); memset(txids,0,sizeof(txids));
memset(secretAm,0,sizeof(secretAm)); memset(secretAm,0,sizeof(secretAm));
@ -410,10 +444,14 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
// printf("%02x",pubkey33[i]); // printf("%02x",pubkey33[i]);
//printf(" <- %s dest33\n",dest33); //printf(" <- %s dest33\n",dest33);
} }
plocktime = juint(item,"plocktime"); if ( (plocktime= juint(item,"plocktime")) == 0 )
dlocktime = juint(item,"dlocktime"); plocktime = LP_extract(requestid,quoteid,fname,"plocktime");
if ( (dlocktime= juint(item,"dlocktime")) == 0 )
dlocktime = LP_extract(requestid,quoteid,fname,"dlocktime");
r = juint(item,"requestid"); r = juint(item,"requestid");
q = juint(item,"quoteid"); q = juint(item,"quoteid");
Atxfee = j64bits(item,"Atxfee");
Btxfee = j64bits(item,"Btxfee");
pubA0 = jbits256(item,"pubA0"); pubA0 = jbits256(item,"pubA0");
pubB0 = jbits256(item,"pubB0"); pubB0 = jbits256(item,"pubB0");
pubB1 = jbits256(item,"pubB1"); pubB1 = jbits256(item,"pubB1");
@ -497,7 +535,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
sprintf(fname,"%s/SWAPS/%u-%u.%s",GLOBAL_DBDIR,requestid,quoteid,txnames[i]), OS_compatible_path(fname); sprintf(fname,"%s/SWAPS/%u-%u.%s",GLOBAL_DBDIR,requestid,quoteid,txnames[i]), OS_compatible_path(fname);
if ( (fstr= OS_filestr(&fsize,fname)) != 0 ) if ( (fstr= OS_filestr(&fsize,fname)) != 0 )
{ {
if ( finishedflag == 0 ) if ( 0 && finishedflag == 0 )
printf("%s\n",fname); printf("%s\n",fname);
//printf("%s -> (%s)\n",fname,fstr); //printf("%s -> (%s)\n",fname,fstr);
if ( (txobj= cJSON_Parse(fstr)) != 0 ) if ( (txobj= cJSON_Parse(fstr)) != 0 )
@ -519,6 +557,16 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
txbytes[i] = clonestr(jstr(txobj,"tx")); txbytes[i] = clonestr(jstr(txobj,"tx"));
//printf("[%s] TX.(%s)\n",txnames[i],txbytes[i]); //printf("[%s] TX.(%s)\n",txnames[i],txbytes[i]);
} }
if ( strcmp(txnames[i],"bobpayment") == 0 && (rstr= jstr(txobj,"redeem")) != 0 && (Predeemlen= is_hexstr(rstr,0)) > 0 )
{
Predeemlen >>= 1;
decode_hex(Predeemscript,Predeemlen,rstr);
}
else if ( strcmp(txnames[i],"bobdeposit") == 0 && (rstr= jstr(txobj,"redeem")) != 0 && (Dredeemlen= is_hexstr(rstr,0)) > 0 )
{
Dredeemlen >>= 1;
decode_hex(Dredeemscript,Dredeemlen,rstr);
}
if ( (value= jdouble(txobj,"amount") * SATOSHIDEN) == 0 ) if ( (value= jdouble(txobj,"amount") * SATOSHIDEN) == 0 )
value = jdouble(txobj,"value") * SATOSHIDEN; value = jdouble(txobj,"value") * SATOSHIDEN;
values[i] = value; values[i] = value;
@ -552,12 +600,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
} }
free_json(sentobj); free_json(sentobj);
} }
printf("%s %s %.8f\n",txnames[i],bits256_str(str,txid),dstr(value)); if ( finishedflag == 0 )
printf("%s %s %.8f\n",txnames[i],bits256_str(str,txid),dstr(value));
} }
} }
} //else printf("no symbol\n"); } //else printf("no symbol\n");
free(fstr); free(fstr);
} else if ( finishedflag == 0 ) } else if ( 0 && finishedflag == 0 )
printf("%s not finished\n",fname); printf("%s not finished\n",fname);
} }
//printf("alicepayment.%s bobpayment.%s bobdeposit.%s\n",alicepaymentaddr,bobpaymentaddr,bobdepositaddr); //printf("alicepayment.%s bobpayment.%s bobdeposit.%s\n",alicepaymentaddr,bobpaymentaddr,bobdepositaddr);
@ -566,6 +615,9 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
Adest = Bdest = AAdest = ABdest = 0; Adest = Bdest = AAdest = ABdest = 0;
if ( bobcoin[0] == 0 || alicecoin[0] == 0 ) if ( bobcoin[0] == 0 || alicecoin[0] == 0 )
return(0); return(0);
Atxfee = LP_txfeecalc(alicecoin,Atxfee);
Btxfee = LP_txfeecalc(bobcoin,Btxfee);
//printf("%s %.8f txfee, %s %.8f txfee\n",alicecoin,dstr(Atxfee),bobcoin,dstr(Btxfee));
//printf("privAm.(%s) %p/%p\n",bits256_str(str,privAm),Adest,AAdest); //printf("privAm.(%s) %p/%p\n",bits256_str(str,privAm),Adest,AAdest);
//printf("privBn.(%s) %p/%p\n",bits256_str(str,privBn),Bdest,ABdest); //printf("privBn.(%s) %p/%p\n",bits256_str(str,privBn),Bdest,ABdest);
if ( finishedflag == 0 && bobcoin[0] != 0 && alicecoin[0] != 0 ) if ( finishedflag == 0 && bobcoin[0] != 0 && alicecoin[0] != 0 )
@ -596,6 +648,16 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
ABdest = Adestaddr; ABdest = Adestaddr;
} }
} }
if ( bob == 0 || alice == 0 )
{
printf("Bob.%p is null or Alice.%p is null\n",bob,alice);
return(0);
}
if ( alice->inactive != 0 || bob->inactive != 0 )
{
printf("Alice.%s inactive.%u or Bob.%s inactive.%u\n",alicecoin,alice->inactive,bobcoin,bob->inactive);
return(0);
}
if ( sentflags[BASILISK_ALICEPAYMENT] == 0 && bits256_nonz(txids[BASILISK_ALICEPAYMENT]) != 0 ) if ( sentflags[BASILISK_ALICEPAYMENT] == 0 && bits256_nonz(txids[BASILISK_ALICEPAYMENT]) != 0 )
{ {
printf("txbytes.%p Apayment.%s\n",txbytes[BASILISK_ALICEPAYMENT],bits256_str(str,txids[BASILISK_ALICEPAYMENT])); printf("txbytes.%p Apayment.%s\n",txbytes[BASILISK_ALICEPAYMENT],bits256_str(str,txids[BASILISK_ALICEPAYMENT]));
@ -626,7 +688,9 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
rev.bytes[j] = privAm.bytes[31 - j]; rev.bytes[j] = privAm.bytes[31 - j];
//revcalc_rmd160_sha256(secretAm,rev);//privAm); //revcalc_rmd160_sha256(secretAm,rev);//privAm);
//vcalc_sha256(0,secretAm256,rev.bytes,sizeof(rev)); //vcalc_sha256(0,secretAm256,rev.bytes,sizeof(rev));
redeemlen = basilisk_swap_bobredeemscript(0,&secretstart,redeemscript,plocktime,pubA0,pubB0,pubB1,rev,privBn,secretAm,secretAm256,secretBn,secretBn256); if ( Predeemlen != 0 )
redeemlen = Predeemlen, memcpy(redeemscript,Predeemscript,Predeemlen);
else redeemlen = basilisk_swap_bobredeemscript(0,&secretstart,redeemscript,plocktime,pubA0,pubB0,pubB1,rev,privBn,secretAm,secretAm256,secretBn,secretBn256);
len = basilisk_swapuserdata(userdata,rev,0,myprivs[0],redeemscript,redeemlen); len = basilisk_swapuserdata(userdata,rev,0,myprivs[0],redeemscript,redeemlen);
{ {
char privaddr[64]; uint8_t privpub33[33]; char privaddr[64]; uint8_t privpub33[33];
@ -636,7 +700,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
} }
for (j=0; j<32; j++) for (j=0; j<32; j++)
rev.bytes[j] = myprivs[0].bytes[31 - j]; rev.bytes[j] = myprivs[0].bytes[31 - j];
if ( (txbytes[BASILISK_ALICESPEND]= basilisk_swap_bobtxspend(&signedtxid,txfee,"alicespend",bobcoin,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,0,pubkey33,1,expiration,&values[BASILISK_ALICESPEND],0,0,bobpaymentaddr,1)) != 0 ) if ( (txbytes[BASILISK_ALICESPEND]= basilisk_swap_bobtxspend(&signedtxid,Btxfee,"alicespend",bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,0,pubkey33,1,expiration,&values[BASILISK_ALICESPEND],0,0,bobpaymentaddr,1)) != 0 )
printf("alicespend.(%s)\n",txbytes[BASILISK_ALICESPEND]); printf("alicespend.(%s)\n",txbytes[BASILISK_ALICESPEND]);
} }
} }
@ -657,11 +721,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
{ {
//if ( txbytes[BASILISK_ALICECLAIM] == 0 ) //if ( txbytes[BASILISK_ALICECLAIM] == 0 )
{ {
redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,dlocktime,pubA0,pubB0,pubB1,privAm,zero,secretAm,secretAm256,secretBn,secretBn256); if ( Dredeemlen != 0 )
redeemlen = Dredeemlen, memcpy(redeemscript,Dredeemscript,Dredeemlen);
else redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,dlocktime,pubA0,pubB0,pubB1,privAm,zero,secretAm,secretAm256,secretBn,secretBn256);
if ( redeemlen > 0 ) if ( redeemlen > 0 )
{ {
len = basilisk_swapuserdata(userdata,zero,1,myprivs[0],redeemscript,redeemlen); len = basilisk_swapuserdata(userdata,zero,1,myprivs[0],redeemscript,redeemlen);
if ( (txbytes[BASILISK_ALICECLAIM]= basilisk_swap_bobtxspend(&signedtxid,txfee,"aliceclaim",bobcoin,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,0,pubkey33,0,expiration,&values[BASILISK_ALICECLAIM],0,0,bobdepositaddr,1)) != 0 ) if ( (txbytes[BASILISK_ALICECLAIM]= basilisk_swap_bobtxspend(&signedtxid,Btxfee,"aliceclaim",bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,0,pubkey33,0,expiration,&values[BASILISK_ALICECLAIM],0,0,bobdepositaddr,1)) != 0 )
printf("privBn.(%s) aliceclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICECLAIM]); printf("privBn.(%s) aliceclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICECLAIM]);
} }
} }
@ -683,7 +749,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
privBn = basilisk_swap_privBn_extract(&txids[BASILISK_BOBREFUND],bobcoin,txids[BASILISK_BOBDEPOSIT],privBn); privBn = basilisk_swap_privBn_extract(&txids[BASILISK_BOBREFUND],bobcoin,txids[BASILISK_BOBDEPOSIT],privBn);
if ( bits256_nonz(txids[BASILISK_ALICEPAYMENT]) != 0 && bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 ) if ( bits256_nonz(txids[BASILISK_ALICEPAYMENT]) != 0 && bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 )
{ {
if ( (txbytes[BASILISK_ALICERECLAIM]= basilisk_swap_Aspend("alicereclaim",alicecoin,alice->taddr,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_ALICERECLAIM],alicepaymentaddr)) != 0 ) if ( (txbytes[BASILISK_ALICERECLAIM]= basilisk_swap_Aspend("alicereclaim",alicecoin,Atxfee,alice->wiftaddr,alice->taddr,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_ALICERECLAIM],alicepaymentaddr)) != 0 )
printf("privBn.(%s) alicereclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICERECLAIM]); printf("privBn.(%s) alicereclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICERECLAIM]);
} }
} }
@ -713,7 +779,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
} }
if ( bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 ) if ( bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 )
{ {
if ( (txbytes[BASILISK_BOBSPEND]= basilisk_swap_Aspend("bobspend",alicecoin,alice->taddr,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_BOBSPEND],alicepaymentaddr)) != 0 ) if ( (txbytes[BASILISK_BOBSPEND]= basilisk_swap_Aspend("bobspend",alicecoin,Atxfee,alice->wiftaddr,alice->taddr,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_BOBSPEND],alicepaymentaddr)) != 0 )
printf("bobspend.(%s)\n",txbytes[BASILISK_BOBSPEND]); printf("bobspend.(%s)\n",txbytes[BASILISK_BOBSPEND]);
} }
} }
@ -737,7 +803,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
if ( redeemlen > 0 ) if ( redeemlen > 0 )
{ {
len = basilisk_swapuserdata(userdata,zero,1,myprivs[1],redeemscript,redeemlen); len = basilisk_swapuserdata(userdata,zero,1,myprivs[1],redeemscript,redeemlen);
if ( (txbytes[BASILISK_BOBRECLAIM]= basilisk_swap_bobtxspend(&signedtxid,txfee,"bobrefund",bobcoin,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[1],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,0,pubkey33,0,expiration,&values[BASILISK_BOBRECLAIM],0,0,bobpaymentaddr,1)) != 0 ) if ( (txbytes[BASILISK_BOBRECLAIM]= basilisk_swap_bobtxspend(&signedtxid,Btxfee,"bobrefund",bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[1],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,0,pubkey33,0,expiration,&values[BASILISK_BOBRECLAIM],0,0,bobpaymentaddr,1)) != 0 )
{ {
int32_t z; int32_t z;
for (z=0; z<20; z++) for (z=0; z<20; z++)
@ -767,7 +833,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
vcalc_sha256(0,secretBn256,privBn.bytes,sizeof(privBn)); vcalc_sha256(0,secretBn256,privBn.bytes,sizeof(privBn));
redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,dlocktime,pubA0,pubB0,pubB1,privAm,privBn,secretAm,secretAm256,secretBn,secretBn256); redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,dlocktime,pubA0,pubB0,pubB1,privAm,privBn,secretAm,secretAm256,secretBn,secretBn256);
len = basilisk_swapuserdata(userdata,privBn,0,myprivs[0],redeemscript,redeemlen); len = basilisk_swapuserdata(userdata,privBn,0,myprivs[0],redeemscript,redeemlen);
if ( (txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend(&signedtxid,txfee,"bobrefund",bobcoin,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,0,pubkey33,1,expiration,&values[BASILISK_BOBREFUND],0,0,bobdepositaddr,1)) != 0 ) if ( (txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend(&signedtxid,Btxfee,"bobrefund",bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,0,pubkey33,1,expiration,&values[BASILISK_BOBREFUND],0,0,bobdepositaddr,1)) != 0 )
printf("pubB1.(%s) bobrefund.(%s)\n",bits256_str(str,pubB1),txbytes[BASILISK_BOBREFUND]); printf("pubB1.(%s) bobrefund.(%s)\n",bits256_str(str,pubB1),txbytes[BASILISK_BOBREFUND]);
} }
if ( txbytes[BASILISK_BOBREFUND] != 0 ) if ( txbytes[BASILISK_BOBREFUND] != 0 )
@ -779,7 +845,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
depositspent = txids[BASILISK_BOBREFUND]; depositspent = txids[BASILISK_BOBREFUND];
} }
} }
} else printf("time %u vs expiration %u\n",(uint32_t)time(NULL),expiration); } else printf("bobrefund's time %u vs expiration %u\n",(uint32_t)time(NULL),expiration);
} }
} }
} }

209
iguana/exchanges/LP_rpc.c

@ -48,17 +48,28 @@ char *LP_isitme(char *destip,uint16_t destport)
} else return(0); } else return(0);
} }
char *issue_LP_getpeers(char *destip,uint16_t destport,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos) char *issue_LP_getpeers(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers,int32_t numutxos)
{ {
char url[512]; char url[512],*retstr;
sprintf(url,"http://%s:%u/api/stats/getpeers?ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,profitmargin,numpeers,numutxos); sprintf(url,"http://%s:%u/api/stats/getpeers?ipaddr=%s&port=%u&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,numpeers,numutxos);
return(LP_issue_curl("getpeers",destip,port,url)); 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 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);
return(retstr);
} }
char *issue_LP_getutxos(char *destip,uint16_t destport,char *coin,int32_t lastn,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos) char *issue_LP_getutxos(char *destip,uint16_t destport,char *coin,int32_t lastn,char *ipaddr,uint16_t port,int32_t numpeers,int32_t numutxos)
{ {
char url[512]; char url[512];
sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,coin,lastn,ipaddr,port,profitmargin,numpeers,numutxos); sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=%s&port=%u&numpeers=%d&numutxos=%d",destip,destport,coin,lastn,ipaddr,port,numpeers,numutxos);
return(LP_issue_curl("getutxos",destip,destport,url)); return(LP_issue_curl("getutxos",destip,destport,url));
//return(issue_curlt(url,LP_HTTP_TIMEOUT)); //return(issue_curlt(url,LP_HTTP_TIMEOUT));
} }
@ -73,104 +84,16 @@ char *issue_LP_clientgetutxos(char *destip,uint16_t destport,char *coin,int32_t
//return(retstr); //return(retstr);
} }
change to nanomsg write only, enforce fee, comms api char *issue_LP_notify(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers,int32_t numutxos,uint32_t sessionid)
char *issue_LP_notify(char *destip,uint16_t destport,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos)
{ {
char url[512],*retstr; char url[512],*retstr;
if ( (retstr= LP_isitme(destip,destport)) != 0 ) if ( (retstr= LP_isitme(destip,destport)) != 0 )
{ return(retstr);
free(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);
return(0);
}
sprintf(url,"http://%s:%u/api/stats/notify?ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,profitmargin,numpeers,numutxos);
return(LP_issue_curl("notify",destip,destport,url)); return(LP_issue_curl("notify",destip,destport,url));
//return(issue_curlt(url,LP_HTTP_TIMEOUT)); //return(issue_curlt(url,LP_HTTP_TIMEOUT));
} }
char *issue_LP_notifyutxo(char *destip,uint16_t destport,struct LP_utxoinfo *utxo)
{
char url[4096],str[65],str2[65],str3[65],*retstr; struct _LP_utxoinfo u; uint64_t val,val2;
if ( (retstr= LP_isitme(destip,destport)) != 0 )
{
free(retstr);
return(0);
}
if ( utxo->iambob == 0 )
{
printf("issue_LP_notifyutxo trying to send Alice %s/v%d\n",bits256_str(str,utxo->payment.txid),utxo->payment.vout);
return(0);
}
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee;
if ( LP_iseligible(&val,&val2,utxo->iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,u.txid,u.vout,utxo->pubkey) > 0 )
{
sprintf(url,"http://%s:%u/api/stats/notified?iambob=%d&pubkey=%s&profit=%.6f&coin=%s&txid=%s&vout=%d&value=%llu&txid2=%s&vout2=%d&value2=%llu&script=%s&address=%s&timestamp=%u&gui=%s",destip,destport,utxo->iambob,bits256_str(str3,utxo->pubkey),utxo->S.profitmargin,utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout,(long long)utxo->payment.value,bits256_str(str2,utxo->deposit.txid),utxo->deposit.vout,(long long)utxo->deposit.value,utxo->spendscript,utxo->coinaddr,(uint32_t)time(NULL),utxo->gui);
if ( strlen(url) > 1024 )
printf("WARNING long url.(%s)\n",url);
return(LP_issue_curl("notifyutxo",destip,destport,url));
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
}
else
{
printf("issue_LP_notifyutxo: ineligible utxo iambob.%d %.8f %.8f\n",utxo->iambob,dstr(val),dstr(val2));
return(0);
}
}
/*char *issue_LP_register(char *destip,uint16_t destport,bits256 pubkey,char *ipaddr,uint16_t pushport)
{
char url[512],str[65],*retstr;
sprintf(url,"http://%s:%u/api/stats/register?client=%s&pushaddr=%s&pushport=%u",destip,destport,bits256_str(str,pubkey),ipaddr,pushport);
//return(LP_issue_curl("register",destip,destport,url));
retstr = issue_curlt(url,LP_HTTP_TIMEOUT);
//printf("register.(%s) -> (%s)\n",url,retstr!=0?retstr:"");
return(retstr);
}*/
char *issue_LP_psock(char *destip,uint16_t destport,int32_t ispaired)
{
char url[512],*retstr;
sprintf(url,"http://%s:%u/api/stats/psock?ispaired=%d",destip,destport,ispaired);
//return(LP_issue_curl("psock",destip,destport,url));
retstr = issue_curlt(url,LP_HTTP_TIMEOUT*3);
return(retstr);
}
uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired)
{
uint16_t publicport = 0; char *retstr,*addr; cJSON *retjson; struct LP_peerinfo *peer,*tmp;
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
connectaddr[0] = publicaddr[0] = 0;
if ( peer->errors < LP_MAXPEER_ERRORS && (retstr= issue_LP_psock(peer->ipaddr,peer->port,ispaired)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (addr= jstr(retjson,"publicaddr")) != 0 )
safecopy(publicaddr,addr,128);
if ( (addr= jstr(retjson,"connectaddr")) != 0 )
safecopy(connectaddr,addr,128);
if ( publicaddr[0] != 0 && connectaddr[0] != 0 )
publicport = juint(retjson,"publicport");
free_json(retjson);
}
printf("got.(%s) connect.%s public.%s\n",retstr,connectaddr,publicaddr);
free(retstr);
}
if ( publicport != 0 )
break;
}
return(publicport);
}
char *issue_LP_lookup(char *destip,uint16_t destport,bits256 pubkey)
{
char url[512],str[65];
sprintf(url,"http://%s:%u/api/stats/lookup?client=%s",destip,destport,bits256_str(str,pubkey));
//printf("getutxo.(%s)\n",url);
return(LP_issue_curl("lookup",destip,destport,url));
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
}
char *issue_LP_getprices(char *destip,uint16_t destport) char *issue_LP_getprices(char *destip,uint16_t destport)
{ {
char url[512]; char url[512];
@ -186,7 +109,7 @@ cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params)
if ( coin != 0 ) if ( coin != 0 )
{ {
//printf("issue.(%s, %s, %s, %s, %s)\n",coin->symbol,coin->serverport,coin->userpass,method,params); //printf("issue.(%s, %s, %s, %s, %s)\n",coin->symbol,coin->serverport,coin->userpass,method,params);
if ( coin->inactive == 0 || strcmp(method,"importprivkey") == 0 ) if ( coin->inactive == 0 || strcmp(method,"importprivkey") == 0 || strcmp(method,"validateaddress") == 0 )
{ {
retstr = bitcoind_passthru(coin->symbol,coin->serverport,coin->userpass,method,params); retstr = bitcoind_passthru(coin->symbol,coin->serverport,coin->userpass,method,params);
if ( retstr != 0 && retstr[0] != 0 ) if ( retstr != 0 && retstr[0] != 0 )
@ -195,7 +118,7 @@ cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params)
retjson = cJSON_Parse(retstr); retjson = cJSON_Parse(retstr);
free(retstr); free(retstr);
} }
//usleep(1000); //usleep(100);
//printf("dpow_gettxout.(%s)\n",retstr); //printf("dpow_gettxout.(%s)\n",retstr);
} else retjson = cJSON_Parse("{\"result\":\"disabled\"}"); } else retjson = cJSON_Parse("{\"result\":\"disabled\"}");
} else printf("bitcoin_json cant talk to NULL coin\n"); } else printf("bitcoin_json cant talk to NULL coin\n");
@ -207,6 +130,39 @@ void LP_unspents_mark(char *symbol,cJSON *vins)
printf("LOCK (%s)\n",jprint(vins,0)); printf("LOCK (%s)\n",jprint(vins,0));
} }
char *NXTnodes[] = { "62.75.159.113", "91.44.203.238", "82.114.88.225", "78.63.207.76", "188.174.110.224", "91.235.72.49", "213.144.130.91", "209.222.98.250", "216.155.128.10", "178.33.203.157", "162.243.122.251", "69.163.47.173", "193.151.106.129", "78.94.2.74", "192.3.196.10", "173.33.112.87", "104.198.173.28", "35.184.154.126", "174.140.167.239", "23.88.113.131", "198.71.84.173", "178.150.207.53", "23.88.61.53", "192.157.233.106", "192.157.241.212", "23.89.192.88", "23.89.200.27", "192.157.241.139", "23.89.200.63", "23.89.192.98", "163.172.214.102", "176.9.85.5", "80.150.243.88", "80.150.243.92", "80.150.243.98", "109.70.186.198", "146.148.84.237", "104.155.56.82", "104.197.157.140", "37.48.73.249", "146.148.77.226", "84.57.170.200", "107.161.145.131", "80.150.243.97", "80.150.243.93", "80.150.243.100", "80.150.243.95", "80.150.243.91", "80.150.243.99", "80.150.243.96", "93.231.187.177", "212.237.23.85", "35.158.179.254", "46.36.66.41", "185.170.113.79", "163.172.68.112", "78.47.35.210", "77.90.90.75", "94.177.196.134", "212.237.22.215", "94.177.234.11", "167.160.180.199", "54.68.189.9", "94.159.62.14", "195.181.221.89", "185.33.145.94", "195.181.209.245", "195.181.221.38", "195.181.221.162", "185.33.145.12", "185.33.145.176", "178.79.128.235", "94.177.214.120", "94.177.199.41", "94.177.214.200", "94.177.213.201", "212.237.13.162", "195.181.221.236", "195.181.221.185", "185.28.103.187", "185.33.146.244", "217.61.123.71", "195.181.214.45", "195.181.212.99", "195.181.214.46", "195.181.214.215", "195.181.214.68", "217.61.123.118", "195.181.214.79", "217.61.123.14", "217.61.124.100", "195.181.214.111", "85.255.0.176", "81.2.254.116", "217.61.123.184", "195.181.212.231", "94.177.214.110", "195.181.209.164", "104.129.56.238", "85.255.13.64", "167.160.180.206", "217.61.123.226", "167.160.180.208", "93.186.253.127", "212.237.6.208", "94.177.207.190", "217.61.123.119", "85.255.1.245", "217.61.124.157", "37.59.57.141", "167.160.180.58", "104.223.53.14", "217.61.124.69", "195.181.212.103", "85.255.13.141", "104.207.133.204", "71.90.7.107", "107.150.18.108", "23.94.134.161", "80.150.243.13", "80.150.243.11", "185.81.165.52", "80.150.243.8" };
cJSON *LP_assethbla(char *assetid)
{
char url[1024],*retstr; int32_t n; cJSON *array,*bid=0,*ask=0,*retjson;
sprintf(url,"http://%s:7876/nxt?=%%2Fnxt&requestType=getBidOrders&asset=%s&firstIndex=0&lastIndex=0",NXTnodes[rand() % (sizeof(NXTnodes)/sizeof(*NXTnodes))],assetid);
if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 )
{
bid = cJSON_Parse(retstr);
free(retstr);
}
sprintf(url,"http://%s:7876/nxt?=%%2Fnxt&requestType=getAskOrders&asset=%s&firstIndex=0&lastIndex=0",NXTnodes[rand() % (sizeof(NXTnodes)/sizeof(*NXTnodes))],assetid);
if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 )
{
ask = cJSON_Parse(retstr);
free(retstr);
}
retjson = cJSON_CreateObject();
if ( bid != 0 && ask != 0 )
{
if ( (array= jarray(&n,bid,"bidOrders")) != 0 )
jadd(retjson,"bid",jduplicate(jitem(array,0)));
if ( (array= jarray(&n,ask,"askOrders")) != 0 )
jadd(retjson,"ask",jduplicate(jitem(array,0)));
}
if ( bid != 0 )
free_json(bid);
if ( ask != 0 )
free_json(ask);
return(retjson);
}
cJSON *LP_getinfo(char *symbol) cJSON *LP_getinfo(char *symbol)
{ {
struct iguana_info *coin = LP_coinfind(symbol); struct iguana_info *coin = LP_coinfind(symbol);
@ -219,10 +175,19 @@ cJSON *LP_getmempool(char *symbol)
return(bitcoin_json(coin,"getrawmempool","[]")); return(bitcoin_json(coin,"getrawmempool","[]"));
} }
cJSON *LP_paxprice(char *fiat)
{
char buf[128],lfiat[65]; struct iguana_info *coin = LP_coinfind("KMD");
strcpy(lfiat,fiat);
tolowercase(lfiat);
sprintf(buf,"[\"%s\", \"kmd\"]",lfiat);
return(bitcoin_json(coin,"paxprice",buf));
}
cJSON *LP_gettxout(char *symbol,bits256 txid,int32_t vout) cJSON *LP_gettxout(char *symbol,bits256 txid,int32_t vout)
{ {
char buf[128],str[65]; struct iguana_info *coin = LP_coinfind(symbol); char buf[128],str[65]; struct iguana_info *coin = LP_coinfind(symbol);
sprintf(buf,"\"%s\", %d, true",bits256_str(str,txid),vout); sprintf(buf,"[\"%s\", %d, true]",bits256_str(str,txid),vout);
return(bitcoin_json(coin,"gettxout",buf)); return(bitcoin_json(coin,"gettxout",buf));
} }
@ -250,7 +215,7 @@ cJSON *LP_getblockhashstr(char *symbol,char *blockhashstr)
cJSON *LP_listunspent(char *symbol,char *coinaddr) cJSON *LP_listunspent(char *symbol,char *coinaddr)
{ {
char buf[128]; struct iguana_info *coin = LP_coinfind(symbol); char buf[128]; struct iguana_info *coin = LP_coinfind(symbol);
sprintf(buf,"0, 99999999, [\"%s\"]",coinaddr); sprintf(buf,"[0, 99999999, [\"%s\"]]",coinaddr);
return(bitcoin_json(coin,"listunspent",buf)); return(bitcoin_json(coin,"listunspent",buf));
} }
@ -266,15 +231,35 @@ cJSON *LP_listtransactions(char *symbol,char *coinaddr,int32_t count,int32_t ski
cJSON *LP_validateaddress(char *symbol,char *address) cJSON *LP_validateaddress(char *symbol,char *address)
{ {
char buf[512]; struct iguana_info *coin = LP_coinfind(symbol); char buf[512]; struct iguana_info *coin = LP_coinfind(symbol);
sprintf(buf,"\"%s\"",address); sprintf(buf,"[\"%s\"]",address);
return(bitcoin_json(coin,"validateaddress",buf)); return(bitcoin_json(coin,"validateaddress",buf));
} }
cJSON *LP_importprivkey(char *symbol,char *wifstr,char *label,int32_t flag) cJSON *LP_importprivkey(char *symbol,char *wifstr,char *label,int32_t flag)
{ {
char buf[512]; struct iguana_info *coin = LP_coinfind(symbol); static void *ctx;
sprintf(buf,"[\"%s\", \"%s\", %s]",wifstr,label,flag < 0 ? "false" : "true"); char buf[512],address[64]; cJSON *retjson; struct iguana_info *coin; int32_t doneflag = 0;
return(bitcoin_json(coin,"importprivkey",buf)); coin = LP_coinfind(symbol);
if ( ctx == 0 )
ctx = bitcoin_ctx();
bitcoin_wif2addr(ctx,coin->wiftaddr,coin->taddr,coin->pubtype,address,wifstr);
if ( (retjson= LP_validateaddress(symbol,address)) != 0 )
{
if ( jobj(retjson,"ismine") != 0 && is_cJSON_True(jobj(retjson,"ismine")) != 0 )
{
doneflag = 1;
//printf("%s already ismine\n",address);
}
//printf("%s\n",jprint(retjson,0));
free_json(retjson);
}
if ( doneflag == 0 )
{
if ( coin->noimportprivkey_flag != 0 )
sprintf(buf,"[\"%s\"]",wifstr);
else sprintf(buf,"\"%s\", \"%s\", %s",wifstr,label,flag < 0 ? "false" : "true");
return(bitcoin_json(coin,"importprivkey",buf));
} else return(cJSON_Parse("{\"result\":\"success\"}"));
} }
int32_t LP_importaddress(char *symbol,char *address) int32_t LP_importaddress(char *symbol,char *address)
@ -307,27 +292,27 @@ int32_t LP_importaddress(char *symbol,char *address)
double LP_getestimatedrate(char *symbol) double LP_getestimatedrate(char *symbol)
{ {
char buf[512],*retstr; double rate = 20; struct iguana_info *coin = LP_coinfind(symbol); char buf[512],*retstr; double rate = 20; struct iguana_info *coin = LP_coinfind(symbol);
if ( coin != 0 ) if ( coin != 0 && (strcmp(coin->symbol,"BTC") == 0 || coin->txfee == 0) )
{ {
sprintf(buf,"[%d]",3); sprintf(buf,"[%d]",3);
if ( (retstr= bitcoind_passthru(symbol,coin->serverport,coin->userpass,"estimatefee",buf)) != 0 ) if ( (retstr= bitcoind_passthru(symbol,coin->serverport,coin->userpass,"estimatefee",buf)) != 0 )
{ {
if ( retstr[0] != '-' ) if ( retstr[0] != '-' )
{ {
coin->estimatedrate = rate = atof(retstr) / 1024.; rate = atof(retstr) / 1024.;
printf("estimated rate.(%s) %s -> %.8f\n",symbol,retstr,rate); //printf("estimated rate.(%s) %s -> %.8f\n",symbol,retstr,rate);
} }
free(retstr); free(retstr);
} }
} } else return((double)coin->txfee / LP_AVETXSIZE);
return(rate); return(SATOSHIDEN * rate);
} }
uint64_t LP_txfee(char *symbol) uint64_t LP_txfee(char *symbol)
{ {
uint64_t txfee = 0; uint64_t txfee = 0;
if ( strcmp(symbol,"BTC") != 0 ) if ( strcmp(symbol,"BTC") != 0 )
txfee = 10000; txfee = LP_MIN_TXFEE;
return(txfee); return(txfee);
} }
@ -412,7 +397,7 @@ cJSON *LP_blockjson(int32_t *heightp,char *symbol,char *blockhashstr,int32_t hei
*heightp = juint(json,"height"); *heightp = juint(json,"height");
if ( height >= 0 && *heightp != height ) if ( height >= 0 && *heightp != height )
{ {
printf("unexpected height %d vs %d\n",*heightp,height); printf("unexpected height %d vs %d for %s (%s)\n",*heightp,height,blockhashstr,jprint(json,0));
*heightp = -1; *heightp = -1;
free_json(json); free_json(json);
json = 0; json = 0;

443
iguana/exchanges/LP_scan.c

@ -18,6 +18,31 @@
// marketmaker // marketmaker
// //
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);
}
struct LP_transaction *LP_transactionfind(struct iguana_info *coin,bits256 txid) struct LP_transaction *LP_transactionfind(struct iguana_info *coin,bits256 txid)
{ {
struct LP_transaction *tx; struct LP_transaction *tx;
@ -119,23 +144,24 @@ uint64_t LP_txinterestvalue(uint64_t *interestp,char *destaddr,struct iguana_inf
if ( n > 1 ) if ( n > 1 )
printf("LP_txinterestvalue warning: violation of 1 output assumption n.%d\n",n); printf("LP_txinterestvalue warning: violation of 1 output assumption n.%d\n",n);
} else printf("LP_txinterestvalue no addresses found?\n"); } else printf("LP_txinterestvalue no addresses found?\n");
//char str[65]; printf("%.8f <- %s.(%s) txobj.(%s)\n",dstr(value),symbol,bits256_str(str,txid),jprint(txobj,0)); //char str[65]; printf("%s %.8f <- %s.(%s) txobj.(%s)\n",destaddr,dstr(value),coin->symbol,bits256_str(str,txid),jprint(txobj,0));
free_json(txobj); free_json(txobj);
} } //else { char str[65]; printf("null gettxout return %s/v%d\n",bits256_str(str,txid),vout); }
return(value); return(value);
} }
int32_t LP_transactioninit(struct iguana_info *coin,bits256 txid) int32_t LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter)
{ {
struct LP_transaction *tx; int32_t i,height,numvouts,numvins,spentvout; uint32_t timestamp,blocktime; cJSON *txobj,*vins,*vouts,*vout,*vin; bits256 spenttxid; char str[65]; struct LP_transaction *tx; char *address; int32_t i,n,height,numvouts,numvins,spentvout; uint32_t timestamp,blocktime; cJSON *txobj,*vins,*vouts,*vout,*vin,*sobj,*addresses; bits256 spenttxid; char str[65];
if ( (txobj=LP_gettx(coin->symbol,txid)) != 0 ) if ( (txobj= LP_gettx(coin->symbol,txid)) != 0 )
{ {
//printf("TX.(%s)\n",jprint(txobj,0));
height = LP_txheight(&timestamp,&blocktime,coin,txid); height = LP_txheight(&timestamp,&blocktime,coin,txid);
if ( timestamp == 0 && height > 0 ) if ( timestamp == 0 && height > 0 )
timestamp = blocktime; timestamp = blocktime;
vins = jarray(&numvins,txobj,"vin"); vins = jarray(&numvins,txobj,"vin");
vouts = jarray(&numvouts,txobj,"vout"); vouts = jarray(&numvouts,txobj,"vout");
if ( vouts != 0 && (tx= LP_transactionadd(coin,txid,height,numvouts,numvins,timestamp)) != 0 ) if ( iter == 0 && vouts != 0 && (tx= LP_transactionadd(coin,txid,height,numvouts,numvins,timestamp)) != 0 )
{ {
for (i=0; i<numvouts; i++) for (i=0; i<numvouts; i++)
{ {
@ -143,15 +169,32 @@ int32_t LP_transactioninit(struct iguana_info *coin,bits256 txid)
if ( (tx->outpoints[i].value= SATOSHIDEN * jdouble(vout,"value")) == 0 ) if ( (tx->outpoints[i].value= SATOSHIDEN * jdouble(vout,"value")) == 0 )
tx->outpoints[i].value = SATOSHIDEN * jdouble(vout,"amount"); tx->outpoints[i].value = SATOSHIDEN * jdouble(vout,"amount");
tx->outpoints[i].interest = SATOSHIDEN * jdouble(vout,"interest"); 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);
} 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);
}
} }
} }
if ( vins != 0 ) if ( iter == 1 && vins != 0 )
{ {
for (i=0; i<numvins; i++) for (i=0; i<numvins; i++)
{ {
vin = jitem(vins,i); vin = jitem(vins,i);
spenttxid = jbits256(vin,"txid"); spenttxid = jbits256(vin,"txid");
spentvout = jint(vin,"vout"); spentvout = jint(vin,"vout");
if ( i == 0 && bits256_nonz(spenttxid) == 0 )
continue;
if ( (tx= LP_transactionfind(coin,spenttxid)) != 0 ) if ( (tx= LP_transactionfind(coin,spenttxid)) != 0 )
{ {
if ( spentvout < tx->numvouts ) if ( spentvout < tx->numvouts )
@ -160,23 +203,26 @@ int32_t LP_transactioninit(struct iguana_info *coin,bits256 txid)
tx->outpoints[spentvout].spendvini = i; tx->outpoints[spentvout].spendvini = i;
tx->outpoints[spentvout].spendheight = height; tx->outpoints[spentvout].spendheight = height;
//printf("spend %s %s/v%d at ht.%d\n",coin->symbol,bits256_str(str,tx->txid),spentvout,height); //printf("spend %s %s/v%d at ht.%d\n",coin->symbol,bits256_str(str,tx->txid),spentvout,height);
} else printf("LP_transactioninint: %s spentvout.%d < numvouts.%d\n",bits256_str(str,spenttxid),spentvout,tx->numvouts); } else printf("LP_transactioninit: %s spentvout.%d < numvouts.%d\n",bits256_str(str,spenttxid),spentvout,tx->numvouts);
} } //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); free_json(txobj);
return(0); return(0);
} else printf("LP_transactioninit error for %s\n",bits256_str(str,txid)); } //else printf("LP_transactioninit error for %s %s\n",coin->symbol,bits256_str(str,txid));
return(-1); return(-1);
} }
int32_t LP_blockinit(struct iguana_info *coin,int32_t height) int32_t LP_blockinit(struct iguana_info *coin,int32_t height)
{ {
int32_t i,numtx,checkht=-1; cJSON *blockobj,*txs; bits256 txid; struct LP_transaction *tx; int32_t i,j,iter,numtx,checkht=-1; cJSON *blockobj,*txs; bits256 txid; struct LP_transaction *tx;
if ( (blockobj= LP_blockjson(&checkht,coin->symbol,0,height)) != 0 ) if ( (blockobj= LP_blockjson(&checkht,coin->symbol,0,height)) != 0 && checkht == height )
{ {
if ( (txs= jarray(&numtx,blockobj,"tx")) != 0 ) if ( (txs= jarray(&numtx,blockobj,"tx")) != 0 )
{ {
for (iter=0; iter<2; iter++)
for (i=0; i<numtx; i++) for (i=0; i<numtx; i++)
{ {
txid = jbits256i(txs,i); txid = jbits256i(txs,i);
@ -189,7 +235,25 @@ int32_t LP_blockinit(struct iguana_info *coin,int32_t height)
printf("LP_blockinit: tx->height %d != %d\n",tx->height,height); printf("LP_blockinit: tx->height %d != %d\n",tx->height,height);
tx->height = height; tx->height = height;
} }
} else LP_transactioninit(coin,txid); if ( iter == 1 )
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);
}
}
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);
}
}
} }
} }
free_json(blockobj); free_json(blockobj);
@ -199,6 +263,339 @@ int32_t LP_blockinit(struct iguana_info *coin,int32_t height)
else return(-1); else return(-1);
} }
int32_t LP_scanblockchain(struct iguana_info *coin,int32_t startheight,int32_t endheight)
{
int32_t ht,n = 0;
for (ht=startheight; ht<=endheight; ht++)
{
if ( LP_blockinit(coin,ht) < 0 )
{
printf("error loading block.%d of (%d, %d)\n",ht,startheight,endheight);
return(ht-1);
}
n++;
if ( (n % 1000) == 0 )
fprintf(stderr,"%.1f%% ",100. * (double)n/(endheight-startheight+1));
}
return(endheight);
}
char *banned_txids[] =
{
"78cb4e21245c26b015b888b14c4f5096e18137d2741a6de9734d62b07014dfca", //233559
"00697be658e05561febdee1aafe368b821ca33fbb89b7027365e3d77b5dfede5", //234172
"e909465788b32047c472d73e882d79a92b0d550f90be008f76e1edaee6d742ea", //234187
"f56c6873748a327d0b92b8108f8ec8505a2843a541b1926022883678fb24f9dc", //234188
"abf08be07d8f5b3a433ddcca7ef539e79a3571632efd6d0294ec0492442a0204", //234213
"3b854b996cc982fba8c06e76cf507ae7eed52ab92663f4c0d7d10b3ed879c3b0", //234367
"fa9e474c2cda3cb4127881a40eb3f682feaba3f3328307d518589024a6032cc4", //234635
"ca746fa13e0113c4c0969937ea2c66de036d20274efad4ce114f6b699f1bc0f3", //234662
"43ce88438de4973f21b1388ffe66e68fda592da38c6ef939be10bb1b86387041", //234697
"0aeb748de82f209cd5ff7d3a06f65543904c4c17387c9d87c65fd44b14ad8f8c", //234899
"bbd3a3d9b14730991e1066bd7c626ca270acac4127131afe25f877a5a886eb25", //235252
"fa9943525f2e6c32cbc243294b08187e314d83a2870830180380c3c12a9fd33c", //235253
"a01671c8775328a41304e31a6693bbd35e9acbab28ab117f729eaba9cb769461", //235265
"2ef49d2d27946ad7c5d5e4ab5c089696762ff04e855f8ab48e83bdf0cc68726d", //235295
"c85dcffb16d5a45bd239021ad33443414d60224760f11d535ae2063e5709efee", //235296
// all vouts banned
"c4ea1462c207547cd6fb6a4155ca6d042b22170d29801a465db5c09fec55b19d", //246748
"305dc96d8bc23a69d3db955e03a6a87c1832673470c32fe25473a46cc473c7d1", //247204
};
int32_t komodo_bannedset(int32_t *indallvoutsp,bits256 *array,int32_t max)
{
int32_t i;
if ( sizeof(banned_txids)/sizeof(*banned_txids) > max )
{
fprintf(stderr,"komodo_bannedset: buffer too small %ld vs %d\n",sizeof(banned_txids)/sizeof(*banned_txids),max);
exit(-1);
}
for (i=0; i<sizeof(banned_txids)/sizeof(*banned_txids); i++)
decode_hex(array[i].bytes,sizeof(array[i]),banned_txids[i]);
*indallvoutsp = i-2;
return(i);
}
int sort_balance(void *a,void *b)
{
int64_t aval,bval;
/* compare a to b (cast a and b appropriately)
* return (int) -1 if (a < b)
* return (int) 0 if (a == b)
* return (int) 1 if (a > b)
*/
aval = ((struct LP_address *)a)->balance;
bval = ((struct LP_address *)b)->balance;
//printf("%.8f vs %.8f -> %d\n",dstr(aval),dstr(bval),(int32_t)(bval - aval));
return((aval == bval) ? 0 : ((aval < bval) ? 1 : -1));
}
// a primitive restore can be done by loading the previous snapshot and creating a virtual tx for all the balance at height-1. this wont allow anything but new snapshots, but for many use cases that is all that is needed
cJSON *LP_snapshot(struct iguana_info *coin,int32_t height)
{
static bits256 bannedarray[64]; static int32_t numbanned,indallvouts,maxsnapht; static char lastcoin[16];
struct LP_transaction *tx,*tmp; struct LP_address *ap,*atmp; int32_t isKMD,i,j,n,skipflag=0,startht,endht,ht; uint64_t banned_balance=0,balance=0,noaddr_balance=0; cJSON *retjson,*array,*item;
if ( bannedarray[0].txid == 0 )
numbanned = komodo_bannedset(&indallvouts,bannedarray,(int32_t)(sizeof(bannedarray)/sizeof(*bannedarray)));
startht = 1;
endht = height-1;
if ( strcmp(coin->symbol,lastcoin) == 0 )
{
if ( maxsnapht > height )
skipflag = 1;
else startht = maxsnapht+1;
}
else
{
maxsnapht = 0;
strcpy(lastcoin,coin->symbol);
}
retjson = cJSON_CreateObject();
if ( skipflag == 0 && startht < endht )
{
if ( (ht= LP_scanblockchain(coin,startht,endht)) < endht )
{
if ( ht > maxsnapht )
{
maxsnapht = ht;
printf("maxsnapht.%d for %s\n",maxsnapht,coin->symbol);
}
sleep(10);
if ( (ht= LP_scanblockchain(coin,maxsnapht+1,endht)) < endht )
{
if ( ht > maxsnapht )
{
maxsnapht = ht;
printf("maxsnapht.%d for %s\n",maxsnapht,coin->symbol);
}
jaddstr(retjson,"error","blockchain scan error");
return(retjson);
}
}
if ( ht > maxsnapht )
{
maxsnapht = ht;
printf("maxsnapht.%d for %s\n",maxsnapht,coin->symbol);
}
}
portable_mutex_lock(&coin->txmutex);
HASH_ITER(hh,coin->addresses,ap,atmp)
{
ap->balance = 0;
}
isKMD = (strcmp(coin->symbol,"KMD") == 0) ? 1 : 0;
HASH_ITER(hh,coin->transactions,tx,tmp)
{
if ( tx->height < height )
{
if ( isKMD != 0 )
{
for (j=0; j<numbanned; j++)
if ( bits256_cmp(bannedarray[j],tx->txid) == 0 )
break;
if ( j < numbanned )
{
for (i=0; i<tx->numvouts; i++)
banned_balance += tx->outpoints[i].value;
//char str[256]; printf("skip banned %s bannedtotal: %.8f\n",bits256_str(str,tx->txid),dstr(banned_balance));
continue;
}
}
for (i=0; i<tx->numvouts; i++)
{
if ( (ht=tx->outpoints[i].spendheight) > 0 && ht < height )
continue;
if ( tx->outpoints[i].coinaddr[0] != 0 && (ap= _LP_address(coin,tx->outpoints[i].coinaddr)) != 0 )
{
balance += tx->outpoints[i].value;
ap->balance += tx->outpoints[i].value;
//printf("(%s/%s) %.8f %.8f\n",tx->outpoints[i].coinaddr,ap->coinaddr,dstr(tx->outpoints[i].value),dstr(ap->balance));
} else noaddr_balance += tx->outpoints[i].value;
}
}
}
HASH_SORT(coin->addresses,sort_balance);
portable_mutex_unlock(&coin->txmutex);
printf("%s balance %.8f at height.%d\n",coin->symbol,dstr(balance),height);
array = cJSON_CreateArray();
n = 0;
HASH_ITER(hh,coin->addresses,ap,atmp)
{
if ( ap->balance != 0 )
{
item = cJSON_CreateObject();
jaddnum(item,ap->coinaddr,dstr(ap->balance));
jaddi(array,item);
n++;
}
}
jadd(retjson,"balances",array);
jaddstr(retjson,"coin",coin->symbol);
jaddnum(retjson,"height",height);
jaddnum(retjson,"numaddresses",n);
jaddnum(retjson,"total",dstr(balance));
jaddnum(retjson,"noaddr_total",dstr(noaddr_balance));
return(retjson);
}
char *LP_snapshot_balance(struct iguana_info *coin,int32_t height,cJSON *argjson)
{
cJSON *snapjson,*retjson,*balances,*array,*addrs,*child,*item,*item2; char *coinaddr,*refaddr; int32_t i,n,j,m; uint64_t total=0,value,balance = 0;
retjson = cJSON_CreateObject();
array = cJSON_CreateArray();
if ( (snapjson= LP_snapshot(coin,height)) != 0 )
{
total = jdouble(snapjson,"total") * SATOSHIDEN;
if ( (addrs= jarray(&m,argjson,"addresses")) != 0 )
{
if ( (balances= jarray(&n,snapjson,"balances")) != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(balances,i);
if ( (child= item->child) != 0 )
{
value = (uint64_t)(child->valuedouble * SATOSHIDEN);
if ( (refaddr= get_cJSON_fieldname(child)) != 0 )
{
//printf("check %s %.8f against %d\n",refaddr,dstr(value),m);
for (j=0; j<m; j++)
{
if ( (coinaddr= jstri(addrs,j)) != 0 )
{
if ( strcmp(coinaddr,refaddr) == 0 )
{
item2 = cJSON_CreateObject();
jaddnum(item2,coinaddr,dstr(value));
jaddi(array,item2);
balance += value;
break;
}
}
}
}
}
}
}
}
free_json(snapjson);
}
jadd(retjson,"balances",array);
jaddstr(retjson,"coin",coin->symbol);
jaddnum(retjson,"height",height);
jaddnum(retjson,"balance",dstr(balance));
jaddnum(retjson,"total",dstr(total));
return(jprint(retjson,1));
}
char *LP_dividends(struct iguana_info *coin,int32_t height,cJSON *argjson)
{
cJSON *array,*retjson,*item,*child,*exclude=0; int32_t i,j,emitted=0,dusted=0,n,execflag=0,flag,iter,numexcluded=0; char buf[1024],*field,*prefix="",*suffix=""; uint64_t dustsum=0,excluded=0,total=0,dividend=0,value,val,emit=0,dust=0; double ratio = 1.;
if ( (retjson= LP_snapshot(coin,height)) != 0 )
{
//printf("SNAPSHOT.(%s)\n",retstr);
if ( (array= jarray(&n,retjson,"balances")) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) != 0 )
{
if ( argjson != 0 )
{
exclude = jarray(&numexcluded,argjson,"exclude");
dust = (uint64_t)(jdouble(argjson,"dust") * SATOSHIDEN);
dividend = (uint64_t)(jdouble(argjson,"dividend") * SATOSHIDEN);
if ( jstr(argjson,"prefix") != 0 )
prefix = jstr(argjson,"prefix");
if ( jstr(argjson,"suffix") != 0 )
suffix = jstr(argjson,"suffix");
execflag = jint(argjson,"system");
}
for (iter=0; iter<2; iter++)
{
for (i=0; i<n; i++)
{
flag = 0;
item = jitem(array,i);
if ( (child= item->child) != 0 )
{
value = (uint64_t)(child->valuedouble * SATOSHIDEN);
if ( (field= get_cJSON_fieldname(child)) != 0 )
{
for (j=0; j<numexcluded; j++)
if ( strcmp(field,jstri(exclude,j)) == 0 )
{
flag = 1;
break;
}
}
//printf("(%s %s %.8f) ",jprint(item,0),field,dstr(value));
if ( iter == 0 )
{
if ( flag != 0 )
excluded += value;
else total += value;
}
else
{
if ( flag == 0 )
{
val = ratio * value;
if ( val >= dust )
{
sprintf(buf,"%s %s %.8f %s",prefix,field,dstr(val),suffix);
if ( execflag != 0 )
{
if ( system(buf) != 0 )
printf("error system.(%s)\n",buf);
}
else printf("%s\n",buf);
emit += val;
emitted++;
} else dustsum += val, dusted++;
}
}
}
}
if ( iter == 0 )
{
if ( total > 0 )
{
if ( dividend == 0 )
dividend = total;
ratio = (double)dividend / total;
} else break;
}
}
}
}
free_json(retjson);
retjson = cJSON_CreateObject();
jaddstr(retjson,"coin",coin->symbol);
jaddnum(retjson,"height",height);
jaddnum(retjson,"total",dstr(total));
jaddnum(retjson,"emitted",emitted);
jaddnum(retjson,"excluded",dstr(excluded));
if ( dust != 0 )
{
jaddnum(retjson,"dust",dstr(dust));
jaddnum(retjson,"dusted",dusted);
}
if ( dustsum != 0 )
jaddnum(retjson,"dustsum",dstr(dustsum));
jaddnum(retjson,"dividend",dstr(dividend));
jaddnum(retjson,"dividends",dstr(emit));
jaddnum(retjson,"ratio",ratio);
if ( execflag != 0 )
jaddnum(retjson,"system",execflag);
/*if ( prefix[0] != 0 )
jaddstr(retjson,"prefix",prefix);
if ( suffix[0] != 0 )
jaddstr(retjson,"suffix",suffix);*/
return(jprint(retjson,1));
}
return(clonestr("{\"error\":\"symbol not found\"}"));
}
int64_t basilisk_txvalue(char *symbol,bits256 txid,int32_t vout) int64_t basilisk_txvalue(char *symbol,bits256 txid,int32_t vout)
{ {
char destaddr[64]; uint64_t value,interest = 0; struct iguana_info *coin; char destaddr[64]; uint64_t value,interest = 0; struct iguana_info *coin;
@ -222,22 +619,23 @@ uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout)
{ {
if ( bits256_nonz(tx->outpoints[vout].spendtxid) != 0 ) if ( bits256_nonz(tx->outpoints[vout].spendtxid) != 0 )
{ {
char str[65]; printf("%s/v%d is spent\n",bits256_str(str,txid),vout); //char str[65]; printf("%s/v%d is spent\n",bits256_str(str,txid),vout);
return(0); return(0);
} }
else else
{ {
if ( coinaddr != 0 && strcmp(symbol,"KMD") == 0 ) if ( coinaddr != 0 )
{
value = LP_txinterestvalue(&tx->outpoints[vout].interest,coinaddr,coin,txid,vout); value = LP_txinterestvalue(&tx->outpoints[vout].interest,coinaddr,coin,txid,vout);
}
//printf("return value %.8f + interest %.8f\n",dstr(tx->outpoints[vout].value),dstr(tx->outpoints[vout].interest)); //printf("return value %.8f + interest %.8f\n",dstr(tx->outpoints[vout].value),dstr(tx->outpoints[vout].interest));
return(tx->outpoints[vout].value + tx->outpoints[vout].interest); return(tx->outpoints[vout].value + tx->outpoints[vout].interest);
} }
} else printf("vout.%d >= tx->numvouts.%d\n",vout,tx->numvouts); } else printf("vout.%d >= tx->numvouts.%d\n",vout,tx->numvouts);
} }
if ( tx == 0 ) if ( tx == 0 )
LP_transactioninit(coin,txid); {
LP_transactioninit(coin,txid,0);
LP_transactioninit(coin,txid,1);
}
if ( coinaddr == 0 ) if ( coinaddr == 0 )
coinaddr = _coinaddr; coinaddr = _coinaddr;
value = LP_txinterestvalue(&interest,coinaddr,coin,txid,vout); value = LP_txinterestvalue(&interest,coinaddr,coin,txid,vout);
@ -277,7 +675,10 @@ int32_t LP_mempoolscan(char *symbol,bits256 searchtxid)
{ {
txid = jbits256i(array,i); txid = jbits256i(array,i);
if ( (tx= LP_transactionfind(coin,txid)) == 0 ) if ( (tx= LP_transactionfind(coin,txid)) == 0 )
LP_transactioninit(coin,txid); {
LP_transactioninit(coin,txid,0);
LP_transactioninit(coin,txid,1);
}
if ( bits256_cmp(txid,searchtxid) == 0 ) if ( bits256_cmp(txid,searchtxid) == 0 )
{ {
char str[65]; printf("found %s tx.(%s) in mempool slot.%d\n",symbol,bits256_str(str,txid),i); char str[65]; printf("found %s tx.(%s) in mempool slot.%d\n",symbol,bits256_str(str,txid),i);
@ -290,7 +691,7 @@ int32_t LP_mempoolscan(char *symbol,bits256 searchtxid)
return(-1); return(-1);
} }
int32_t LP_numconfirms(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx) int32_t LP_numconfirms(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx,int32_t mempool)
{ {
struct iguana_info *coin; int32_t numconfirms = 100; struct iguana_info *coin; int32_t numconfirms = 100;
//#ifndef BASILISK_DISABLEWAITTX //#ifndef BASILISK_DISABLEWAITTX
@ -303,7 +704,7 @@ int32_t LP_numconfirms(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx)
numconfirms = jint(txobj,"confirmations"); numconfirms = jint(txobj,"confirmations");
free_json(txobj); free_json(txobj);
} }
else if ( LP_mempoolscan(rawtx->coin->symbol,rawtx->I.signedtxid) >= 0 ) else if ( mempool != 0 && LP_mempoolscan(rawtx->coin->symbol,rawtx->I.signedtxid) >= 0 )
numconfirms = 0; numconfirms = 0;
//#endif //#endif
return(numconfirms); return(numconfirms);

115
iguana/exchanges/LP_statemachine.c

@ -113,6 +113,109 @@ FILE *basilisk_swap_save(struct basilisk_swap *swap,bits256 privkey,struct basil
}*/ }*/
return(fp); return(fp);
} }
/*char *issue_LP_notifyutxo(char *destip,uint16_t destport,struct LP_utxoinfo *utxo)
{
char url[4096],str[65],str2[65],str3[65],*retstr; struct _LP_utxoinfo u; uint64_t val,val2;
if ( (retstr= LP_isitme(destip,destport)) != 0 )
return(retstr);
if ( utxo->iambob == 0 )
{
printf("issue_LP_notifyutxo trying to send Alice %s/v%d\n",bits256_str(str,utxo->payment.txid),utxo->payment.vout);
return(0);
}
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee;
if ( LP_iseligible(&val,&val2,utxo->iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,u.txid,u.vout) > 0 )
{
sprintf(url,"http://%s:%u/api/stats/notified?iambob=%d&pubkey=%s&coin=%s&txid=%s&vout=%d&value=%llu&txid2=%s&vout2=%d&value2=%llu&script=%s&address=%s&timestamp=%u&gui=%s",destip,destport,utxo->iambob,bits256_str(str3,utxo->pubkey),utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout,(long long)utxo->payment.value,bits256_str(str2,utxo->deposit.txid),utxo->deposit.vout,(long long)utxo->deposit.value,utxo->spendscript,utxo->coinaddr,(uint32_t)time(NULL),utxo->gui);
if ( strlen(url) > 1024 )
printf("WARNING long url.(%s)\n",url);
return(LP_issue_curl("notifyutxo",destip,destport,url));
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
}
else
{
printf("issue_LP_notifyutxo: ineligible utxo iambob.%d %.8f %.8f\n",utxo->iambob,dstr(val),dstr(val2));
if ( utxo->T.spentflag == 0 )
utxo->T.spentflag = (uint32_t)time(NULL);
return(0);
}
}*/
/*char *issue_LP_lookup(char *destip,uint16_t destport,bits256 pubkey)
{
char url[512],str[65];
sprintf(url,"http://%s:%u/api/stats/lookup?client=%s",destip,destport,bits256_str(str,pubkey));
//printf("getutxo.(%s)\n",url);
return(LP_issue_curl("lookup",destip,destport,url));
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
}*/
/*if ( LP_canbind == 0 )
{
//printf("check deadman %u vs %u\n",LP_deadman_switch,(uint32_t)time(NULL));
if ( LP_deadman_switch < time(NULL)-PSOCK_KEEPALIVE )
{
printf("DEAD man's switch %u activated at %u lag.%d, register forwarding again\n",LP_deadman_switch,(uint32_t)time(NULL),(uint32_t)(time(NULL) - LP_deadman_switch));
if ( pullsock >= 0 )
nn_close(pullsock);
pullsock = LP_initpublicaddr(ctx,&mypullport,pushaddr,myipaddr,mypullport,0);
LP_deadman_switch = (uint32_t)time(NULL);
strcpy(LP_publicaddr,pushaddr);
LP_publicport = mypullport;
LP_forwarding_register(LP_mypubkey,pushaddr,mypullport,MAX_PSOCK_PORT);
}
}*/
/*if ( lastforward < now-3600 )
{
if ( (retstr= LP_registerall(0)) != 0 )
free(retstr);
//LP_forwarding_register(LP_mypubkey,pushaddr,pushport,10);
lastforward = now;
}*/
//if ( IAMLP != 0 && (counter % 600) == 42 )
// LP_hellos();
/*if ( 0 && LP_canbind == 0 && (counter % (PSOCK_KEEPALIVE*MAINLOOP_PERSEC/2)) == 13 )
{
char keepalive[128];
sprintf(keepalive,"{\"method\":\"keepalive\"}");
//printf("send keepalive to %s pullsock.%d\n",pushaddr,pullsock);
if ( /LP_send(pullsock,keepalive,(int32_t)strlen(keepalive)+1,0) < 0 )
{
//LP_deadman_switch = 0;
}
}*/
/*int32_t nn_tests(void *ctx,int32_t pullsock,char *pushaddr,int32_t nnother)
{
int32_t sock,n,m,timeout,retval = -1; char msg[512],*retstr;
printf("nn_tests.(%s)\n",pushaddr);
if ( (sock= nn_socket(AF_SP,nnother)) >= 0 )
{
if ( nn_connect(sock,pushaddr) < 0 )
printf("connect error %s\n",nn_strerror(nn_errno()));
else
{
sleep(3);
timeout = 1;
nn_setsockopt(sock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
sprintf(msg,"{\"method\":\"nn_tests\",\"ipaddr\":\"%s\"}",pushaddr);
n = /LP_send(sock,msg,(int32_t)strlen(msg)+1,0);
sleep(3);
LP_pullsock_check(ctx,&retstr,"127.0.0.1",-1,pullsock,0.);
sprintf(msg,"{\"method\":\"nn_tests2\",\"ipaddr\":\"%s\"}",pushaddr);
m = /LP_send(pullsock,msg,(int32_t)strlen(msg)+1,0);
printf(">>>>>>>>>>>>>>>>>>>>>> sent %d+%d bytes -> pullsock.%d retstr.(%s)\n",n,m,pullsock,retstr!=0?retstr:"");
if ( retstr != 0 )
{
free(retstr);
retval = 0;
}
}
nn_close(sock);
}
return(retval);
}*/
int32_t basilisk_swap_load(uint32_t requestid,uint32_t quoteid,bits256 *privkeyp,struct basilisk_request *rp,uint32_t *statebitsp,int32_t *optiondurationp) int32_t basilisk_swap_load(uint32_t requestid,uint32_t quoteid,bits256 *privkeyp,struct basilisk_request *rp,uint32_t *statebitsp,int32_t *optiondurationp)
{ {
@ -685,7 +788,7 @@ int32_t basilisk_swapiteration(struct basilisk_swap *swap,uint8_t *data,int32_t
} }
else if ( (swap->I.statebits & 0x2000) == 0 ) else if ( (swap->I.statebits & 0x2000) == 0 )
{ {
if ( (swap->I.aliceconfirms == 0 && swap->aliceunconf != 0) || LP_numconfirms(swap,&swap->alicepayment) >= swap->I.aliceconfirms ) if ( (swap->I.aliceconfirms == 0 && swap->aliceunconf != 0) || LP_numconfirms(swap,&swap->alicepayment,1) >= swap->I.aliceconfirms )
{ {
swap->I.statebits |= 0x2000; swap->I.statebits |= 0x2000;
printf("alicepayment confirmed\n"); printf("alicepayment confirmed\n");
@ -711,7 +814,7 @@ int32_t basilisk_swapiteration(struct basilisk_swap *swap,uint8_t *data,int32_t
tradebot_swap_balancingtrade(swap,1); tradebot_swap_balancingtrade(swap,1);
printf("Bob spends alicepayment aliceconfirms.%d\n",swap->I.aliceconfirms); printf("Bob spends alicepayment aliceconfirms.%d\n",swap->I.aliceconfirms);
swap->I.statebits |= 0x40000; swap->I.statebits |= 0x40000;
if ( LP_numconfirms(swap,&swap->bobspend) >= swap->I.aliceconfirms ) if ( LP_numconfirms(swap,&swap->bobspend,1) >= swap->I.aliceconfirms )
{ {
printf("bobspend confirmed\n"); printf("bobspend confirmed\n");
swap->I.statebits |= 0x80000; swap->I.statebits |= 0x80000;
@ -734,7 +837,7 @@ int32_t basilisk_swapiteration(struct basilisk_swap *swap,uint8_t *data,int32_t
printf("Bob reclaimed own payment\n"); printf("Bob reclaimed own payment\n");
while ( 0 && (swap->I.statebits & 0x100000) == 0 ) // why wait for own tx? while ( 0 && (swap->I.statebits & 0x100000) == 0 ) // why wait for own tx?
{ {
if ( LP_numconfirms(swap,&swap->bobreclaim) >= 1 ) if ( LP_numconfirms(swap,&swap->bobreclaim,1) >= 1 )
{ {
printf("bobreclaim confirmed\n"); printf("bobreclaim confirmed\n");
swap->I.statebits |= 0x100000; swap->I.statebits |= 0x100000;
@ -762,7 +865,7 @@ int32_t basilisk_swapiteration(struct basilisk_swap *swap,uint8_t *data,int32_t
} }
else if ( (swap->I.statebits & 0x400) == 0 ) else if ( (swap->I.statebits & 0x400) == 0 )
{ {
if ( basilisk_istrustedbob(swap) != 0 || (swap->I.bobconfirms == 0 && swap->depositunconf != 0) || LP_numconfirms(swap,&swap->bobdeposit) >= swap->I.bobconfirms ) if ( basilisk_istrustedbob(swap) != 0 || (swap->I.bobconfirms == 0 && swap->depositunconf != 0) || LP_numconfirms(swap,&swap->bobdeposit,1) >= swap->I.bobconfirms )
{ {
printf("bobdeposit confirmed\n"); printf("bobdeposit confirmed\n");
swap->I.statebits |= 0x400; swap->I.statebits |= 0x400;
@ -786,7 +889,7 @@ int32_t basilisk_swapiteration(struct basilisk_swap *swap,uint8_t *data,int32_t
} }
else if ( (swap->I.statebits & 0x10000) == 0 ) else if ( (swap->I.statebits & 0x10000) == 0 )
{ {
if ( basilisk_istrustedbob(swap) != 0 || (swap->I.bobconfirms == 0 && swap->paymentunconf != 0) || LP_numconfirms(swap,&swap->bobpayment) >= swap->I.bobconfirms ) if ( basilisk_istrustedbob(swap) != 0 || (swap->I.bobconfirms == 0 && swap->paymentunconf != 0) || LP_numconfirms(swap,&swap->bobpayment,1) >= swap->I.bobconfirms )
{ {
printf("bobpayment confirmed\n"); printf("bobpayment confirmed\n");
swap->I.statebits |= 0x10000; swap->I.statebits |= 0x10000;
@ -803,7 +906,7 @@ int32_t basilisk_swapiteration(struct basilisk_swap *swap,uint8_t *data,int32_t
else if ( (swap->I.statebits & 0x40000) == 0 ) else if ( (swap->I.statebits & 0x40000) == 0 )
{ {
int32_t numconfs; int32_t numconfs;
if ( (numconfs= LP_numconfirms(swap,&swap->alicespend)) >= swap->I.bobconfirms ) if ( (numconfs= LP_numconfirms(swap,&swap->alicespend,1)) >= swap->I.bobconfirms )
{ {
for (j=datalen=0; j<32; j++) for (j=datalen=0; j<32; j++)
data[datalen++] = swap->I.privAm.bytes[j]; data[datalen++] = swap->I.privAm.bytes[j];

130
iguana/exchanges/LP_swap.c

@ -400,35 +400,56 @@ int32_t LP_mostprivs_verify(struct basilisk_swap *swap,uint8_t *data,int32_t dat
int32_t LP_waitfor(int32_t pairsock,struct basilisk_swap *swap,int32_t timeout,int32_t (*verify)(struct basilisk_swap *swap,uint8_t *data,int32_t datalen)) int32_t LP_waitfor(int32_t pairsock,struct basilisk_swap *swap,int32_t timeout,int32_t (*verify)(struct basilisk_swap *swap,uint8_t *data,int32_t datalen))
{ {
void *data; int32_t datalen,retval = -1; uint32_t expiration = (uint32_t)time(NULL) + timeout; struct nn_pollfd pfd; void *data; int32_t datalen,retval = -1; uint32_t expiration = (uint32_t)time(NULL) + timeout;
while ( time(NULL) < expiration ) while ( time(NULL) < expiration )
{ {
//printf("start wait\n"); memset(&pfd,0,sizeof(pfd));
if ( (datalen= nn_recv(pairsock,&data,NN_MSG,0)) >= 0 ) pfd.fd = pairsock;
pfd.events = NN_POLLIN;
if ( nn_poll(&pfd,1,1) > 0 )
{ {
//printf("wait for got.%d\n",datalen); //printf("start wait\n");
retval = (*verify)(swap,data,datalen); if ( (datalen= nn_recv(pairsock,&data,NN_MSG,0)) >= 0 )
nn_freemsg(data); {
//printf("retval.%d\n",retval); //printf("wait for got.%d\n",datalen);
return(retval); retval = (*verify)(swap,data,datalen);
} // else printf("error nn_recv\n"); nn_freemsg(data);
//printf("retval.%d\n",retval);
return(retval);
} // else printf("error nn_recv\n");
}
} }
printf("waitfor timedout\n"); printf("waitfor timedout\n");
return(retval); return(retval);
} }
int32_t swap_nn_send(int32_t sock,uint8_t *data,int32_t datalen,uint32_t flags,int32_t timeout)
{
struct nn_pollfd pfd; int32_t i;
for (i=0; i<timeout*1000; i++)
{
memset(&pfd,0,sizeof(pfd));
pfd.fd = sock;
pfd.events = NN_POLLOUT;
if ( nn_poll(&pfd,1,1) > 0 )
return(nn_send(sock,data,datalen,flags));
usleep(1000);
}
return(-1);
}
int32_t LP_waitsend(char *statename,int32_t timeout,int32_t pairsock,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen,int32_t (*verify)(struct basilisk_swap *swap,uint8_t *data,int32_t datalen),int32_t (*datagen)(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)) int32_t LP_waitsend(char *statename,int32_t timeout,int32_t pairsock,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen,int32_t (*verify)(struct basilisk_swap *swap,uint8_t *data,int32_t datalen),int32_t (*datagen)(struct basilisk_swap *swap,uint8_t *data,int32_t maxlen))
{ {
int32_t datalen,sendlen,retval = -1; int32_t datalen,sendlen,retval = -1;
printf("waitsend.%s\n",statename); //printf("waitsend.%s timeout.%d\n",statename,timeout);
if ( LP_waitfor(pairsock,swap,timeout,verify) == 0 ) if ( LP_waitfor(pairsock,swap,timeout,verify) == 0 )
{ {
printf("waited for %s\n",statename); //printf("waited for %s\n",statename);
if ( (datalen= (*datagen)(swap,data,maxlen)) > 0 ) if ( (datalen= (*datagen)(swap,data,maxlen)) > 0 )
{ {
if ( (sendlen= nn_send(pairsock,data,datalen,0)) == datalen ) if ( (sendlen= swap_nn_send(pairsock,data,datalen,0,timeout)) == datalen )
{ {
printf("sent.%d after waitfor.%s\n",sendlen,statename); //printf("sent.%d after waitfor.%s\n",sendlen,statename);
retval = 0; retval = 0;
} else printf("send %s error\n",statename); } else printf("send %s error\n",statename);
} else printf("%s datagen no data\n",statename); } else printf("%s datagen no data\n",statename);
@ -442,8 +463,8 @@ int32_t LP_sendwait(char *statename,int32_t timeout,int32_t pairsock,struct basi
//printf("sendwait.%s\n",statename); //printf("sendwait.%s\n",statename);
if ( (datalen= (*datagen)(swap,data,maxlen)) > 0 ) if ( (datalen= (*datagen)(swap,data,maxlen)) > 0 )
{ {
//printf("generated %d for %s\n",datalen,statename); //printf("generated %d for %s, timeout.%d\n",datalen,statename,timeout);
if ( (sendlen= nn_send(pairsock,data,datalen,0)) == datalen ) if ( (sendlen= swap_nn_send(pairsock,data,datalen,0,timeout)) == datalen )
{ {
//printf("sendwait.%s sent %d\n",statename,sendlen); //printf("sendwait.%s sent %d\n",statename,sendlen);
if ( LP_waitfor(pairsock,swap,timeout,verify) == 0 ) if ( LP_waitfor(pairsock,swap,timeout,verify) == 0 )
@ -451,7 +472,7 @@ int32_t LP_sendwait(char *statename,int32_t timeout,int32_t pairsock,struct basi
//printf("waited! sendwait.%s sent %d\n",statename,sendlen); //printf("waited! sendwait.%s sent %d\n",statename,sendlen);
retval = 0; retval = 0;
} else printf("didnt get %s\n",statename); } else printf("didnt get %s\n",statename);
} else printf("send pubkeys error\n"); } else printf("send %s error\n",statename);
} else printf("no datagen for %s\n",statename); } else printf("no datagen for %s\n",statename);
return(retval); return(retval);
} }
@ -489,7 +510,7 @@ struct basilisk_rawtx *LP_swapdata_rawtx(struct basilisk_swap *swap,uint8_t *dat
int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys) int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys)
{ {
bits256 otherhash,myhash,txid; int32_t i,offset=0,datalen=0,retval=-1,hexlen,n; uint8_t *data; cJSON *txobj,*skey,*vouts,*vout; char *hexstr,redeemaddr[64],checkaddr[64]; uint32_t quoteid,msgbits; bits256 otherhash,myhash,txid; int64_t txfee; int32_t i,offset=0,datalen=0,retval=-1,hexlen,n; uint8_t *data; cJSON *txobj,*skey,*vouts,*vout; char *hexstr,redeemaddr[64],checkaddr[64]; uint32_t quoteid,msgbits;
for (i=0; i<32; i++) for (i=0; i<32; i++)
otherhash.bytes[i] = recvbuf[offset++]; otherhash.bytes[i] = recvbuf[offset++];
for (i=0; i<32; i++) for (i=0; i<32; i++)
@ -545,23 +566,37 @@ int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct ba
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 ) if ( (txobj= bitcoin_data2json(rawtx->coin->taddr,rawtx->coin->pubtype,rawtx->coin->p2shtype,rawtx->coin->isPoS,height,&rawtx->I.signedtxid,&rawtx->msgtx,rawtx->extraspace,sizeof(rawtx->extraspace),data,datalen,0,suppress_pubkeys)) != 0 )
{ {
rawtx->I.actualtxid = rawtx->I.signedtxid; rawtx->I.actualtxid = rawtx->I.signedtxid;
//char str[65]; printf("got %s txid.%s (%s)\n",rawtx->name,bits256_str(str,rawtx->I.signedtxid),jprint(txobj,0));
rawtx->I.locktime = rawtx->msgtx.lock_time; rawtx->I.locktime = rawtx->msgtx.lock_time;
if ( (vouts= jarray(&n,txobj,"vout")) != 0 && v < n ) if ( (vouts= jarray(&n,txobj,"vout")) != 0 && v < n )
{ {
vout = jitem(vouts,v); vout = jitem(vouts,v);
if ( j64bits(vout,"satoshis") == rawtx->I.amount && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 ) if ( strcmp("BTC",rawtx->coin->symbol) == 0 && rawtx == &swap->otherfee )
txfee = LP_MIN_TXFEE;
else
{
if ( strcmp(rawtx->coin->symbol,swap->bobcoin.symbol) == 0 )
txfee = swap->I.Btxfee;
else if ( strcmp(rawtx->coin->symbol,swap->alicecoin.symbol) == 0 )
txfee = swap->I.Atxfee;
else txfee = LP_MIN_TXFEE;
}
if ( j64bits(vout,"satoshis") >= rawtx->I.amount && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 )
{ {
if ( (hexlen= (int32_t)strlen(hexstr) >> 1) < sizeof(rawtx->spendscript) ) if ( (hexlen= (int32_t)strlen(hexstr) >> 1) < sizeof(rawtx->spendscript) )
{ {
decode_hex(rawtx->spendscript,hexlen,hexstr); decode_hex(rawtx->spendscript,hexlen,hexstr);
rawtx->I.spendlen = hexlen; rawtx->I.spendlen = hexlen;
bitcoin_address(rawtx->p2shaddr,rawtx->coin->taddr,rawtx->coin->p2shtype,rawtx->spendscript,hexlen);
//if ( swap != 0 ) //if ( swap != 0 )
// basilisk_txlog(swap->myinfoptr,swap,rawtx,-1); // bobdeposit, bobpayment or alicepayment // basilisk_txlog(swap->myinfoptr,swap,rawtx,-1); // bobdeposit, bobpayment or alicepayment
retval = 0; retval = 0;
if ( rawtx == &swap->otherfee )
{
char str[65];
LP_swap_coinaddr(swap,rawtx->coin,rawtx->p2shaddr,data,datalen);
printf("got %s txid.%s (%s) -> %s\n",rawtx->name,bits256_str(str,rawtx->I.signedtxid),jprint(txobj,0),rawtx->p2shaddr);
} else bitcoin_address(rawtx->p2shaddr,rawtx->coin->taddr,rawtx->coin->p2shtype,rawtx->spendscript,hexlen);
} }
} else printf("%s ERROR.(%s)\n",rawtx->name,jprint(txobj,0)); } else printf("%s ERROR.(%s) txfees.[%.8f %.8f: %.8f] amount.%.8f -> %.8f\n",rawtx->name,jprint(txobj,0),dstr(swap->I.Atxfee),dstr(swap->I.Btxfee),dstr(txfee),dstr(rawtx->I.amount),dstr(rawtx->I.amount)-dstr(txfee));
} }
free_json(txobj); free_json(txobj);
} }
@ -659,14 +694,14 @@ int32_t LP_swapwait(uint32_t requestid,uint32_t quoteid,int32_t duration,int32_t
void LP_bobloop(void *_swap) void LP_bobloop(void *_swap)
{ {
uint8_t *data; int32_t maxlen,n; uint32_t expiration; struct basilisk_swap *swap = _swap; uint8_t *data; int32_t maxlen,m,n; uint32_t expiration; struct basilisk_swap *swap = _swap;
fprintf(stderr,"start swap iambob\n"); fprintf(stderr,"start swap iambob\n");
maxlen = 1024*1024 + sizeof(*swap); maxlen = 1024*1024 + sizeof(*swap);
data = malloc(maxlen); data = malloc(maxlen);
expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT; expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT;
if ( swap != 0 ) if ( swap != 0 )
{ {
if ( LP_waitsend("pubkeys",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) if ( LP_waitsend("pubkeys",60,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 )
printf("error waitsend pubkeys\n"); printf("error waitsend pubkeys\n");
else if ( LP_waitsend("choosei",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 ) else if ( LP_waitsend("choosei",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 )
printf("error waitsend choosei\n"); printf("error waitsend choosei\n");
@ -681,11 +716,11 @@ void LP_bobloop(void *_swap)
basilisk_bobdeposit_refund(swap,swap->I.putduration); basilisk_bobdeposit_refund(swap,swap->I.putduration);
//printf("depositlen.%d\n",swap->bobdeposit.I.datalen); //printf("depositlen.%d\n",swap->bobdeposit.I.datalen);
LP_swapsfp_update(&swap->I.req); LP_swapsfp_update(&swap->I.req);
if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT,LP_verify_otherfee) < 0 ) if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT*3,LP_verify_otherfee) < 0 )
printf("error waiting for alicefee\n"); printf("error waiting for alicefee\n");
else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x200,data,maxlen,&swap->bobdeposit,0x100,0) == 0 ) else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x200,data,maxlen,&swap->bobdeposit,0x100,0) == 0 )
printf("error sending bobdeposit\n"); printf("error sending bobdeposit\n");
else if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT,LP_verify_alicepayment) < 0 ) else if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT*3,LP_verify_alicepayment) < 0 )
printf("error waiting for alicepayment\n"); printf("error waiting for alicepayment\n");
else else
{ {
@ -693,7 +728,10 @@ void LP_bobloop(void *_swap)
printf("error bobscripts payment\n"); printf("error bobscripts payment\n");
else else
{ {
while ( (n= LP_numconfirms(swap,&swap->alicepayment)) < 1 ) // sync with alice if ( strcmp(swap->alicecoin.symbol,"BTC") == 0 )
m = 0;
else m = 1;
while ( (n= LP_numconfirms(swap,&swap->alicepayment,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 to be confirmed.%d %s %s\n",n,1,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid));
sleep(3); sleep(3);
@ -717,14 +755,14 @@ void LP_bobloop(void *_swap)
void LP_aliceloop(void *_swap) void LP_aliceloop(void *_swap)
{ {
uint8_t *data; int32_t maxlen,n; uint32_t expiration; struct basilisk_swap *swap = _swap; uint8_t *data; int32_t maxlen,n,m; uint32_t expiration; struct basilisk_swap *swap = _swap;
maxlen = 1024*1024 + sizeof(*swap); maxlen = 1024*1024 + sizeof(*swap);
data = malloc(maxlen); data = malloc(maxlen);
expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT; expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT;
if ( swap != 0 ) if ( swap != 0 )
{ {
fprintf(stderr,"start swap iamalice pair.%d\n",swap->N.pair); fprintf(stderr,"start swap iamalice pair.%d\n",swap->N.pair);
if ( LP_sendwait("pubkeys",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) if ( LP_sendwait("pubkeys",60,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 )
printf("error LP_sendwait pubkeys\n"); printf("error LP_sendwait pubkeys\n");
else if ( LP_sendwait("choosei",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 ) else if ( LP_sendwait("choosei",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_choosei_verify,LP_choosei_data) < 0 )
printf("error LP_sendwait choosei\n"); printf("error LP_sendwait choosei\n");
@ -737,30 +775,33 @@ void LP_aliceloop(void *_swap)
LP_swapsfp_update(&swap->I.req); LP_swapsfp_update(&swap->I.req);
if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x80,data,maxlen,&swap->myfee,0x40,0) == 0 ) if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x80,data,maxlen,&swap->myfee,0x40,0) == 0 )
printf("error sending alicefee\n"); printf("error sending alicefee\n");
else if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT,LP_verify_bobdeposit) < 0 ) else if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT*3,LP_verify_bobdeposit) < 0 )
printf("error waiting for bobdeposit\n"); printf("error waiting for bobdeposit\n");
else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0) == 0 ) else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0) == 0 )
printf("error sending alicepayment\n"); printf("error sending alicepayment\n");
else else
{ {
while ( (n= LP_numconfirms(swap,&swap->alicepayment)) < 1 ) if ( strcmp(swap->alicecoin.symbol,"BTC") == 0 )
m = 0;
else m = 1;
while ( (n= LP_numconfirms(swap,&swap->alicepayment,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 to be confirmed.%d %s %s\n",n,1,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid));
sleep(LP_SWAPSTEP_TIMEOUT); sleep(LP_SWAPSTEP_TIMEOUT);
} }
swap->sentflag = 1; swap->sentflag = 1;
if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT,LP_verify_bobpayment) < 0 ) if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT*3,LP_verify_bobpayment) < 0 )
printf("error waiting for bobpayment\n"); printf("error waiting for bobpayment\n");
else else
{ {
while ( (n= LP_numconfirms(swap,&swap->bobpayment)) < swap->I.bobconfirms ) while ( (n= LP_numconfirms(swap,&swap->bobpayment,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 to be confirmed.%d %s %s\n",n,swap->I.bobconfirms,swap->bobcoin.symbol,bits256_str(str,swap->bobpayment.I.signedtxid));
sleep(LP_SWAPSTEP_TIMEOUT); sleep(LP_SWAPSTEP_TIMEOUT);
} }
if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x20000,data,maxlen,&swap->alicespend,0x40000,0) == 0 ) if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x20000,data,maxlen,&swap->alicespend,0x40000,0) == 0 )
printf("error sending alicespend\n"); printf("error sending alicespend\n");
while ( (n= LP_numconfirms(swap,&swap->alicespend)) < swap->I.aliceconfirms ) while ( (n= LP_numconfirms(swap,&swap->alicespend,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 to be confirmed.%d %s %s\n",n,swap->I.aliceconfirms,swap->bobcoin.symbol,bits256_str(str,swap->alicespend.I.signedtxid));
sleep(LP_SWAPSTEP_TIMEOUT); sleep(LP_SWAPSTEP_TIMEOUT);
@ -775,7 +816,11 @@ void LP_aliceloop(void *_swap)
free(swap); free(swap);
} }
free(data); free(data);
nn_close(swap->N.pair); if ( swap->N.pair >= 0 )
{
nn_close(swap->N.pair);
swap->N.pair = -1;
}
} }
bits256 instantdex_derivekeypair(void *ctx,bits256 *newprivp,uint8_t pubkey[33],bits256 privkey,bits256 orderhash) bits256 instantdex_derivekeypair(void *ctx,bits256 *newprivp,uint8_t pubkey[33],bits256 privkey,bits256 orderhash)
@ -865,8 +910,8 @@ void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx *
rawtx->coin = coin; rawtx->coin = coin;
strcpy(rawtx->I.coinstr,coin->symbol); strcpy(rawtx->I.coinstr,coin->symbol);
rawtx->I.numconfirms = numconfirms; rawtx->I.numconfirms = numconfirms;
if ( (rawtx->I.amount= satoshis) < 10000 ) if ( (rawtx->I.amount= satoshis) < LP_MIN_TXFEE )
rawtx->I.amount = 10000; rawtx->I.amount = LP_MIN_TXFEE;
rawtx->I.vintype = vintype; // 0 -> std, 2 -> 2of2, 3 -> spend bobpayment, 4 -> spend bobdeposit rawtx->I.vintype = vintype; // 0 -> std, 2 -> 2of2, 3 -> spend bobpayment, 4 -> spend bobdeposit
rawtx->I.vouttype = vouttype; // 0 -> fee, 1 -> std, 2 -> 2of2, 3 -> bobpayment, 4 -> bobdeposit rawtx->I.vouttype = vouttype; // 0 -> fee, 1 -> std, 2 -> 2of2, 3 -> bobpayment, 4 -> bobdeposit
if ( rawtx->I.vouttype == 0 ) if ( rawtx->I.vouttype == 0 )
@ -893,6 +938,8 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256
{ {
//FILE *fp; char fname[512]; //FILE *fp; char fname[512];
uint8_t *alicepub33=0,*bobpub33=0; int32_t bobistrusted,aliceistrusted,jumblrflag=-2,x = -1; struct iguana_info *coin; uint8_t *alicepub33=0,*bobpub33=0; int32_t bobistrusted,aliceistrusted,jumblrflag=-2,x = -1; struct iguana_info *coin;
swap->I.Atxfee = qp->desttxfee;
swap->I.Btxfee = qp->txfee;
swap->I.putduration = swap->I.callduration = INSTANTDEX_LOCKTIME; swap->I.putduration = swap->I.callduration = INSTANTDEX_LOCKTIME;
if ( optionduration < 0 ) if ( optionduration < 0 )
swap->I.putduration -= optionduration; swap->I.putduration -= optionduration;
@ -900,10 +947,10 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256
swap->I.callduration += optionduration; swap->I.callduration += optionduration;
swap->I.bobsatoshis = swap->I.req.srcamount; swap->I.bobsatoshis = swap->I.req.srcamount;
swap->I.alicesatoshis = swap->I.req.destamount; swap->I.alicesatoshis = swap->I.req.destamount;
if ( (swap->I.bobinsurance= (swap->I.bobsatoshis / INSTANTDEX_INSURANCEDIV)) < 10000 ) if ( (swap->I.bobinsurance= (swap->I.bobsatoshis / INSTANTDEX_INSURANCEDIV)) < LP_MIN_TXFEE )
swap->I.bobinsurance = 10000; swap->I.bobinsurance = LP_MIN_TXFEE;
if ( (swap->I.aliceinsurance= (swap->I.alicesatoshis / INSTANTDEX_INSURANCEDIV)) < 10000 ) if ( (swap->I.aliceinsurance= (swap->I.alicesatoshis / INSTANTDEX_INSURANCEDIV)) < LP_MIN_TXFEE )
swap->I.aliceinsurance = 10000; swap->I.aliceinsurance = LP_MIN_TXFEE;
strcpy(swap->I.bobstr,swap->I.req.src); strcpy(swap->I.bobstr,swap->I.req.src);
strcpy(swap->I.alicestr,swap->I.req.dest); strcpy(swap->I.alicestr,swap->I.req.dest);
swap->I.started = (uint32_t)time(NULL); swap->I.started = (uint32_t)time(NULL);
@ -1011,10 +1058,11 @@ struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256
{ {
struct basilisk_swap *swap; bits256 pubkey25519; uint8_t pubkey33[33]; struct basilisk_swap *swap; bits256 pubkey25519; uint8_t pubkey33[33];
swap = calloc(1,sizeof(*swap)); swap = calloc(1,sizeof(*swap));
swap->I.req.quoteid = rp->quoteid;
swap->ctx = bitcoin_ctx(); swap->ctx = bitcoin_ctx();
vcalc_sha256(0,swap->I.orderhash.bytes,(uint8_t *)rp,sizeof(*rp)); vcalc_sha256(0,swap->I.orderhash.bytes,(uint8_t *)rp,sizeof(*rp));
swap->I.req = *rp; swap->I.req = *rp;
printf("basilisk_thread_start request.%u iambob.%d (%s/%s)\n",rp->requestid,iambob,rp->src,rp->dest); 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); bitcoin_pubkey33(swap->ctx,pubkey33,privkey);
pubkey25519 = curve25519(privkey,curve25519_basepoint9()); pubkey25519 = curve25519(privkey,curve25519_basepoint9());
swap->persistent_pubkey = pubkey25519; swap->persistent_pubkey = pubkey25519;

120
iguana/exchanges/LP_transaction.c

@ -30,7 +30,8 @@ bits256 LP_broadcast(char *txname,char *symbol,char *txbytes,bits256 expectedtxi
if ( is_hexstr(retstr,0) == 64 ) if ( is_hexstr(retstr,0) == 64 )
{ {
decode_hex(txid.bytes,32,retstr); decode_hex(txid.bytes,32,retstr);
sentflag = 1; if ( bits256_cmp(txid,expectedtxid) == 0 || (bits256_nonz(expectedtxid) == 0 && bits256_nonz(txid) != 0) )
sentflag = 1;
} }
else if ( (retjson= cJSON_Parse(retstr)) != 0 ) else if ( (retjson= cJSON_Parse(retstr)) != 0 )
{ {
@ -44,7 +45,7 @@ bits256 LP_broadcast(char *txname,char *symbol,char *txbytes,bits256 expectedtxi
} }
free_json(retjson); free_json(retjson);
} }
char str[65]; printf("[%s] %s RETSTR.(%s) %s.%s\n",txname,txbytes,retstr,symbol,bits256_str(str,txid)); char str[65]; printf("sentflag.%d [%s] %s RETSTR.(%s) %s.%s\n",sentflag,txname,txbytes,retstr,symbol,bits256_str(str,txid));
free(retstr); free(retstr);
} }
if ( sentflag != 0 ) if ( sentflag != 0 )
@ -230,7 +231,7 @@ int32_t iguana_interpreter(struct iguana_info *coin,cJSON *logarray,int64_t nLoc
return(0); return(0);
} }
bits256 iguana_str2priv(char *str) bits256 iguana_str2priv(uint8_t wiftaddr,char *str)
{ {
bits256 privkey; int32_t n; uint8_t addrtype; //struct iguana_waccount *wacct=0; struct iguana_waddress *waddr; bits256 privkey; int32_t n; uint8_t addrtype; //struct iguana_waccount *wacct=0; struct iguana_waddress *waddr;
memset(&privkey,0,sizeof(privkey)); memset(&privkey,0,sizeof(privkey));
@ -239,7 +240,7 @@ bits256 iguana_str2priv(char *str)
n = (int32_t)strlen(str) >> 1; n = (int32_t)strlen(str) >> 1;
if ( n == sizeof(bits256) && is_hexstr(str,sizeof(bits256)) > 0 ) if ( n == sizeof(bits256) && is_hexstr(str,sizeof(bits256)) > 0 )
decode_hex(privkey.bytes,sizeof(privkey),str); decode_hex(privkey.bytes,sizeof(privkey),str);
else if ( bitcoin_wif2priv(&addrtype,&privkey,str) != sizeof(bits256) ) else if ( bitcoin_wif2priv(wiftaddr,&addrtype,&privkey,str) != sizeof(bits256) )
{ {
//if ( (waddr= iguana_waddresssearch(&wacct,str)) != 0 ) //if ( (waddr= iguana_waddresssearch(&wacct,str)) != 0 )
// privkey = waddr->privkey; // privkey = waddr->privkey;
@ -393,7 +394,7 @@ int64_t iguana_lockval(int32_t finalized,int64_t locktime)
return(lockval); return(lockval);
} }
int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,struct iguana_msgtx *msgtx,char **signedtxp,bits256 *signedtxidp,struct vin_info *V,int32_t numinputs,char *rawtx,cJSON *vins,cJSON *privkeysjson) 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 = 65536; char *privkeystr,*signedtx = 0; bits256 privkeys[64],privkey,txid; cJSON *item; cJSON *txobj = 0;
maxsize = 1000000; maxsize = 1000000;
@ -428,7 +429,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t taddr,uint8_t p
privkeystr = jstr(item,0); privkeystr = jstr(item,0);
if ( privkeystr == 0 || privkeystr[0] == 0 ) if ( privkeystr == 0 || privkeystr[0] == 0 )
continue; continue;
privkeys[i] = privkey = iguana_str2priv(privkeystr); privkeys[i] = privkey = iguana_str2priv(wiftaddr,privkeystr);
bitcoin_pubkey33(ctx,pubkeys[i],privkey); bitcoin_pubkey33(ctx,pubkeys[i],privkey);
//if ( bits256_nonz(privkey) != 0 ) //if ( bits256_nonz(privkey) != 0 )
// iguana_ensure_privkey(coin,privkey); // iguana_ensure_privkey(coin,privkey);
@ -523,7 +524,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t taddr,uint8_t p
return(complete); return(complete);
} }
char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privkey,bits256 *privkey2p,uint8_t *redeemscript,int32_t redeemlen,uint8_t *userdata,int32_t userdatalen,bits256 utxotxid,int32_t vout,char *destaddr,uint8_t *pubkey33,int32_t finalseqid,uint32_t expiration,int64_t *destamountp,uint64_t satoshis,char *changeaddr,char *vinaddr,int32_t suppress_pubkeys) char *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,tmpaddr[64],hexstr[999],wifstr[128],txdestaddr[64],_destaddr[64]; uint8_t spendscript[512],addrtype,rmd160[20]; cJSON *txobj,*vins,*item,*privkeys; int32_t completed,spendlen,ignore_cltverr=1; struct vin_info V[2]; uint32_t timestamp,locktime = 0,sequenceid = 0xffffffff * finalseqid; bits256 txid; uint64_t value,change = 0; struct iguana_msgtx msgtx;
*destamountp = 0; *destamountp = 0;
@ -545,12 +546,37 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch
#endif #endif
if ( satoshis != 0 ) if ( satoshis != 0 )
{ {
if ( value < satoshis+txfee )
{
if ( satoshis > value-txfee/2 )
{
satoshis = value - txfee;
printf("reduce satoshis by txfee %.8f to %.8f\n",dstr(txfee),dstr(satoshis));
}
else
{
printf("utxo %.8f too small for %.8f + %.8f\n",dstr(value),dstr(satoshis),dstr(txfee));
return(0);
}
}
if ( value > satoshis+txfee ) if ( value > satoshis+txfee )
change = value - (satoshis + txfee); change = value - (satoshis + txfee);
printf("utxo %.8f, destamount %.8f change %.8f txfee %.8f\n",dstr(value),dstr(satoshis),dstr(change),dstr(txfee)); printf("utxo %.8f, destamount %.8f change %.8f txfee %.8f\n",dstr(value),dstr(satoshis),dstr(change),dstr(txfee));
} else if ( value > txfee ) } else if ( value > txfee )
satoshis = value - txfee; satoshis = value - txfee;
else printf("unexpected small value %.8f vs txfee %.8f\n",dstr(value),dstr(txfee)); else
{
printf("unexpected small value %.8f vs txfee %.8f\n",dstr(value),dstr(txfee));
change = 0;
satoshis = value >> 1;
txfee = (value - satoshis);
printf("unexpected small value %.8f vs txfee %.8f -> %.8f %.8f\n",dstr(value),dstr(txfee),dstr(satoshis),dstr(txfee));
}
if ( change < 6000 )
{
satoshis += change;
change = 0;
}
if ( destamountp != 0 ) if ( destamountp != 0 )
*destamountp = satoshis; *destamountp = satoshis;
timestamp = (uint32_t)time(NULL); timestamp = (uint32_t)time(NULL);
@ -560,13 +586,13 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch
{ {
V[0].signers[1].privkey = *privkey2p; V[0].signers[1].privkey = *privkey2p;
bitcoin_pubkey33(ctx,V[0].signers[1].pubkey,*privkey2p); bitcoin_pubkey33(ctx,V[0].signers[1].pubkey,*privkey2p);
bitcoin_priv2wif(wifstr,*privkey2p,wiftype); bitcoin_priv2wif(wiftaddr,wifstr,*privkey2p,wiftype);
jaddistr(privkeys,wifstr); jaddistr(privkeys,wifstr);
V[0].N = V[0].M = 2; V[0].N = V[0].M = 2;
} else V[0].N = V[0].M = 1; } else V[0].N = V[0].M = 1;
V[0].signers[0].privkey = privkey; V[0].signers[0].privkey = privkey;
bitcoin_pubkey33(ctx,V[0].signers[0].pubkey,privkey); bitcoin_pubkey33(ctx,V[0].signers[0].pubkey,privkey);
bitcoin_priv2wif(wifstr,privkey,wiftype); bitcoin_priv2wif(wiftaddr,wifstr,privkey,wiftype);
jaddistr(privkeys,wifstr); jaddistr(privkeys,wifstr);
V[0].suppress_pubkeys = suppress_pubkeys; V[0].suppress_pubkeys = suppress_pubkeys;
V[0].ignore_cltverr = ignore_cltverr; V[0].ignore_cltverr = ignore_cltverr;
@ -631,7 +657,7 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch
completed = 0; completed = 0;
memset(signedtxidp,0,sizeof(*signedtxidp)); memset(signedtxidp,0,sizeof(*signedtxidp));
//printf("locktime.%u sequenceid.%x rawtx.(%s) vins.(%s)\n",locktime,sequenceid,rawtxbytes,jprint(vins,0)); //printf("locktime.%u sequenceid.%x rawtx.(%s) vins.(%s)\n",locktime,sequenceid,rawtxbytes,jprint(vins,0));
if ( (completed= iguana_signrawtransaction(ctx,symbol,taddr,pubtype,p2shtype,isPoS,1000000,&msgtx,&signedtx,signedtxidp,V,1,rawtxbytes,vins,privkeys)) < 0 ) if ( (completed= iguana_signrawtransaction(ctx,symbol,wiftaddr,taddr,pubtype,p2shtype,isPoS,1000000,&msgtx,&signedtx,signedtxidp,V,1,rawtxbytes,vins,privkeys)) < 0 )
//if ( (signedtx= LP_signrawtx(symbol,signedtxidp,&completed,vins,rawtxbytes,privkeys,V)) == 0 ) //if ( (signedtx= LP_signrawtx(symbol,signedtxidp,&completed,vins,rawtxbytes,privkeys,V)) == 0 )
printf("couldnt sign transaction.%s %s\n",name,bits256_str(str,*signedtxidp)); printf("couldnt sign transaction.%s %s\n",name,bits256_str(str,*signedtxidp));
else if ( completed == 0 ) else if ( completed == 0 )
@ -660,9 +686,11 @@ int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pub
bitcoin_address(changeaddr,coin->taddr,coin->pubtype,changermd160,20); bitcoin_address(changeaddr,coin->taddr,coin->pubtype,changermd160,20);
//printf("changeaddr.(%s) vs destaddr.(%s)\n",changeaddr,rawtx->I.destaddr); //printf("changeaddr.(%s) vs destaddr.(%s)\n",changeaddr,rawtx->I.destaddr);
} }
if ( strcmp(str,"myfee") == 0 && strcmp(coin->symbol,"BTC") == 0 )
txfee = LP_MIN_TXFEE;
for (iter=0; iter<2; iter++) for (iter=0; iter<2; iter++)
{ {
if ( (signedtx= basilisk_swap_bobtxspend(&rawtx->I.signedtxid,iter == 0 ? txfee : newtxfee,str,coin->symbol,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,ctx,privkey,0,0,0,0,0,rawtx->utxotxid,rawtx->utxovout,rawtx->I.destaddr,pubkey33,1,0,&destamount,rawtx->I.amount,changeaddr,vinaddr,rawtx->I.suppress_pubkeys)) != 0 ) if ( (signedtx= basilisk_swap_bobtxspend(&rawtx->I.signedtxid,iter == 0 ? txfee : newtxfee,str,coin->symbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,ctx,privkey,0,0,0,0,0,rawtx->utxotxid,rawtx->utxovout,rawtx->I.destaddr,pubkey33,1,0,&destamount,rawtx->I.amount,changeaddr,vinaddr,rawtx->I.suppress_pubkeys)) != 0 )
{ {
rawtx->I.datalen = (int32_t)strlen(signedtx) >> 1; rawtx->I.datalen = (int32_t)strlen(signedtx) >> 1;
if ( rawtx->I.datalen <= sizeof(rawtx->txbytes) ) if ( rawtx->I.datalen <= sizeof(rawtx->txbytes) )
@ -675,18 +703,16 @@ int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pub
if ( strcmp(coin->symbol,"BTC") != 0 ) if ( strcmp(coin->symbol,"BTC") != 0 )
return(retval); return(retval);
len = rawtx->I.datalen; len = rawtx->I.datalen;
if ( coin->estimatedrate == 0. ) newtxfee = LP_txfeecalc(coin->symbol,0);
coin->estimatedrate = LP_getestimatedrate(coin->symbol);
newtxfee = coin->estimatedrate * len;
if ( newtxfee < LP_MIN_TXFEE )
newtxfee = LP_MIN_TXFEE;
printf("txfee %.8f -> newtxfee %.8f\n",dstr(txfee),dstr(newtxfee)); printf("txfee %.8f -> newtxfee %.8f\n",dstr(txfee),dstr(newtxfee));
} else break; } else break;
if ( strcmp(str,"myfee") == 0 )
break;
} }
return(retval); return(retval);
} }
int32_t basilisk_rawtx_sign(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,struct basilisk_swap *swap,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr,uint8_t *changermd160,char *vinaddr) int32_t basilisk_rawtx_sign(char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,struct basilisk_swap *swap,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr,uint8_t *changermd160,char *vinaddr)
{ {
char *signedtx,*changeaddr = 0,_changeaddr[64]; int64_t txfee,newtxfee=0,destamount; uint32_t timestamp,locktime=0,sequenceid = 0xffffffff; int32_t iter,retval = -1; double estimatedrate; char *signedtx,*changeaddr = 0,_changeaddr[64]; int64_t txfee,newtxfee=0,destamount; uint32_t timestamp,locktime=0,sequenceid = 0xffffffff; int32_t iter,retval = -1; double estimatedrate;
//char str2[65]; printf("%s rawtxsign.(%s/v%d)\n",dest->name,bits256_str(str2,dest->utxotxid),dest->utxovout); //char str2[65]; printf("%s rawtxsign.(%s/v%d)\n",dest->name,bits256_str(str2,dest->utxotxid),dest->utxovout);
@ -695,7 +721,7 @@ int32_t basilisk_rawtx_sign(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p
locktime = swap->bobdeposit.I.locktime + 1, sequenceid = 0; locktime = swap->bobdeposit.I.locktime + 1, sequenceid = 0;
else if ( dest == &swap->bobreclaim ) else if ( dest == &swap->bobreclaim )
locktime = swap->bobpayment.I.locktime + 1, sequenceid = 0; locktime = swap->bobpayment.I.locktime + 1, sequenceid = 0;
txfee = strcmp("BTC",symbol) == 0 ? 0 : 10000; txfee = strcmp("BTC",symbol) == 0 ? 0 : LP_MIN_TXFEE;
if ( changermd160 != 0 ) if ( changermd160 != 0 )
{ {
changeaddr = _changeaddr; changeaddr = _changeaddr;
@ -704,7 +730,7 @@ int32_t basilisk_rawtx_sign(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p
} }
for (iter=0; iter<2; iter++) for (iter=0; iter<2; iter++)
{ {
if ( (signedtx= basilisk_swap_bobtxspend(&dest->I.signedtxid,iter == 0 ? txfee : newtxfee,rawtx->name,symbol,taddr,pubtype,p2shtype,isPoS,wiftype,swap->ctx,privkey,privkey2,rawtx->redeemscript,rawtx->I.redeemlen,userdata,userdatalen,dest->utxotxid,dest->utxovout,dest->I.destaddr,rawtx->I.pubkey33,1,0,&destamount,rawtx->I.amount,changeaddr,vinaddr,dest->I.suppress_pubkeys)) != 0 ) if ( (signedtx= basilisk_swap_bobtxspend(&dest->I.signedtxid,iter == 0 ? txfee : newtxfee,rawtx->name,symbol,wiftaddr,taddr,pubtype,p2shtype,isPoS,wiftype,swap->ctx,privkey,privkey2,rawtx->redeemscript,rawtx->I.redeemlen,userdata,userdatalen,dest->utxotxid,dest->utxovout,dest->I.destaddr,rawtx->I.pubkey33,1,0,&destamount,rawtx->I.amount,changeaddr,vinaddr,dest->I.suppress_pubkeys)) != 0 )
{ {
dest->I.datalen = (int32_t)strlen(signedtx) >> 1; dest->I.datalen = (int32_t)strlen(signedtx) >> 1;
if ( dest->I.datalen <= sizeof(dest->txbytes) ) if ( dest->I.datalen <= sizeof(dest->txbytes) )
@ -740,7 +766,7 @@ int32_t basilisk_alicescript(uint8_t *redeemscript,int32_t *redeemlenp,uint8_t *
return(n); return(n);
} }
char *basilisk_swap_Aspend(char *name,char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privAm,bits256 privBn,bits256 utxotxid,int32_t vout,uint8_t pubkey33[33],uint32_t expiration,int64_t *destamountp,char *vinaddr) char *basilisk_swap_Aspend(char *name,char *symbol,uint64_t Atxfee,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privAm,bits256 privBn,bits256 utxotxid,int32_t vout,uint8_t pubkey33[33],uint32_t expiration,int64_t *destamountp,char *vinaddr)
{ {
char msigaddr[64],*signedtx = 0; int32_t spendlen,redeemlen; uint8_t tmp33[33],redeemscript[512],spendscript[128]; bits256 pubAm,pubBn,signedtxid; uint64_t txfee; char msigaddr[64],*signedtx = 0; int32_t spendlen,redeemlen; uint8_t tmp33[33],redeemscript[512],spendscript[128]; bits256 pubAm,pubBn,signedtxid; uint64_t txfee;
if ( bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 ) if ( bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 )
@ -758,8 +784,13 @@ char *basilisk_swap_Aspend(char *name,char *symbol,uint8_t taddr,uint8_t pubtype
rev = privBn; rev = privBn;
for (i=0; i<32; i++) for (i=0; i<32; i++)
privBn.bytes[i] = rev.bytes[31 - i];*/ privBn.bytes[i] = rev.bytes[31 - i];*/
txfee = LP_txfee(symbol); if ( (txfee= Atxfee) == 0 )
signedtx = basilisk_swap_bobtxspend(&signedtxid,txfee,name,symbol,taddr,pubtype,p2shtype,isPoS,wiftype,ctx,privAm,&privBn,redeemscript,redeemlen,0,0,utxotxid,vout,0,pubkey33,1,expiration,destamountp,0,0,vinaddr,1); {
if ( (txfee= LP_getestimatedrate(symbol) * LP_AVETXSIZE) < LP_MIN_TXFEE )
txfee = LP_MIN_TXFEE;
}
//txfee = LP_txfee(symbol);
signedtx = basilisk_swap_bobtxspend(&signedtxid,txfee,name,symbol,wiftaddr,taddr,pubtype,p2shtype,isPoS,wiftype,ctx,privAm,&privBn,redeemscript,redeemlen,0,0,utxotxid,vout,0,pubkey33,1,expiration,destamountp,0,0,vinaddr,1);
} }
return(signedtx); return(signedtx);
} }
@ -816,6 +847,7 @@ int32_t basilisk_swap_getsigscript(char *symbol,uint8_t *script,int32_t maxlen,b
return(scriptlen); return(scriptlen);
} }
#ifdef notnow
bits256 _LP_swap_spendtxid(char *symbol,char *destaddr,char *coinaddr,bits256 utxotxid,int32_t vout) bits256 _LP_swap_spendtxid(char *symbol,char *destaddr,char *coinaddr,bits256 utxotxid,int32_t vout)
{ {
char *retstr,*addr; cJSON *array,*item,*array2; int32_t i,n,m; bits256 spendtxid,txid; char *retstr,*addr; cJSON *array,*item,*array2; int32_t i,n,m; bits256 spendtxid,txid;
@ -868,6 +900,7 @@ bits256 _LP_swap_spendtxid(char *symbol,char *destaddr,char *coinaddr,bits256 ut
} }
return(spendtxid); return(spendtxid);
} }
#endif
bits256 LP_swap_spendtxid(char *symbol,char *destaddr,bits256 utxotxid,int32_t vout) bits256 LP_swap_spendtxid(char *symbol,char *destaddr,bits256 utxotxid,int32_t vout)
{ {
@ -880,12 +913,12 @@ bits256 LP_swap_spendtxid(char *symbol,char *destaddr,bits256 utxotxid,int32_t v
printf("spend of %s/v%d detected\n",bits256_str(str,utxotxid),vout); printf("spend of %s/v%d detected\n",bits256_str(str,utxotxid),vout);
return(spendtxid); return(spendtxid);
//char str[65]; printf("swap %s spendtxid.(%s)\n",symbol,bits256_str(str,utxotxid)); //char str[65]; printf("swap %s spendtxid.(%s)\n",symbol,bits256_str(str,utxotxid));
if ( 0 && strcmp("BTC",symbol) == 0 ) if ( (0) && strcmp("BTC",symbol) == 0 )
{ {
//[{"type":"sent","confirmations":379,"height":275311,"timestamp":1492084664,"txid":"8703c5517bc57db38134058370a14e99b8e662b99ccefa2061dea311bbd02b8b","vout":0,"amount":117.50945263,"spendtxid":"cf2509e076fbb9b22514923df916b7aacb1391dce9c7e1460b74947077b12510","vin":0,"paid":{"type":"paid","txid":"cf2509e076fbb9b22514923df916b7aacb1391dce9c7e1460b74947077b12510","height":275663,"timestamp":1492106024,"vouts":[{"RUDpN6PEBsE7ZFbGjUxk1W3QVsxnjBLYw6":117.50935263}]}}] //[{"type":"sent","confirmations":379,"height":275311,"timestamp":1492084664,"txid":"8703c5517bc57db38134058370a14e99b8e662b99ccefa2061dea311bbd02b8b","vout":0,"amount":117.50945263,"spendtxid":"cf2509e076fbb9b22514923df916b7aacb1391dce9c7e1460b74947077b12510","vin":0,"paid":{"type":"paid","txid":"cf2509e076fbb9b22514923df916b7aacb1391dce9c7e1460b74947077b12510","height":275663,"timestamp":1492106024,"vouts":[{"RUDpN6PEBsE7ZFbGjUxk1W3QVsxnjBLYw6":117.50935263}]}}]
LP_swap_getcoinaddr(symbol,coinaddr,utxotxid,vout); /*LP_swap_getcoinaddr(symbol,coinaddr,utxotxid,vout);
if ( coinaddr[0] != 0 ) if ( coinaddr[0] != 0 )
spendtxid = _LP_swap_spendtxid(symbol,destaddr,coinaddr,utxotxid,vout); spendtxid = _LP_swap_spendtxid(symbol,destaddr,coinaddr,utxotxid,vout);*/
} }
else else
{ {
@ -1099,7 +1132,7 @@ int32_t basilisk_bobpayment_reclaim(struct basilisk_swap *swap,int32_t delay)
len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[1],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[1],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen);
memcpy(swap->I.userdata_bobreclaim,userdata,len); memcpy(swap->I.userdata_bobreclaim,userdata,len);
swap->I.userdata_bobreclaimlen = len; swap->I.userdata_bobreclaimlen = len;
if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->bobreclaim,&swap->bobpayment,swap->I.myprivs[1],0,userdata,len,1,swap->changermd160,swap->bobpayment.I.destaddr)) == 0 ) 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->bobreclaim,&swap->bobpayment,swap->I.myprivs[1],0,userdata,len,1,swap->changermd160,swap->bobpayment.I.destaddr)) == 0 )
{ {
//for (i=0; i<swap->bobreclaim.I.datalen; i++) //for (i=0; i<swap->bobreclaim.I.datalen; i++)
// printf("%02x",swap->bobreclaim.txbytes[i]); // printf("%02x",swap->bobreclaim.txbytes[i]);
@ -1116,7 +1149,7 @@ int32_t basilisk_bobdeposit_refund(struct basilisk_swap *swap,int32_t delay)
len = basilisk_swapuserdata(userdata,swap->I.privBn,0,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); len = basilisk_swapuserdata(userdata,swap->I.privBn,0,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen);
memcpy(swap->I.userdata_bobrefund,userdata,len); memcpy(swap->I.userdata_bobrefund,userdata,len);
swap->I.userdata_bobrefundlen = len; swap->I.userdata_bobrefundlen = len;
if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->bobrefund,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,0,swap->changermd160,swap->bobdeposit.I.destaddr)) == 0 ) 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->bobrefund,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,0,swap->changermd160,swap->bobdeposit.I.destaddr)) == 0 )
{ {
for (i=0; i<swap->bobrefund.I.datalen; i++) for (i=0; i<swap->bobrefund.I.datalen; i++)
printf("%02x",swap->bobrefund.txbytes[i]); printf("%02x",swap->bobrefund.txbytes[i]);
@ -1278,7 +1311,7 @@ void basilisk_alicepayment(struct basilisk_swap *swap,struct iguana_info *coin,s
printf(" rmd160, ");*/ printf(" rmd160, ");*/
bitcoin_address(coinaddr,coin->taddr,coin->pubtype,swap->changermd160,20); bitcoin_address(coinaddr,coin->taddr,coin->pubtype,swap->changermd160,20);
//printf("%s suppress.%d fee.%d\n",coinaddr,alicepayment->I.suppress_pubkeys,swap->myfee.I.suppress_pubkeys); //printf("%s suppress.%d fee.%d\n",coinaddr,alicepayment->I.suppress_pubkeys,swap->myfee.I.suppress_pubkeys);
basilisk_rawtx_gen(swap->ctx,"alicepayment",swap->I.started,swap->persistent_pubkey33,0,1,alicepayment,alicepayment->I.locktime,alicepayment->spendscript,alicepayment->I.spendlen,coin->txfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr); basilisk_rawtx_gen(swap->ctx,"alicepayment",swap->I.started,swap->persistent_pubkey33,0,1,alicepayment,alicepayment->I.locktime,alicepayment->spendscript,alicepayment->I.spendlen,swap->I.Atxfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr);
} }
int32_t basilisk_alicetxs(int32_t pairsock,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) int32_t basilisk_alicetxs(int32_t pairsock,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
@ -1303,11 +1336,11 @@ int32_t basilisk_alicetxs(int32_t pairsock,struct basilisk_swap *swap,uint8_t *d
} }
if ( swap->myfee.I.datalen == 0 ) if ( swap->myfee.I.datalen == 0 )
{ {
printf("generate fee\n"); printf("generate fee %.8f\n",dstr(strcmp(swap->myfee.coin->symbol,"BTC") == 0 ? LP_MIN_TXFEE : swap->myfee.coin->txfee));
bitcoin_address(coinaddr,swap->alicecoin.taddr,swap->alicecoin.pubtype,swap->changermd160,20); bitcoin_address(coinaddr,swap->alicecoin.taddr,swap->alicecoin.pubtype,swap->changermd160,20);
if ( basilisk_rawtx_gen(swap->ctx,"myfee",swap->I.started,swap->persistent_pubkey33,swap->I.iambob,1,&swap->myfee,0,swap->myfee.spendscript,swap->myfee.I.spendlen,swap->myfee.coin->txfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr) == 0 ) if ( basilisk_rawtx_gen(swap->ctx,"myfee",swap->I.started,swap->persistent_pubkey33,swap->I.iambob,1,&swap->myfee,0,swap->myfee.spendscript,swap->myfee.I.spendlen,strcmp(swap->myfee.coin->symbol,"BTC") == 0 ? LP_MIN_TXFEE : swap->myfee.coin->txfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr) == 0 )
{ {
printf("rawtxsend\n"); printf("rawtxsend %s %.8f\n",swap->myfee.coin->symbol,dstr(strcmp(swap->myfee.coin->symbol,"BTC") == 0 ? LP_MIN_TXFEE : swap->myfee.coin->txfee));
swap->I.statebits |= LP_swapdata_rawtxsend(pairsock,swap,0x80,data,maxlen,&swap->myfee,0x40,0); swap->I.statebits |= LP_swapdata_rawtxsend(pairsock,swap,0x80,data,maxlen,&swap->myfee,0x40,0);
LP_unspents_mark(swap->I.iambob!=0?swap->bobcoin.symbol:swap->alicecoin.symbol,swap->myfee.vins); LP_unspents_mark(swap->I.iambob!=0?swap->bobcoin.symbol:swap->alicecoin.symbol,swap->myfee.vins);
//basilisk_txlog(swap,&swap->myfee,-1); //basilisk_txlog(swap,&swap->myfee,-1);
@ -1329,11 +1362,16 @@ int32_t basilisk_alicetxs(int32_t pairsock,struct basilisk_swap *swap,uint8_t *d
int32_t LP_verify_otherfee(struct basilisk_swap *swap,uint8_t *data,int32_t datalen) int32_t LP_verify_otherfee(struct basilisk_swap *swap,uint8_t *data,int32_t datalen)
{ {
// add verification and broadcast if ( LP_rawtx_spendscript(swap,swap->bobcoin.longestchain,&swap->otherfee,0,data,datalen,0) == 0 )
memcpy(swap->otherfee.txbytes,data,datalen); {
swap->otherfee.I.datalen = datalen; printf("otherfee amount %.8f -> %s vs %s\n",dstr(swap->otherfee.I.amount),swap->otherfee.p2shaddr,swap->otherfee.I.destaddr);
swap->otherfee.I.actualtxid = swap->otherfee.I.signedtxid = bits256_doublesha256(0,data,datalen); if ( strcmp(swap->otherfee.I.destaddr,swap->otherfee.p2shaddr) == 0 )
return(0); {
printf("dexfee verified\n");
return(0);
}
}
return(-1);
} }
/* Bob deposit: /* Bob deposit:
@ -1352,12 +1390,12 @@ int32_t LP_verify_bobdeposit(struct basilisk_swap *swap,uint8_t *data,int32_t da
swap->aliceclaim.utxotxid = swap->bobdeposit.I.signedtxid = LP_broadcast_tx(swap->bobdeposit.name,swap->bobcoin.symbol,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen); swap->aliceclaim.utxotxid = swap->bobdeposit.I.signedtxid = LP_broadcast_tx(swap->bobdeposit.name,swap->bobcoin.symbol,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen);
if ( bits256_nonz(swap->bobdeposit.I.signedtxid) != 0 ) if ( bits256_nonz(swap->bobdeposit.I.signedtxid) != 0 )
swap->depositunconf = 1; swap->depositunconf = 1;
basilisk_dontforget_update(swap,&swap->bobdeposit);
len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen);
memcpy(swap->I.userdata_aliceclaim,userdata,len); memcpy(swap->I.userdata_aliceclaim,userdata,len);
swap->I.userdata_aliceclaimlen = len; swap->I.userdata_aliceclaimlen = len;
bitcoin_address(swap->bobdeposit.p2shaddr,swap->bobcoin.taddr,swap->bobcoin.p2shtype,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); bitcoin_address(swap->bobdeposit.p2shaddr,swap->bobcoin.taddr,swap->bobcoin.p2shtype,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen);
strcpy(swap->bobdeposit.I.destaddr,swap->bobdeposit.p2shaddr); strcpy(swap->bobdeposit.I.destaddr,swap->bobdeposit.p2shaddr);
basilisk_dontforget_update(swap,&swap->bobdeposit);
//LP_importaddress(swap->bobcoin.symbol,swap->bobdeposit.I.destaddr); //LP_importaddress(swap->bobcoin.symbol,swap->bobdeposit.I.destaddr);
/*for (i=0; i<swap->bobdeposit.I.datalen; i++) /*for (i=0; i<swap->bobdeposit.I.datalen; i++)
printf("%02x",swap->bobdeposit.txbytes[i]); printf("%02x",swap->bobdeposit.txbytes[i]);
@ -1370,7 +1408,7 @@ int32_t LP_verify_bobdeposit(struct basilisk_swap *swap,uint8_t *data,int32_t da
memcpy(swap->aliceclaim.I.pubkey33,swap->persistent_pubkey33,33); memcpy(swap->aliceclaim.I.pubkey33,swap->persistent_pubkey33,33);
bitcoin_address(swap->aliceclaim.I.destaddr,swap->alicecoin.taddr,swap->alicecoin.pubtype,swap->persistent_pubkey33,33); bitcoin_address(swap->aliceclaim.I.destaddr,swap->alicecoin.taddr,swap->alicecoin.pubtype,swap->persistent_pubkey33,33);
retval = 0; retval = 0;
if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->aliceclaim,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,1,swap->changermd160,swap->bobdeposit.I.destaddr)) == 0 ) 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++) /*for (i=0; i<swap->bobdeposit.I.datalen; i++)
printf("%02x",swap->bobdeposit.txbytes[i]); printf("%02x",swap->bobdeposit.txbytes[i]);
@ -1416,12 +1454,12 @@ int32_t LP_verify_bobpayment(struct basilisk_swap *swap,uint8_t *data,int32_t da
swap->alicespend.utxotxid = swap->bobpayment.I.signedtxid = LP_broadcast_tx(swap->bobpayment.name,swap->bobpayment.coin->symbol,swap->bobpayment.txbytes,swap->bobpayment.I.datalen); swap->alicespend.utxotxid = swap->bobpayment.I.signedtxid = LP_broadcast_tx(swap->bobpayment.name,swap->bobpayment.coin->symbol,swap->bobpayment.txbytes,swap->bobpayment.I.datalen);
if ( bits256_nonz(swap->bobpayment.I.signedtxid) != 0 ) if ( bits256_nonz(swap->bobpayment.I.signedtxid) != 0 )
swap->paymentunconf = 1; swap->paymentunconf = 1;
basilisk_dontforget_update(swap,&swap->bobpayment);
for (i=0; i<32; i++) for (i=0; i<32; i++)
revAm.bytes[i] = swap->I.privAm.bytes[31-i]; revAm.bytes[i] = swap->I.privAm.bytes[31-i];
len = basilisk_swapuserdata(userdata,revAm,0,swap->I.myprivs[0],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); len = basilisk_swapuserdata(userdata,revAm,0,swap->I.myprivs[0],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen);
bitcoin_address(swap->bobpayment.p2shaddr,swap->bobcoin.taddr,swap->bobcoin.p2shtype,swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen); bitcoin_address(swap->bobpayment.p2shaddr,swap->bobcoin.taddr,swap->bobcoin.p2shtype,swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen);
strcpy(swap->bobpayment.I.destaddr,swap->bobpayment.p2shaddr); strcpy(swap->bobpayment.I.destaddr,swap->bobpayment.p2shaddr);
basilisk_dontforget_update(swap,&swap->bobpayment);
//LP_importaddress(swap->bobcoin.symbol,swap->bobpayment.I.destaddr); //LP_importaddress(swap->bobcoin.symbol,swap->bobpayment.I.destaddr);
/*for (i=0; i<swap->bobpayment.I.datalen; i++) /*for (i=0; i<swap->bobpayment.I.datalen; i++)
printf("%02x",swap->bobpayment.txbytes[i]); printf("%02x",swap->bobpayment.txbytes[i]);
@ -1435,7 +1473,7 @@ int32_t LP_verify_bobpayment(struct basilisk_swap *swap,uint8_t *data,int32_t da
memcpy(swap->alicespend.I.pubkey33,swap->persistent_pubkey33,33); memcpy(swap->alicespend.I.pubkey33,swap->persistent_pubkey33,33);
bitcoin_address(swap->alicespend.I.destaddr,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->persistent_pubkey33,33); bitcoin_address(swap->alicespend.I.destaddr,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->persistent_pubkey33,33);
//char str[65],str2[65]; printf("bobpaid privAm.(%s) myprivs[0].(%s)\n",bits256_str(str,swap->I.privAm),bits256_str(str2,swap->I.myprivs[0])); //char str[65],str2[65]; printf("bobpaid privAm.(%s) myprivs[0].(%s)\n",bits256_str(str,swap->I.privAm),bits256_str(str2,swap->I.myprivs[0]));
if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->alicespend,&swap->bobpayment,swap->I.myprivs[0],0,userdata,len,1,swap->changermd160,swap->alicepayment.I.destaddr)) == 0 ) 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->alicespend,&swap->bobpayment,swap->I.myprivs[0],0,userdata,len,1,swap->changermd160,swap->alicepayment.I.destaddr)) == 0 )
{ {
/*for (i=0; i<swap->bobpayment.I.datalen; i++) /*for (i=0; i<swap->bobpayment.I.datalen; i++)
printf("%02x",swap->bobpayment.txbytes[i]); printf("%02x",swap->bobpayment.txbytes[i]);

420
iguana/exchanges/LP_utxos.c

@ -20,7 +20,7 @@
int32_t LP_ismine(struct LP_utxoinfo *utxo) int32_t LP_ismine(struct LP_utxoinfo *utxo)
{ {
if ( utxo != 0 && bits256_cmp(utxo->pubkey,LP_mypubkey) == 0 ) if ( utxo != 0 && bits256_cmp(utxo->pubkey,LP_mypub25519) == 0 )
return(1); return(1);
else return(0); else return(0);
} }
@ -114,6 +114,8 @@ int32_t LP_utxoaddptrs(struct LP_utxoinfo *ptrs[],int32_t n,struct LP_utxoinfo *
int32_t LP_utxocollisions(struct LP_utxoinfo *ptrs[],struct LP_utxoinfo *refutxo) int32_t LP_utxocollisions(struct LP_utxoinfo *ptrs[],struct LP_utxoinfo *refutxo)
{ {
int32_t iambob,n = 0; struct LP_utxoinfo *utxo; struct _LP_utxoinfo u; int32_t iambob,n = 0; struct LP_utxoinfo *utxo; struct _LP_utxoinfo u;
if ( refutxo == 0 )
return(0);
portable_mutex_lock(&LP_utxomutex); portable_mutex_lock(&LP_utxomutex);
for (iambob=0; iambob<=1; iambob++) for (iambob=0; iambob<=1; iambob++)
{ {
@ -175,24 +177,27 @@ void LP_unavailableset(struct LP_utxoinfo *utxo,bits256 otherpubkey)
void LP_availableset(struct LP_utxoinfo *utxo) void LP_availableset(struct LP_utxoinfo *utxo)
{ {
struct LP_utxoinfo *ptrs[8]; int32_t i,n,count = 0; struct _LP_utxoinfo u; struct LP_utxoinfo *ptrs[8]; int32_t i,n,count = 0; struct _LP_utxoinfo u;
memset(ptrs,0,sizeof(ptrs)); if ( utxo != 0 )
if ( (n= LP_utxocollisions(ptrs,utxo)) > 0 )
{
for (i=0; i<n; i++)
count += _LP_availableset(ptrs[i]);
}
count += _LP_availableset(utxo);
if ( count > 0 )
{ {
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; memset(ptrs,0,sizeof(ptrs));
char str[65],str2[65]; printf("UTXO.[%d] AVAIL %s/v%d %s/v%d collisions.%d\n",utxo->iambob,bits256_str(str,utxo->payment.txid),utxo->payment.vout,bits256_str(str2,u.txid),u.vout,n); if ( (n= LP_utxocollisions(ptrs,utxo)) > 0 )
{
for (i=0; i<n; i++)
count += _LP_availableset(ptrs[i]);
}
count += _LP_availableset(utxo);
if ( count > 0 )
{
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee;
char str[65],str2[65]; printf("UTXO.[%d] AVAIL %s/v%d %s/v%d collisions.%d\n",utxo->iambob,bits256_str(str,utxo->payment.txid),utxo->payment.vout,bits256_str(str2,u.txid),u.vout,n);
}
} }
} }
int32_t LP_utxopurge(int32_t allutxos) int32_t LP_utxopurge(int32_t allutxos)
{ {
char str[65]; struct LP_utxoinfo *utxo,*tmp; int32_t iambob,n = 0; char str[65]; struct LP_utxoinfo *utxo,*tmp; int32_t iambob,n = 0;
printf("LP_utxopurge mypub.(%s)\n",bits256_str(str,LP_mypubkey)); printf("LP_utxopurge mypub.(%s)\n",bits256_str(str,LP_mypub25519));
portable_mutex_lock(&LP_utxomutex); portable_mutex_lock(&LP_utxomutex);
for (iambob=0; iambob<=1; iambob++) for (iambob=0; iambob<=1; iambob++)
{ {
@ -228,11 +233,13 @@ int32_t LP_utxopurge(int32_t allutxos)
cJSON *LP_inventoryjson(cJSON *item,struct LP_utxoinfo *utxo) cJSON *LP_inventoryjson(cJSON *item,struct LP_utxoinfo *utxo)
{ {
struct _LP_utxoinfo u; struct _LP_utxoinfo u;
jaddstr(item,"method","notified"); jaddstr(item,"method","utxo");
if ( utxo == 0 )
return(item);
if ( utxo->gui[0] != 0 ) if ( utxo->gui[0] != 0 )
jaddstr(item,"gui",utxo->gui); jaddstr(item,"gui",utxo->gui);
jaddstr(item,"coin",utxo->coin); jaddstr(item,"coin",utxo->coin);
jaddnum(item,"now",time(NULL)); //jaddnum(item,"now",time(NULL));
jaddnum(item,"iambob",utxo->iambob); jaddnum(item,"iambob",utxo->iambob);
jaddstr(item,"address",utxo->coinaddr); jaddstr(item,"address",utxo->coinaddr);
jaddbits256(item,"txid",utxo->payment.txid); jaddbits256(item,"txid",utxo->payment.txid);
@ -250,13 +257,13 @@ cJSON *LP_inventoryjson(cJSON *item,struct LP_utxoinfo *utxo)
jaddnum(item,"pending",utxo->T.swappending); jaddnum(item,"pending",utxo->T.swappending);
if ( utxo->iambob != 0 ) if ( utxo->iambob != 0 )
{ {
jaddbits256(item,"srchash",LP_mypubkey); jaddbits256(item,"srchash",utxo->pubkey);//LP_mypub25519);
if ( bits256_nonz(utxo->S.otherpubkey) != 0 ) if ( bits256_nonz(utxo->S.otherpubkey) != 0 )
jaddbits256(item,"desthash",utxo->S.otherpubkey); jaddbits256(item,"desthash",utxo->S.otherpubkey);
} }
else else
{ {
jaddbits256(item,"desthash",LP_mypubkey); jaddbits256(item,"desthash",utxo->pubkey);//LP_mypub25519);
if ( bits256_nonz(utxo->S.otherpubkey) != 0 ) if ( bits256_nonz(utxo->S.otherpubkey) != 0 )
jaddbits256(item,"srchash",utxo->S.otherpubkey); jaddbits256(item,"srchash",utxo->S.otherpubkey);
} }
@ -264,6 +271,7 @@ cJSON *LP_inventoryjson(cJSON *item,struct LP_utxoinfo *utxo)
jaddstr(item,"swap","in progress"); jaddstr(item,"swap","in progress");
if ( utxo->T.spentflag != 0 ) if ( utxo->T.spentflag != 0 )
jaddnum(item,"spent",utxo->T.spentflag); jaddnum(item,"spent",utxo->T.spentflag);
jaddnum(item,"session",utxo->T.sessionid);
return(item); return(item);
} }
@ -272,24 +280,34 @@ cJSON *LP_utxojson(struct LP_utxoinfo *utxo)
cJSON *item = cJSON_CreateObject(); cJSON *item = cJSON_CreateObject();
item = LP_inventoryjson(item,utxo); item = LP_inventoryjson(item,utxo);
jaddbits256(item,"pubkey",utxo->pubkey); jaddbits256(item,"pubkey",utxo->pubkey);
jaddnum(item,"profit",utxo->S.profitmargin); //jaddnum(item,"profit",utxo->S.profitmargin);
jaddstr(item,"base",utxo->coin); jaddstr(item,"base",utxo->coin);
jaddstr(item,"script",utxo->spendscript); jaddstr(item,"script",utxo->spendscript);
return(item); return(item);
} }
int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2,bits256 pubkey) int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2)
{ {
uint64_t val,val2=0,threshold; char destaddr[64],destaddr2[64]; //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);
destaddr[0] = destaddr2[0] = 0; destaddr[0] = destaddr2[0] = 0;
if ( (val= LP_txvalue(destaddr,symbol,txid,vout)) >= satoshis ) if ( coin != 0 && IAMLP != 0 && coin->inactive != 0 )
{ bypass = 1;
threshold = (iambob != 0) ? LP_DEPOSITSATOSHIS(satoshis) : LP_DEXFEE(satoshis); if ( bypass != 0 )
if ( (val2= LP_txvalue(destaddr2,symbol,txid2,vout2)) >= threshold ) val = satoshis;
else val = LP_txvalue(destaddr,symbol,txid,vout);
txfee = LP_txfeecalc(symbol,0);
if ( val >= satoshis && val > (1+LP_MINSIZE_TXFEEMULT)*txfee )
{
threshold = (iambob != 0) ? LP_DEPOSITSATOSHIS(satoshis) : (LP_DEXFEE(satoshis) + txfee);
if ( bypass != 0 )
val2 = threshold;
else val2 = LP_txvalue(destaddr2,symbol,txid2,vout2);
if ( val2 >= threshold )
{ {
if ( strcmp(destaddr,destaddr2) != 0 ) if ( bypass == 0 && strcmp(destaddr,destaddr2) != 0 )
printf("mismatched %s destaddr (%s) vs (%s)\n",symbol,destaddr,destaddr2); printf("mismatched %s destaddr (%s) vs (%s)\n",symbol,destaddr,destaddr2);
else if ( (iambob == 0 && val2 > val) || (iambob != 0 && val2 <= satoshis) ) else if ( bypass == 0 && ((iambob == 0 && val2 > val) || (iambob != 0 && val2 <= satoshis)) )
printf("iambob.%d ineligible due to offsides: val %.8f and val2 %.8f vs %.8f diff %lld\n",iambob,dstr(val),dstr(val2),dstr(satoshis),(long long)(val2 - val)); printf("iambob.%d ineligible due to offsides: val %.8f and val2 %.8f vs %.8f diff %lld\n",iambob,dstr(val),dstr(val2),dstr(satoshis),(long long)(val2 - val));
else else
{ {
@ -297,8 +315,36 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol
*val2p = val2; *val2p = val2;
return(1); return(1);
} }
} else printf("no val2\n"); } // else printf("no val2\n");
} else printf("mismatched %s txid value %.8f < %.8f\n",symbol,dstr(val),dstr(satoshis)); }
// 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));
/*for (iter=0; iter<2; iter++)
{
if ( (utxo= LP_utxofind(iter,txid,vout)) != 0 )
{
//printf("iambob.%d case 00\n",iter);
if ( utxo->T.spentflag == 0 )
utxo->T.spentflag = (uint32_t)time(NULL);
}
if ( (utxo= LP_utxo2find(iter,txid,vout)) != 0 )
{
//printf("iambob.%d case 01\n",iter);
if ( utxo->T.spentflag == 0 )
utxo->T.spentflag = (uint32_t)time(NULL);
}
if ( (utxo= LP_utxofind(iter,txid2,vout2)) != 0 )
{
//printf("iambob.%d case 10\n",iter);
if ( utxo->T.spentflag == 0 )
utxo->T.spentflag = (uint32_t)time(NULL);
}
if ( (utxo= LP_utxo2find(iter,txid2,vout2)) != 0 )
{
//printf("iambob.%d case 11\n",iter);
if ( utxo->T.spentflag == 0 )
utxo->T.spentflag = (uint32_t)time(NULL);
}
}*/
*valp = val; *valp = val;
*val2p = val2; *val2p = val2;
return(0); return(0);
@ -306,30 +352,29 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol
char *LP_utxos(int32_t iambob,struct LP_peerinfo *mypeer,char *symbol,int32_t lastn) char *LP_utxos(int32_t iambob,struct LP_peerinfo *mypeer,char *symbol,int32_t lastn)
{ {
int32_t i,firsti,n; uint64_t val,val2; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray(); int32_t i,n,m; uint64_t val,val2; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray();
i = 0; //n = mypeer != 0 ? mypeer->numutxos : 0;
n = mypeer != 0 ? mypeer->numutxos : 0;
if ( lastn <= 0 ) if ( lastn <= 0 )
lastn = LP_PROPAGATION_SLACK * 2; lastn = LP_PROPAGATION_SLACK * 2;
if ( lastn >= n )
firsti = -1;
else firsti = (lastn - n);
//printf("LP_utxos iambob.%d symbol.%s firsti.%d lastn.%d\n",iambob,symbol==0?"":symbol,firsti,lastn);
HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp)
{ {
//char str[65]; printf("check %s.%s\n",utxo->coin,bits256_str(str,utxo->payment.txid)); //char str[65]; printf("check %s.%s\n",utxo->coin,bits256_str(str,utxo->payment.txid));
if ( i++ < firsti )
continue;
if ( (symbol == 0 || symbol[0] == 0 || strcmp(symbol,utxo->coin) == 0) && utxo->T.spentflag == 0 ) if ( (symbol == 0 || symbol[0] == 0 || strcmp(symbol,utxo->coin) == 0) && utxo->T.spentflag == 0 )
{ {
u = (iambob != 0) ? utxo->deposit : utxo->fee; u = (iambob != 0) ? utxo->deposit : utxo->fee;
if ( LP_iseligible(&val,&val2,iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,u.txid,u.vout,utxo->pubkey) == 0 ) 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); 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; continue;
} else jaddi(utxosjson,LP_utxojson(utxo)); } 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)); return(jprint(utxosjson,1));
} }
@ -349,16 +394,29 @@ int32_t LP_inventory_prevent(int32_t iambob,bits256 txid,int32_t vout)
struct LP_utxoinfo *LP_utxo_bestfit(char *symbol,uint64_t destsatoshis) struct LP_utxoinfo *LP_utxo_bestfit(char *symbol,uint64_t destsatoshis)
{ {
struct LP_utxoinfo *utxo,*tmp,*bestutxo = 0; uint64_t srcvalue,srcvalue2; struct LP_utxoinfo *utxo,*tmp,*bestutxo = 0;
if ( symbol == 0 || destsatoshis == 0 ) if ( symbol == 0 || destsatoshis == 0 )
{
printf("LP_utxo_bestfit error symbol.%p %.8f\n",symbol,dstr(destsatoshis));
return(0); return(0);
}
HASH_ITER(hh,LP_utxoinfos[0],utxo,tmp) HASH_ITER(hh,LP_utxoinfos[0],utxo,tmp)
{ {
//char str[65]; printf("[%.8f vs %.8f] check %s.%s avail.%d ismine.%d >= %d\n",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); //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 && LP_isavailable(utxo) > 0 && LP_ismine(utxo) > 0 ) if ( strcmp(symbol,utxo->coin) != 0 )
continue;
if ( LP_isavailable(utxo) > 0 && LP_ismine(utxo) > 0 )
{ {
if ( utxo->S.satoshis >= destsatoshis && (bestutxo == 0 || utxo->S.satoshis < bestutxo->S.satoshis) ) 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 ( LP_iseligible(&srcvalue,&srcvalue2,utxo->iambob,symbol,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,utxo->fee.txid,utxo->fee.vout) == 0 )
{
//if ( utxo->T.spentflag == 0 )
// utxo->T.spentflag = (uint32_t)time(NULL);
continue;
}
bestutxo = utxo; bestutxo = utxo;
} //else printf("skip alice utxo %.8f vs dest %.8f\n",dstr(utxo->S.satoshis),dstr(destsatoshis));
} }
} }
return(bestutxo); return(bestutxo);
@ -366,11 +424,13 @@ struct LP_utxoinfo *LP_utxo_bestfit(char *symbol,uint64_t destsatoshis)
void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector) void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector)
{ {
cJSON *argjson; struct _LP_utxoinfo u; char *msg; //cJSON *argjson; struct _LP_utxoinfo u; char *msg;
if ( utxo == 0 )
return;
utxo->T.spentflag = (uint32_t)time(NULL); utxo->T.spentflag = (uint32_t)time(NULL);
if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 ) if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 )
LP_mypeer->numutxos--; LP_mypeer->numutxos--;
if ( LP_mypubsock >= 0 ) /*if ( LP_mypubsock >= 0 )
{ {
argjson = cJSON_CreateObject(); argjson = cJSON_CreateObject();
jaddstr(argjson,"method","checktxid"); jaddstr(argjson,"method","checktxid");
@ -385,8 +445,8 @@ void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector)
jaddnum(argjson,"checkvout",u.vout); jaddnum(argjson,"checkvout",u.vout);
} }
msg = jprint(argjson,1); msg = jprint(argjson,1);
LP_send(LP_mypubsock,msg,(int32_t)strlen(msg)+1,1); /LP_send(LP_mypubsock,msg,(int32_t)strlen(msg)+1,1);
} }*/
} }
char *LP_spentcheck(cJSON *argjson) char *LP_spentcheck(cJSON *argjson)
@ -420,40 +480,96 @@ char *LP_spentcheck(cJSON *argjson)
return(clonestr("{\"error\":\"cant find txid to check spent status\"}")); return(clonestr("{\"error\":\"cant find txid to check spent status\"}"));
} }
struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bits256 txid,int32_t vout,int64_t value,bits256 txid2,int32_t vout2,int64_t value2,char *spendscript,char *coinaddr,bits256 pubkey,double profitmargin,char *gui) void LP_utxo_clientpublish(struct LP_utxoinfo *utxo)
{ {
uint64_t val,val2=0,tmpsatoshis,bigtxfee = 100000; int32_t spendvini,selector; bits256 spendtxid; char *msg; struct iguana_info *coin; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo = 0; bits256 zero; char *msg;
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 ) 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)
{ {
printf("malformed addutxo %d %d %d %d %d %d %d %d %d\n", symbol == 0,spendscript == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(txid2) == 0,vout < 0,vout2 < 0,value <= 0,value2 <= 0); 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)
{
uint64_t val,val2=0,tmpsatoshis,txfee; cJSON *txobj; 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 )
{
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);
return(0); return(0);
} }
if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) if ( (coin= LP_coinfind(symbol)) == 0 || (IAMLP == 0 && coin->inactive != 0) )
{
printf("LP_utxoadd reject inactive %s\n",symbol);
return(0); return(0);
if ( iambob != 0 && value2 < 9 * (value >> 3) + bigtxfee ) // big txfee padding }
txfee = LP_txfeecalc(coin->symbol,0);
if ( iambob != 0 && value2 < 9 * (value >> 3) + 2*txfee ) // big txfee padding
{ {
if ( value2 > bigtxfee+20000 ) if ( value2 > 2*txfee )
tmpsatoshis = (((value2 - bigtxfee) / 9) << 3); tmpsatoshis = (((value2 - 2*txfee) / 9) << 3);
else return(0); else return(0);
} else tmpsatoshis = value; } else tmpsatoshis = (value - txfee);
char str[65],str2[65],dispflag = (iambob == 0); char str[65],str2[65],dispflag = (iambob == 0);
if ( iambob == 0 && bits256_cmp(pubkey,LP_mypubkey) != 0 ) if ( iambob == 0 && bits256_cmp(pubkey,LP_mypub25519) != 0 )
{ {
printf("trying to add Alice utxo when not mine? %s/v%d\n",bits256_str(str,txid),vout); printf("trying to add Alice utxo when not mine? %s/v%d\n",bits256_str(str,txid),vout);
return(0); return(0);
} }
if ( LP_iseligible(&val,&val2,iambob,symbol,txid,vout,tmpsatoshis,txid2,vout2,pubkey) <= 0 ) if ( LP_iseligible(&val,&val2,iambob,symbol,txid,vout,tmpsatoshis,txid2,vout2) <= 0 )
{ {
// iambob.0 utxoadd COQUI inactive.0 got ineligible txid value 1.20000000, value2 0.01000000, tmpsatoshis 1.20000000
printf("iambob.%d utxoadd %s inactive.%u got ineligible txid value %.8f, value2 %.8f, tmpsatoshis %.8f\n",iambob,symbol,coin->inactive,dstr(value),dstr(value2),dstr(tmpsatoshis)); printf("iambob.%d utxoadd %s inactive.%u got ineligible txid value %.8f, value2 %.8f, tmpsatoshis %.8f\n",iambob,symbol,coin->inactive,dstr(value),dstr(value2),dstr(tmpsatoshis));
return(0); return(0);
} }
numconfirms = -1;
if ( (txobj= LP_gettx(symbol,txid)) != 0 )
{
numconfirms = jint(txobj,"confirmations");
free_json(txobj);
}
if ( numconfirms <= 0 )
{
//printf("LP_utxoadd reject numconfirms.%d\n",numconfirms);
return(0);
}
numconfirms = -1;
if ( (txobj= LP_gettx(symbol,txid2)) != 0 )
{
numconfirms = jint(txobj,"confirmations");
free_json(txobj);
}
if ( numconfirms <= 0 )
{
printf("LP_utxoadd reject2 numconfirms.%d\n",numconfirms);
return(0);
}
if ( 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)); 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; dispflag = 1;
if ( (selector= LP_mempool_vinscan(&spendtxid,&spendvini,symbol,txid,vout,txid2,vout2)) >= 0 ) if ( (selector= LP_mempool_vinscan(&spendtxid,&spendvini,symbol,txid,vout,txid2,vout2)) >= 0 )
{ {
printf("utxoadd selector.%d in mempool %s vini.%d",selector,bits256_str(str,spendtxid),spendvini); printf("utxoadd selector.%d spent in mempool %s vini.%d",selector,bits256_str(str,spendtxid),spendvini);
return(0); return(0);
} }
if ( (utxo= LP_utxofinds(iambob,txid,vout,txid2,vout2)) != 0 ) if ( (utxo= LP_utxofinds(iambob,txid,vout,txid2,vout2)) != 0 )
@ -468,23 +584,28 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit
{ {
utxo->T.errors++; utxo->T.errors++;
char str[65],str2[65],str3[65],str4[65],str5[65],str6[65]; char str[65],str2[65],str3[65],str4[65],str5[65],str6[65];
if ( dispflag != 0 )
printf("error on subsequent utxo iambob.%d %.8f %.8f add.(%s %s) when.(%s %s) %d %d %d %d %d %d %d %d %d %d %d pubkeys.(%s vs %s)\n",iambob,dstr(val),dstr(val2),bits256_str(str,txid),bits256_str(str2,txid2),bits256_str(str3,utxo->payment.txid),bits256_str(str4,utxo->deposit.txid),bits256_cmp(txid,utxo->payment.txid) != 0,bits256_cmp(txid2,u.txid) != 0,vout != utxo->payment.vout,tmpsatoshis != utxo->S.satoshis,vout2 != u.vout,value2 != u.value,strcmp(symbol,utxo->coin) != 0,strcmp(spendscript,utxo->spendscript) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,bits256_cmp(pubkey,utxo->pubkey) != 0,value != utxo->payment.value,bits256_str(str5,pubkey),bits256_str(str6,utxo->pubkey));
if ( utxo->T.spentflag != 0 || LP_txvalue(0,utxo->coin,utxo->payment.txid,utxo->payment.vout) < utxo->payment.value || LP_txvalue(0,utxo->coin,u.txid,u.vout) < u.value ) if ( utxo->T.spentflag != 0 || LP_txvalue(0,utxo->coin,utxo->payment.txid,utxo->payment.vout) < utxo->payment.value || LP_txvalue(0,utxo->coin,u.txid,u.vout) < u.value )
{ {
if ( utxo->T.spentflag == 0 ) if ( utxo->T.spentflag == 0 )
utxo->T.spentflag = (uint32_t)time(NULL); utxo->T.spentflag = (uint32_t)time(NULL);
printf("original utxo pair not valid\n"); 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));
utxo = 0; utxo = 0;
} }
} }
else if ( profitmargin > SMALLVAL )
utxo->S.profitmargin = profitmargin;
if ( utxo != 0 ) if ( utxo != 0 )
{
if ( utxo->T.sessionid == 0 )
utxo->T.sessionid = sessionid;
//else if ( profitmargin > SMALLVAL )
// utxo->S.profitmargin = profitmargin;
utxo->T.lasttime = (uint32_t)time(NULL);
return(utxo); return(utxo);
}
} }
utxo = calloc(1,sizeof(*utxo)); utxo = calloc(1,sizeof(*utxo));
utxo->S.profitmargin = profitmargin; //utxo->S.profitmargin = profitmargin;
utxo->pubkey = pubkey; utxo->pubkey = pubkey;
safecopy(utxo->gui,gui,sizeof(utxo->gui)); safecopy(utxo->gui,gui,sizeof(utxo->gui));
safecopy(utxo->coin,symbol,sizeof(utxo->coin)); safecopy(utxo->coin,symbol,sizeof(utxo->coin));
@ -508,6 +629,10 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit
} }
LP_utxosetkey(utxo->key,txid,vout); LP_utxosetkey(utxo->key,txid,vout);
LP_utxosetkey(utxo->key2,txid2,vout2); LP_utxosetkey(utxo->key2,txid2,vout2);
if ( LP_ismine(utxo) > 0 )
utxo->T.sessionid = LP_sessionid;
else utxo->T.sessionid = sessionid;
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);
portable_mutex_lock(&LP_utxomutex); portable_mutex_lock(&LP_utxomutex);
HASH_ADD_KEYPTR(hh,LP_utxoinfos[iambob],utxo->key,sizeof(utxo->key),utxo); HASH_ADD_KEYPTR(hh,LP_utxoinfos[iambob],utxo->key,sizeof(utxo->key),utxo);
if ( _LP_utxo2find(iambob,txid2,vout2) == 0 ) if ( _LP_utxo2find(iambob,txid2,vout2) == 0 )
@ -515,13 +640,14 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit
portable_mutex_unlock(&LP_utxomutex); portable_mutex_unlock(&LP_utxomutex);
if ( iambob != 0 ) if ( iambob != 0 )
{ {
if ( mypubsock >= 0 ) if ( LP_mypeer != 0 )
{
msg = jprint(LP_utxojson(utxo),1);
LP_send(mypubsock,msg,(int32_t)strlen(msg)+1,1);
} else LP_utxo_clientpublish(utxo);
if ( LP_mypeer != 0 && LP_ismine(utxo) > 0 )
LP_mypeer->numutxos++; LP_mypeer->numutxos++;
if ( LP_ismine(utxo) > 0 )
{
LP_utxo_clientpublish(utxo);
if ( LP_mypeer != 0 )
utxo->T.lasttime = (uint32_t)time(NULL);
}
} }
return(utxo); return(utxo);
} }
@ -535,7 +661,12 @@ struct LP_utxoinfo *LP_utxoaddjson(int32_t iambob,int32_t pubsock,cJSON *argjson
return(0); return(0);
} }
portable_mutex_lock(&LP_UTXOmutex); portable_mutex_lock(&LP_UTXOmutex);
utxo = LP_utxoadd(iambob,pubsock,jstr(argjson,"coin"),jbits256(argjson,"txid"),jint(argjson,"vout"),j64bits(argjson,"value"),jbits256(argjson,"txid2"),jint(argjson,"vout2"),j64bits(argjson,"value2"),jstr(argjson,"script"),jstr(argjson,"address"),jbits256(argjson,"pubkey"),jdouble(argjson,"profit"),jstr(argjson,"gui")); 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); portable_mutex_unlock(&LP_UTXOmutex);
return(utxo); return(utxo);
} }
@ -559,18 +690,14 @@ int32_t LP_utxosparse(char *destipaddr,uint16_t destport,char *retstr,uint32_t n
subport = argport + 2; subport = argport + 2;
argipbits = (uint32_t)calc_ipbits(argipaddr); argipbits = (uint32_t)calc_ipbits(argipaddr);
if ( (peer= LP_peerfind(argipbits,argport)) == 0 ) if ( (peer= LP_peerfind(argipbits,argport)) == 0 )
peer = LP_addpeer(0,-1,argipaddr,argport,pushport,subport,jdouble(item,"profit"),jint(item,"numpeers"),jint(item,"numutxos")); peer = LP_addpeer(0,-1,argipaddr,argport,pushport,subport,jint(item,"numpeers"),jint(item,"numutxos"),juint(item,"session"));
} }
if ( jobj(item,"txid") != 0 ) if ( jobj(item,"txid") != 0 )
{ {
txid = jbits256(item,"txid"); txid = jbits256(item,"txid");
//printf("parse.(%s)\n",jprint(item,0)); //printf("parse.(%s)\n",jprint(item,0));
if ( (utxo= LP_utxoaddjson(1,-1,item)) != 0 ) if ( (utxo= LP_utxoaddjson(1,-1,item)) != 0 )
{
//if ( strcmp(utxo->coin,"HUSH") == 0 )
// printf("%s set lasttime (%s)\n",destipaddr,jprint(item,0));
utxo->T.lasttime = now; utxo->T.lasttime = now;
}
} }
} }
if ( (destpeer= LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport)) != 0 ) if ( (destpeer= LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport)) != 0 )
@ -583,7 +710,7 @@ int32_t LP_utxosparse(char *destipaddr,uint16_t destport,char *retstr,uint32_t n
return(n); 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,double myprofit) int32_t LP_utxosquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *coin,int32_t lastn,char *myipaddr,uint16_t myport,int32_t maxentries)
{ {
char *retstr; struct LP_peerinfo *peer; uint32_t now; int32_t retval = -1; char *retstr; struct LP_peerinfo *peer; uint32_t now; int32_t retval = -1;
peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport);
@ -591,8 +718,8 @@ int32_t LP_utxosquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipa
coin = ""; coin = "";
//printf("utxo query.(%s)\n",destipaddr); //printf("utxo query.(%s)\n",destipaddr);
if ( IAMLP != 0 ) if ( IAMLP != 0 )
retstr = issue_LP_getutxos(destipaddr,destport,coin,lastn,myipaddr,myport,myprofit,mypeer != 0 ? mypeer->numpeers : 0,mypeer != 0 ? mypeer->numutxos : 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,100); else retstr = issue_LP_clientgetutxos(destipaddr,destport,coin,maxentries);
if ( retstr != 0 ) if ( retstr != 0 )
{ {
now = (uint32_t)time(NULL); now = (uint32_t)time(NULL);
@ -623,16 +750,27 @@ int32_t LP_utxosquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipa
cJSON *LP_inventory(char *symbol,int32_t iambob) cJSON *LP_inventory(char *symbol,int32_t iambob)
{ {
struct LP_utxoinfo *utxo,*tmp; char *myipaddr; cJSON *array; struct LP_utxoinfo *utxo,*tmp; struct _LP_utxoinfo u; char *myipaddr; cJSON *array; uint64_t val,val2;
array = cJSON_CreateArray(); array = cJSON_CreateArray();
if ( LP_mypeer != 0 ) if ( LP_mypeer != 0 )
myipaddr = LP_mypeer->ipaddr; myipaddr = LP_mypeer->ipaddr;
else myipaddr = "127.0.0.1"; else myipaddr = "127.0.0.1";
HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp)
{ {
//char str[65]; printf("iambob.%d iterate %s\n",iambob,bits256_str(str,LP_mypubkey)); //char str[65]; printf("iambob.%d iterate %s\n",iambob,bits256_str(str,LP_mypub25519));
if ( LP_isunspent(utxo) != 0 && strcmp(symbol,utxo->coin) == 0 && utxo->iambob == iambob && LP_ismine(utxo) > 0 ) if ( LP_isunspent(utxo) != 0 && strcmp(symbol,utxo->coin) == 0 && utxo->iambob == iambob && LP_ismine(utxo) > 0 )
{
u = (iambob != 0) ? utxo->deposit : utxo->fee;
if ( LP_iseligible(&val,&val2,iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,u.txid,u.vout) == 0 )
{
if ( utxo->T.spentflag == 0 )
utxo->T.spentflag = (uint32_t)time(NULL);
continue;
}
if ( iambob != 0 )
LP_utxo_clientpublish(utxo);
jaddi(array,LP_inventoryjson(cJSON_CreateObject(),utxo)); jaddi(array,LP_inventoryjson(cJSON_CreateObject(),utxo));
}
//else printf("skip %s %d %d %d %d\n",bits256_str(str,utxo->pubkey),LP_isunspent(utxo) != 0,strcmp(symbol,utxo->coin) == 0,utxo->iambob == iambob,LP_ismine(utxo) > 0); //else printf("skip %s %d %d %d %d\n",bits256_str(str,utxo->pubkey),LP_isunspent(utxo) != 0,strcmp(symbol,utxo->coin) == 0,utxo->iambob == iambob,LP_ismine(utxo) > 0);
} }
return(array); return(array);
@ -650,14 +788,15 @@ int32_t LP_maxvalue(uint64_t *values,int32_t n)
return(maxi); return(maxi);
} }
int32_t LP_nearestvalue(uint64_t *values,int32_t n,uint64_t targetval) int32_t LP_nearestvalue(int32_t iambob,uint64_t *values,int32_t n,uint64_t targetval)
{ {
int32_t i,mini = -1; int64_t dist; uint64_t mindist = (1 << 31); int32_t i,mini = -1; int64_t dist; uint64_t mindist = (1 << 31);
for (i=0; i<n; i++) for (i=0; i<n; i++)
{ {
dist = (values[i] - targetval); dist = (values[i] - targetval);
if ( dist < 0 && -dist < values[i]/10 ) if ( iambob != 0 && dist < 0 && -dist < values[i]/10 )
dist = -dist; dist = -dist;
//printf("(%.8f %.8f %.8f).%d ",dstr(values[i]),dstr(dist),dstr(mindist),mini);
if ( dist >= 0 && dist < mindist ) if ( dist >= 0 && dist < mindist )
{ {
mini = i; mini = i;
@ -667,9 +806,9 @@ int32_t LP_nearestvalue(uint64_t *values,int32_t n,uint64_t targetval)
return(mini); return(mini);
} }
uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 myprivkey,bits256 mypub,uint8_t *pubkey33) uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 myprivkey,bits256 mypub)
{ {
char *script; struct LP_utxoinfo *utxo; cJSON *array,*item; bits256 txid,deposittxid; int32_t used,i,n,iambob,vout,depositvout; uint64_t *values=0,satoshis,depositval,targetval,value,total = 0; char *script; struct LP_utxoinfo *utxo; cJSON *array,*item; bits256 txid,deposittxid; int32_t used,i,n,iambob,vout,depositvout; uint64_t *values=0,satoshis,txfee,depositval,targetval,value,total = 0;
if ( coin == 0 ) if ( coin == 0 )
{ {
printf("coin not active\n"); printf("coin not active\n");
@ -678,6 +817,7 @@ uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypr
//printf("privkey init.(%s) %s\n",coin->symbol,coin->smartaddr); //printf("privkey init.(%s) %s\n",coin->symbol,coin->smartaddr);
if ( coin->inactive == 0 && (array= LP_listunspent(coin->symbol,coin->smartaddr)) != 0 ) if ( coin->inactive == 0 && (array= LP_listunspent(coin->symbol,coin->smartaddr)) != 0 )
{ {
txfee = LP_txfeecalc(coin->symbol,0);
if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{ {
for (iambob=0; iambob<=1; iambob++) for (iambob=0; iambob<=1; iambob++)
@ -692,14 +832,20 @@ uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypr
{ {
item = jitem(array,i); item = jitem(array,i);
satoshis = SATOSHIDEN * jdouble(item,"amount"); satoshis = SATOSHIDEN * jdouble(item,"amount");
if ( LP_inventory_prevent(iambob,jbits256(item,"txid"),juint(item,"vout")) == 0 ) if ( satoshis == 0 )
satoshis = SATOSHIDEN * jdouble(item,"value");
if ( LP_inventory_prevent(iambob,jbits256(item,"txid"),juint(item,"vout")) == 0 && jint(item,"confirmations") > 0 )
{
//printf("%s\n",jprint(item,0));
values[i] = satoshis; values[i] = satoshis;
else used++; } else used++;
//printf("%.8f ",dstr(satoshis)); //printf("%.8f ",dstr(satoshis));
} }
//printf("array.%d\n",n); //printf("array.%d\n",n);
while ( used < n-1 ) while ( used < n-1 )
{ {
//for (i=0; i<n; i++)
// printf("%.8f ",dstr(values[i]));
//printf("used.%d of n.%d\n",used,n); //printf("used.%d of n.%d\n",used,n);
if ( (i= LP_maxvalue(values,n)) >= 0 ) if ( (i= LP_maxvalue(values,n)) >= 0 )
{ {
@ -710,12 +856,20 @@ uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypr
depositval = values[i]; depositval = values[i];
values[i] = 0, used++; values[i] = 0, used++;
if ( iambob == 0 ) if ( iambob == 0 )
targetval = (depositval / 776) + 100000; targetval = (depositval / 776) + txfee;
else targetval = (depositval / 9) * 8 + 100000; else targetval = (depositval / 9) * 8 + 2*txfee;
//printf("i.%d %.8f target %.8f\n",i,dstr(depositval),dstr(targetval)); if ( depositval < (1+LP_MINSIZE_TXFEEMULT)*txfee )
if ( (i= LP_nearestvalue(values,n,targetval)) < 0 && iambob != 0 ) continue;
targetval /= 4; //printf("iambob.%d i.%d %.8f target %.8f\n",iambob,i,dstr(depositval),dstr(targetval));
if ( (i= LP_nearestvalue(values,n,targetval)) >= 0 ) i = -1;
if ( iambob != 0 )
{
if ( (i= LP_nearestvalue(iambob,values,n,targetval)) < 0 )
targetval /= 4;
if ( targetval < txfee*(1+LP_MINSIZE_TXFEEMULT) )
continue;
}
if ( i >= 0 || (i= LP_nearestvalue(iambob,values,n,targetval)) >= 0 )
{ {
item = jitem(array,i); item = jitem(array,i);
txid = jbits256(item,"txid"); txid = jbits256(item,"txid");
@ -727,20 +881,20 @@ uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypr
portable_mutex_lock(&LP_UTXOmutex); portable_mutex_lock(&LP_UTXOmutex);
if ( iambob != 0 ) if ( iambob != 0 )
{ {
if ( (utxo= LP_utxoadd(1,mypubsock,coin->symbol,txid,vout,value,deposittxid,depositvout,depositval,script,coin->smartaddr,mypub,LP_mypeer != 0 ? LP_mypeer->profitmargin : 0.01,LP_gui)) != 0 ) if ( (utxo= LP_utxoadd(1,mypubsock,coin->symbol,txid,vout,value,deposittxid,depositvout,depositval,script,coin->smartaddr,mypub,LP_gui,LP_sessionid)) != 0 )
{ {
} }
} }
else else
{ {
if ( (utxo= LP_utxoadd(0,mypubsock,coin->symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coin->smartaddr,mypub,0.,LP_gui)) != 0 ) if ( (utxo= LP_utxoadd(0,mypubsock,coin->symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coin->smartaddr,mypub,LP_gui,LP_sessionid)) != 0 )
{ {
} }
} }
portable_mutex_unlock(&LP_UTXOmutex); portable_mutex_unlock(&LP_UTXOmutex);
total += value; total += value;
} } else printf("scriptmismatch.(%s) vs %s\n",script,jprint(item,0));
} } //else printf("nothing near i.%d\n",i);
} else break; } else break;
} }
if ( iambob == 1 ) if ( iambob == 1 )
@ -753,29 +907,84 @@ uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypr
return(total); return(total);
} }
char *LP_secretaddresses(void *ctx,char *passphrase,int32_t n,uint8_t taddr,uint8_t pubtype)
{
int32_t i; uint8_t tmptype,pubkey33[33],rmd160[20]; char output[777*45],str[65],str2[65],buf[8192],wifstr[128],coinaddr[64]; bits256 checkprivkey,privkey,pubkey; cJSON *retjson;
retjson = cJSON_CreateObject();
if ( passphrase == 0 || passphrase[0] == 0 )
passphrase = "password";
if ( n <= 0 )
n = 16;
else if ( n > 777 )
n = 777;
conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase));
bitcoin_priv2pub(ctx,pubkey33,coinaddr,privkey,taddr,pubtype);
printf("generator (%s) secrets.[%d] <%s> t.%u p.%u\n",coinaddr,n,passphrase,taddr,pubtype);
sprintf(output,"\"addresses\":[");
for (i=0; i<n; i++)
{
sprintf(buf,"secretaddress %s %03d",passphrase,i);
conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)buf,(int32_t)strlen(buf));
bitcoin_priv2pub(ctx,pubkey33,coinaddr,privkey,taddr,pubtype);
bitcoin_priv2wif(0,wifstr,privkey,188);
bitcoin_wif2priv(0,&tmptype,&checkprivkey,wifstr);
bitcoin_addr2rmd160(taddr,&tmptype,rmd160,coinaddr);
if ( bits256_cmp(checkprivkey,privkey) != 0 )
{
printf("WIF.(%s) error -> %s vs %s?\n",wifstr,bits256_str(str,privkey),bits256_str(str2,checkprivkey));
free_json(retjson);
return(clonestr("{\"error\":\"couldnt validate wifstr\"}"));
}
else if ( tmptype != pubtype )
{
printf("checktype.%d != pubtype.%d\n",tmptype,pubtype);
free_json(retjson);
return(clonestr("{\"error\":\"couldnt validate pubtype\"}"));
}
jaddstr(retjson,coinaddr,wifstr);
sprintf(output+strlen(output),"\\\"%s\\\"%c ",coinaddr,i<n-1?',':' ');
printf("./komodo-cli jumblr_secret %s\n",coinaddr);
}
printf("%s]\n",output);
return(jprint(retjson,1));
}
bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguana_info *coin,char *passphrase,char *wifstr) 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; char tmpstr[128]; cJSON *retjson; uint8_t tmptype,rmd160[20]; bits256 privkey,userpub,userpass,checkkey; char tmpstr[128]; cJSON *retjson; uint8_t tmptype,rmd160[20];
if ( passphrase != 0 && passphrase[0] != 0 ) if ( passphrase != 0 && passphrase[0] != 0 )
conv_NXTpassword(privkey.bytes,pubkeyp->bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); conv_NXTpassword(privkey.bytes,pubkeyp->bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase));
else else
{ {
privkey = iguana_wif2privkey(wifstr); bitcoin_wif2priv(coin->wiftaddr,&tmptype,&privkey,wifstr);
//printf("WIF.(%s) -> %s\n",wifstr,bits256_str(str,privkey)); if ( 0 )
{
char str[65],str2[65];
checkkey = iguana_wif2privkey(wifstr);
if ( bits256_cmp(checkkey,privkey) != 0 )
printf("WIF.(%s) -> %s or %s?\n",wifstr,bits256_str(str,privkey),bits256_str(str2,checkkey));
}
} }
iguana_priv2pub(ctx,pubkey33,coin->smartaddr,privkey,coin->taddr,coin->pubtype); bitcoin_priv2pub(ctx,coin->pubkey33,coin->smartaddr,privkey,coin->taddr,coin->pubtype);
if ( coin->counter == 0 ) if ( coin->counter == 0 )
{ {
coin->counter++; coin->counter++;
bitcoin_priv2wif(tmpstr,privkey,coin->wiftype); bitcoin_priv2wif(coin->wiftaddr,tmpstr,privkey,coin->wiftype);
bitcoin_addr2rmd160(coin->taddr,&tmptype,rmd160,coin->smartaddr); bitcoin_addr2rmd160(coin->taddr,&tmptype,rmd160,coin->smartaddr);
LP_privkeyadd(privkey,rmd160); LP_privkeyadd(privkey,rmd160);
if ( 0 && (coin->pubtype != 60 || strcmp(coin->symbol,"KMD") == 0) ) 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); printf("%s (%s) %d wif.(%s) (%s)\n",coin->symbol,coin->smartaddr,coin->pubtype,tmpstr,passphrase);
if ( counter++ == 0 ) if ( counter++ == 0 )
{ {
bitcoin_priv2wif(USERPASS_WIFSTR,privkey,188); bitcoin_priv2wif(coin->wiftaddr,USERPASS_WIFSTR,privkey,188);
bitcoin_wif2priv(coin->wiftaddr,&tmptype,&checkkey,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));
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 *)USERPASS_WIFSTR,(int32_t)strlen(USERPASS_WIFSTR));
userpub = curve25519(userpass,curve25519_basepoint9()); userpub = curve25519(userpass,curve25519_basepoint9());
printf("userpass.(%s)\n",bits256_str(USERPASS,userpub)); printf("userpass.(%s)\n",bits256_str(USERPASS,userpub));
@ -789,8 +998,9 @@ bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguan
} }
} }
} }
LP_mypubkey = *pubkeyp = curve25519(privkey,curve25519_basepoint9()); LP_mypub25519 = *pubkeyp = curve25519(privkey,curve25519_basepoint9());
//printf("privkey.(%s) -> LP_mypubkey.(%s)\n",bits256_str(str,privkey),bits256_str(str2,LP_mypubkey)); LP_mypriv25519 = privkey;
//printf("privkey.(%s) -> LP_mypub25519.(%s)\n",bits256_str(str,privkey),bits256_str(str2,LP_mypub25519));
return(privkey); return(privkey);
} }
@ -805,7 +1015,7 @@ void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase,int32_t inito
if ( bits256_nonz(privkey) == 0 || coin->smartaddr[0] == 0 ) if ( bits256_nonz(privkey) == 0 || coin->smartaddr[0] == 0 )
privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,coin,passphrase,""); privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,coin,passphrase,"");
if ( coin->inactive == 0 && initonly == 0 ) if ( coin->inactive == 0 && initonly == 0 )
LP_privkey_init(pubsock,coin,privkey,pubkey,pubkey33); LP_privkey_init(pubsock,coin,privkey,pubkey);
} }
} }

0
iguana/exchanges/SVM/.tmpmarker

0
iguana/exchanges/SVM/models/.tmpmarker

0
iguana/exchanges/SVM/rawfeatures/.tmpmarker

2
iguana/exchanges/autofill

@ -0,0 +1,2 @@
source userpass
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autofill\",\"base\":\"KMD\",\"rel\":\"BTC\",\"price\":0.0005,\"relvolume\":0.1}"

9
iguana/exchanges/autoprice

@ -0,0 +1,9 @@
source userpass
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"BTC\",\"margin\":0.0001}"
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"BTC\",\"rel\":\"KMD\",\"margin\":0.0001}"
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"HUSH\",\"margin\":0.01}"
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"HUSH\",\"rel\":\"KMD\",\"margin\":0.01}"
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"USD\",\"margin\":0.01}"
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"USD\",\"rel\":\"KMD\",\"margin\":0.01}"
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"JUMBLR\",\"margin\":0.01}"
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"JUMBLR\",\"rel\":\"KMD\",\"margin\":0.01}"

11
iguana/exchanges/balance_loop

@ -0,0 +1,11 @@
source userpass
ht=$1
while true
do
#curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"snapshot\",\"coin\":\"KMD\",\"height\":$ht}"
ht=`curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"snapshot\",\"coin\":\"KMD\"}" | jq .blocks`
echo next height $ht
sleep 600
done

2
iguana/exchanges/cancelorder

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

4
iguana/exchanges/coins

File diff suppressed because one or more lines are too long

0
iguana/exchanges/confs/.tmpmarker

8
iguana/exchanges/debug

@ -0,0 +1,8 @@
source passphrase
source coins
pkill -15 marketmaker;
git pull;
cd ..;
./m_mm;
gdb -args ./marketmaker "{\"gui\":\"nogui\",\"client\":1, \"userhome\":\"/${HOME#"/"}\", \"passphrase\":\"$passphrase\", \"coins\":$coins}"

2
iguana/exchanges/deletemessages

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

2
iguana/exchanges/dividends

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

2
iguana/exchanges/forward

@ -1,2 +0,0 @@
source userpass
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"6578099f6474d9b8bd66a7a136b922029a989818ec0309aee962dd6ac1862b74\",\"method\":\"forward\",\"method2\":\"getprice\",\"base\":\"REVS\",\"rel\":\"KMD\"}"

0
iguana/exchanges/genesis/.tmpmarker

2
iguana/exchanges/getcoin

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

2
iguana/exchanges/getmessages

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

4
iguana/exchanges/goal

@ -0,0 +1,4 @@
source userpass
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"goal\",\"coin\":\"KMD\",\"val\":99}"
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"goal\",\"coin\":\"BTC\",\"val\":10}"
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"goal\",\"coin\":\"REVS\",\"val\":1}"

2
iguana/exchanges/goals

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

3
iguana/exchanges/install

@ -1,5 +1,4 @@
cp trade ordermatch bestfit orderbook autotrade client run_osx client_osx run coins disable enable forward myprice myprices getcoins getpeers getpeersIP getprices getutxos help inv lookup pub setprice status utxos ../dexscripts cp 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
cd ../dexscripts cd ../dexscripts
echo now in dexscripts directory where you can make customized scripts that wont conflict with git pull
#cp ../exchanges/passphrase ../exchanges/userpass . #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

2
iguana/exchanges/lookup

@ -1,2 +0,0 @@
source userpass
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"6578099f6474d9b8bd66a7a136b922029a989818ec0309aee962dd6ac1862b74\",\"method\":\"forward\",\"method2\":\"lookup\",\"client\":\"$1\"}"

2
iguana/exchanges/message

@ -0,0 +1,2 @@
source userpass
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"$1\",\"method\":\"sendmessage\",\"message\":\"some sort of message\"}"

19
iguana/exchanges/mm.c

@ -24,7 +24,7 @@
#include <stdint.h> #include <stdint.h>
#include "OS_portable.h" #include "OS_portable.h"
#define MAX(a,b) ((a) > (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b))
char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,cJSON *argjson,char *remoteaddr,uint16_t port); char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *remoteaddr,uint16_t port);
#include "stats.c" #include "stats.c"
void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32]); void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32]);
@ -179,10 +179,10 @@ char *iguana_walletpassphrase(char *passphrase,int32_t timeout)
return(bitcoind_RPC(0,"",url,0,"listunspent",postdata)); return(bitcoind_RPC(0,"",url,0,"listunspent",postdata));
}*/ }*/
/*char *issue_LP_intro(char *destip,uint16_t destport,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers) /*char *issue_LP_intro(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers)
{ {
char url[512]; char url[512];
sprintf(url,"http://%s:%u/api/stats/intro?ipaddr=%s&port=%u&profit=%.6f&numpeers=%d",destip,destport,ipaddr,port,profitmargin,numpeers); sprintf(url,"http://%s:%u/api/stats/intro?ipaddr=%s&port=%u&numpeers=%d",destip,destport,ipaddr,port,numpeers);
printf("(%s)\n",url); printf("(%s)\n",url);
return(issue_curl(url)); return(issue_curl(url));
}*/ }*/
@ -786,19 +786,26 @@ void marketmaker(double minask,double maxbid,char *baseaddr,char *reladdr,double
void LP_main(void *ptr) void LP_main(void *ptr)
{ {
char *passphrase; double profitmargin; cJSON *argjson = ptr; char *passphrase; double profitmargin; uint16_t port; cJSON *argjson = ptr;
if ( (passphrase= jstr(argjson,"passphrase")) != 0 ) if ( (passphrase= jstr(argjson,"passphrase")) != 0 )
{ {
profitmargin = jdouble(argjson,"profitmargin"); profitmargin = jdouble(argjson,"profitmargin");
LPinit(7779,7780,7781,profitmargin,passphrase,jint(argjson,"client"),jstr(argjson,"userhome"),argjson); LP_profitratio += profitmargin;
if ( (port= juint(argjson,"rpcport")) < 1000 )
port = 7779;
LPinit(port,7780,7781,7782,passphrase,jint(argjson,"client"),jstr(argjson,"userhome"),argjson);
} }
} }
int main(int argc, const char * argv[]) int main(int argc, const char * argv[])
{ {
char *base,*rel,*name,*exchange,*apikey,*apisecret,*blocktrail,*retstr,*baseaddr,*reladdr,*passphrase; char dirname[512],*base,*rel,*name,*exchange,*apikey,*apisecret,*blocktrail,*retstr,*baseaddr,*reladdr,*passphrase;
double profitmargin,maxexposure,incrratio,start_rel,start_base,minask,maxbid,incr; double profitmargin,maxexposure,incrratio,start_rel,start_base,minask,maxbid,incr;
cJSON *retjson,*loginjson; int32_t i; cJSON *retjson,*loginjson; int32_t i;
OS_init();
sprintf(dirname,"%s",GLOBAL_DBDIR), OS_ensure_directory(dirname);
sprintf(dirname,"%s/SWAPS",GLOBAL_DBDIR), OS_ensure_directory(dirname);
sprintf(dirname,"%s/PRICES",GLOBAL_DBDIR), OS_ensure_directory(dirname);
if ( argc > 1 && (retjson= cJSON_Parse(argv[1])) != 0 ) if ( argc > 1 && (retjson= cJSON_Parse(argv[1])) != 0 )
{ {
if ( (passphrase= jstr(retjson,"passphrase")) == 0 ) if ( (passphrase= jstr(retjson,"passphrase")) == 0 )

2
iguana/exchanges/numutxos

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

2
iguana/exchanges/portfolio

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

2
iguana/exchanges/pricearray

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

5
iguana/exchanges/secretaddresses

@ -0,0 +1,5 @@
source userpass
echo "usage: ./secretaddresses 'passphrase'"
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"secretaddresses\",\"num\":16,\"passphrase\":\"$1\"}"

2
iguana/exchanges/snapshot

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

4
iguana/exchanges/snapshot_balance

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

11
iguana/exchanges/snapshot_loop

@ -0,0 +1,11 @@
source userpass
ht=$1
while true
do
curl --url "http://127.0.0.1:7779" --data "{\"userpass\":\"$userpass\",\"method\":\"snapshot\",\"coin\":\"KMD\",\"height\":$ht}"
#ht=`komodo-cli getinfo | jq .blocks`
ht=$(( $ht + 1000 ))
echo next height $ht
sleep 1
done

25
iguana/exchanges/stats.c

@ -21,11 +21,12 @@
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include "OS_portable.h" #include "../../crypto777/OS_portable.h"
#define MAX(a,b) ((a) > (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b))
#define STATS_DESTDIR "/var/www/html" #define STATS_DESTDIR "/var/www/html"
#define STATS_DEST "/var/www/html/DEXstats.json" #define STATS_DEST "/var/www/html/DEXstats.json"
#include "DEXstats.h" #include "DEXstats.h"
char *stats_JSON(void *ctx,char *myipaddr,int32_t mypubsock,cJSON *argjson,char *remoteaddr,uint16_t port);
#ifndef WIN32 #ifndef WIN32
#ifndef MSG_NOSIGNAL #ifndef MSG_NOSIGNAL
@ -307,7 +308,7 @@ extern void *bitcoin_ctx();
char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *postflagp,char *urlstr,char *remoteaddr,char *filetype,uint16_t port) char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *postflagp,char *urlstr,char *remoteaddr,char *filetype,uint16_t port)
{ {
static void *ctx; static void *ctx;
cJSON *tokens,*argjson,*origargjson,*tmpjson=0,*json = 0; long filesize; double profitmargin = 0.; char *myipaddr="127.0.0.1",symbol[64],buf[4096],*userpass=0,urlmethod[16],*data,url[8192],furl[8192],*retstr,*filestr,*token = 0; int32_t i,j,n,num=0; cJSON *tokens,*argjson,*origargjson,*tmpjson=0,*json = 0; long filesize; char *myipaddr="127.0.0.1",symbol[64],buf[4096],*userpass=0,urlmethod[16],*data,url[8192],furl[8192],*retstr,*filestr,*token = 0; int32_t i,j,n,num=0;
//printf("rpcparse.(%s)\n",urlstr); //printf("rpcparse.(%s)\n",urlstr);
if ( ctx == 0 ) if ( ctx == 0 )
ctx = bitcoin_ctx(); ctx = bitcoin_ctx();
@ -493,7 +494,7 @@ char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *po
if ( userpass != 0 && jstr(argjson,"userpass") == 0 ) if ( userpass != 0 && jstr(argjson,"userpass") == 0 )
jaddstr(argjson,"userpass",userpass); jaddstr(argjson,"userpass",userpass);
//printf("after urlconv.(%s) argjson.(%s)\n",jprint(json,0),jprint(argjson,0)); //printf("after urlconv.(%s) argjson.(%s)\n",jprint(json,0),jprint(argjson,0));
if ( (retstr= stats_JSON(ctx,myipaddr,-1,profitmargin,argjson,remoteaddr,port)) != 0 ) if ( (retstr= stats_JSON(ctx,myipaddr,-1,argjson,remoteaddr,port)) != 0 )
{ {
if ( (retitem= cJSON_Parse(retstr)) != 0 ) if ( (retitem= cJSON_Parse(retstr)) != 0 )
jaddi(retarray,retitem); jaddi(retarray,retitem);
@ -516,7 +517,7 @@ char *stats_rpcparse(char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *po
//printf("ARGJSON.(%s)\n",jprint(arg,0)); //printf("ARGJSON.(%s)\n",jprint(arg,0));
if ( userpass != 0 && jstr(arg,"userpass") == 0 ) if ( userpass != 0 && jstr(arg,"userpass") == 0 )
jaddstr(arg,"userpass",userpass); jaddstr(arg,"userpass",userpass);
retstr = stats_JSON(ctx,myipaddr,-1,profitmargin,arg,remoteaddr,port); retstr = stats_JSON(ctx,myipaddr,-1,arg,remoteaddr,port);
} }
free_json(argjson); free_json(argjson);
free_json(json); free_json(json);
@ -558,7 +559,7 @@ void stats_rpcloop(void *args)
uint16_t port; char filetype[128],content_type[128]; uint16_t port; char filetype[128],content_type[128];
int32_t recvlen,flag,bindsock,postflag=0,contentlen,sock,remains,numsent,jsonflag=0,hdrsize,len; int32_t recvlen,flag,bindsock,postflag=0,contentlen,sock,remains,numsent,jsonflag=0,hdrsize,len;
socklen_t clilen; char helpname[512],remoteaddr[64],*buf,*retstr,*space; socklen_t clilen; char helpname[512],remoteaddr[64],*buf,*retstr,*space;
struct sockaddr_in cli_addr; uint32_t ipbits,i,size = IGUANA_MAXPACKETSIZE + 512; struct sockaddr_in cli_addr; uint32_t ipbits,i,size = 32*IGUANA_MAXPACKETSIZE + 512;
if ( (port= *(uint16_t *)args) == 0 ) if ( (port= *(uint16_t *)args) == 0 )
port = 7779; port = 7779;
if ( jsonbuf == 0 ) if ( jsonbuf == 0 )
@ -665,9 +666,11 @@ void stats_rpcloop(void *args)
if ( retstr != 0 ) if ( retstr != 0 )
{ {
char *response,hdrs[1024]; char *response,hdrs[1024];
//printf("RETURN.(%s)\n",retstr); //printf("RETURN.(%s) jsonflag.%d postflag.%d\n",retstr,jsonflag,postflag);
if ( jsonflag != 0 || postflag != 0 ) if ( jsonflag != 0 || postflag != 0 )
{ {
if ( retstr == 0 )
retstr = clonestr("{}");
response = malloc(strlen(retstr)+1024+1+1); response = malloc(strlen(retstr)+1024+1+1);
sprintf(hdrs,"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Credentials: true\r\nAccess-Control-Allow-Methods: GET, POST\r\nCache-Control : no-cache, no-store, must-revalidate\r\n%sContent-Length : %8d\r\n\r\n",content_type,(int32_t)strlen(retstr)); sprintf(hdrs,"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Credentials: true\r\nAccess-Control-Allow-Methods: GET, POST\r\nCache-Control : no-cache, no-store, must-revalidate\r\n%sContent-Length : %8d\r\n\r\n",content_type,(int32_t)strlen(retstr));
response[0] = '\0'; response[0] = '\0';
@ -677,6 +680,7 @@ void stats_rpcloop(void *args)
if ( retstr != space ) if ( retstr != space )
free(retstr); free(retstr);
retstr = response; retstr = response;
//printf("RET.(%s)\n",retstr);
} }
remains = (int32_t)strlen(retstr); remains = (int32_t)strlen(retstr);
i = 0; i = 0;
@ -726,8 +730,8 @@ void stats_kvjson(FILE *logfp,int32_t height,int32_t savedheight,uint32_t timest
void komodo_kvupdate(FILE *logfp,struct komodo_state *sp,int32_t ht,bits256 txid,int32_t vout,uint8_t *opretbuf,int32_t opretlen,uint64_t value) void komodo_kvupdate(FILE *logfp,struct komodo_state *sp,int32_t ht,bits256 txid,int32_t vout,uint8_t *opretbuf,int32_t opretlen,uint64_t value)
{ {
static bits256 zeroes; //static bits256 zeroes;
uint32_t flags; bits256 pubkey,refpubkey,sig; cJSON *kvjson; char decodestr[10000]; int32_t i,refvaluesize,hassig,coresize,haspubkey,height,kvheight; uint16_t keylen,valuesize,newflag = 0; uint8_t *key,*valueptr,keyvalue[10000]; uint32_t flags; bits256 pubkey,sig; cJSON *kvjson; char decodestr[10000]; int32_t i,hassig,coresize,haspubkey,height; uint16_t keylen,valuesize; uint8_t *key,*valueptr; // bits256 refpubkey; int32_t refvaluesize,kvheight; uint16_t newflag = 0; uint8_t keyvalue[10000];
iguana_rwnum(0,&opretbuf[1],sizeof(keylen),&keylen); iguana_rwnum(0,&opretbuf[1],sizeof(keylen),&keylen);
iguana_rwnum(0,&opretbuf[3],sizeof(valuesize),&valuesize); iguana_rwnum(0,&opretbuf[3],sizeof(valuesize),&valuesize);
iguana_rwnum(0,&opretbuf[5],sizeof(height),&height); iguana_rwnum(0,&opretbuf[5],sizeof(height),&height);
@ -830,7 +834,7 @@ void komodo_eventadd_kmdheight(struct komodo_state *sp,char *symbol,int32_t heig
void stats_pricefeed(struct komodo_state *sp,char *symbol,int32_t ht,uint32_t *pvals,int32_t numpvals) void stats_pricefeed(struct komodo_state *sp,char *symbol,int32_t ht,uint32_t *pvals,int32_t numpvals)
{ {
struct tai T; int32_t seconds,datenum,n; cJSON *argjson; struct tai T; int32_t seconds,datenum; cJSON *argjson;
if ( ht > 300000 && pvals[32] != 0 ) if ( ht > 300000 && pvals[32] != 0 )
{ {
datenum = OS_conv_unixtime(&T,&seconds,sp->SAVEDTIMESTAMP); datenum = OS_conv_unixtime(&T,&seconds,sp->SAVEDTIMESTAMP);
@ -930,7 +934,7 @@ int32_t komodo_parsestatefile(FILE *logfp,struct komodo_state *sp,FILE *fp,char
{ {
if ( fread(opret,1,olen,fp) != olen ) if ( fread(opret,1,olen,fp) != olen )
errs++; errs++;
if ( 0 && matched != 0 ) if ( (0) && matched != 0 )
{ {
int32_t i; for (i=0; i<olen; i++) int32_t i; for (i=0; i<olen; i++)
printf("%02x",opret[i]); printf("%02x",opret[i]);
@ -1003,6 +1007,7 @@ int32_t stats_stateupdate(FILE *logfp,char *destdir,char *statefname,int32_t max
strcpy(base,"KMD"); strcpy(base,"KMD");
strcpy(symbol,"KMD"); strcpy(symbol,"KMD");
} }
return(n);
} }
char *stats_update(FILE *logfp,char *destdir,char *statefname,char *komodofname) char *stats_update(FILE *logfp,char *destdir,char *statefname,char *komodofname)

0
iguana/exchanges/tmp/.tmpmarker

3
iguana/exchanges/userpass

@ -1 +1,2 @@
export userpass="<put the userpass value from the first API call here>" #export userpass="<put the userpass value from the first API call here>"
export userpass="c3d8c2a364b7d18c1f9d7321d017b92e9f9c791e4f5c741214fefdea8a071256"

19
iguana/iguana777.c

@ -105,25 +105,6 @@ void iguana_recvalloc(struct iguana_info *coin,int32_t numitems)
//coin->blocks.maxbits = numitems; //coin->blocks.maxbits = numitems;
} }
static int _decreasing_double(const void *a,const void *b)
{
#define double_a (*(double *)a)
#define double_b (*(double *)b)
if ( double_b > double_a )
return(1);
else if ( double_b < double_a )
return(-1);
return(0);
#undef double_a
#undef double_b
}
static int32_t revsortds(double *buf,uint32_t num,int32_t size)
{
qsort(buf,num,size,_decreasing_double);
return(0);
}
double iguana_metric(struct iguana_peer *addr,uint32_t now,double decay) double iguana_metric(struct iguana_peer *addr,uint32_t now,double decay)
{ {
int32_t duration; double metric = addr->recvblocks * addr->recvtotal; int32_t duration; double metric = addr->recvblocks * addr->recvtotal;

3
iguana/iguana_exchanges.c

@ -784,7 +784,8 @@ void exchanges777_loop(void *ptr)
printf("exchanges loop.(%s)\n",exchange->name); printf("exchanges loop.(%s)\n",exchange->name);
while ( 1 ) while ( 1 )
{ {
PAX_idle(myinfo); if ( strcmp("bitcoin",exchange->name) == 0 )
PAX_idle(myinfo);
flag = retval = 0; flag = retval = 0;
retstr = 0; retstr = 0;
if ( (req= queue_dequeue(&exchange->requestQ)) != 0 ) if ( (req= queue_dequeue(&exchange->requestQ)) != 0 )

4
iguana/iguana_msg.c

@ -640,7 +640,7 @@ int32_t iguana_rwtx(struct supernet_info *myinfo,uint8_t zcash,int32_t rwflag,st
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->timestamp),&msg->timestamp); len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->timestamp),&msg->timestamp);
} }
len += iguana_rwvarint32(rwflag,&serialized[len],&msg->tx_in); len += iguana_rwvarint32(rwflag,&serialized[len],&msg->tx_in);
if ( rwflag == 0 ) if ( rwflag == 0 && msg->tx_in > 0 )
msg->vins = iguana_memalloc(mem,msg->tx_in * sizeof(*msg->vins),1); msg->vins = iguana_memalloc(mem,msg->tx_in * sizeof(*msg->vins),1);
if ( maxsize-len <= 0 ) if ( maxsize-len <= 0 )
return(-1); return(-1);
@ -671,7 +671,7 @@ int32_t iguana_rwtx(struct supernet_info *myinfo,uint8_t zcash,int32_t rwflag,st
return(-1); return(-1);
} }
//printf("numvouts.%d ",msg->tx_out); //printf("numvouts.%d ",msg->tx_out);
if ( rwflag == 0 ) if ( rwflag == 0 && msg->tx_out > 0 )
msg->vouts = iguana_memalloc(mem,msg->tx_out * sizeof(*msg->vouts),1); msg->vouts = iguana_memalloc(mem,msg->tx_out * sizeof(*msg->vouts),1);
for (i=0; i<msg->tx_out; i++) for (i=0; i<msg->tx_out; i++)
{ {

4
iguana/iguana_notary.c

@ -71,9 +71,7 @@ void dpow_srcupdate(struct supernet_info *myinfo,struct dpow_info *dp,int32_t he
else else
{ {
freq = 1; freq = 1;
//minsigs = 7;//(komodo_notaries(dp->symbol,pubkeys,height) >> 1) + 1; minsigs = 11;
//if ( minsigs < DPOW_MINSIGS )
minsigs = DPOW_MINSIGS;
} }
printf("%s/%s src ht.%d dest.%u nonz.%d %s minsigs.%d\n",dp->symbol,dp->dest,checkpoint.blockhash.height,dp->destupdated,bits256_nonz(checkpoint.blockhash.hash),bits256_str(str,dp->last.blockhash.hash),minsigs); printf("%s/%s src ht.%d dest.%u nonz.%d %s minsigs.%d\n",dp->symbol,dp->dest,checkpoint.blockhash.height,dp->destupdated,bits256_nonz(checkpoint.blockhash.hash),bits256_str(str,dp->last.blockhash.hash),minsigs);
dpow_fifoupdate(myinfo,dp->srcfifo,dp->last); dpow_fifoupdate(myinfo,dp->srcfifo,dp->last);

1
iguana/iguana_peers.c

@ -488,6 +488,7 @@ int32_t iguana_socket(int32_t bindflag,char *hostname,uint16_t port)
{ {
sleep(1); sleep(1);
printf("ERROR BINDING PORT.%d. this is normal tcp timeout, unless another process is using port\n",port); printf("ERROR BINDING PORT.%d. this is normal tcp timeout, unless another process is using port\n",port);
fflush(stdout);
sleep(3); sleep(3);
printf("%s(%s) port.%d try again: %s sock.%d. errno.%d\n",bindflag!=0?"bind":"connect",hostname,port,strerror(errno),sock,errno); printf("%s(%s) port.%d try again: %s sock.%d. errno.%d\n",bindflag!=0?"bind":"connect",hostname,port,strerror(errno),sock,errno);
if ( bindflag == 1 ) if ( bindflag == 1 )

32
iguana/iguana_ramchain.c

@ -184,7 +184,7 @@ uint32_t iguana_ramchain_addtxid(struct iguana_info *coin,RAMCHAIN_FUNC,bits256
{ {
if ( t->txidind != txidind || memcmp(t->txid.bytes,txid.bytes,sizeof(bits256)) != 0 || t->numvouts != numvouts || t->numvins != numvins || t->firstvout != ramchain->H.unspentind || t->firstvin != ramchain->H.spendind || t->locktime != locktime || t->version != version || t->timestamp != timestamp ) if ( t->txidind != txidind || memcmp(t->txid.bytes,txid.bytes,sizeof(bits256)) != 0 || t->numvouts != numvouts || t->numvins != numvins || t->firstvout != ramchain->H.unspentind || t->firstvin != ramchain->H.spendind || t->locktime != locktime || t->version != version || t->timestamp != timestamp )
{ {
printf("iguana_ramchain_addtxid.RO: addtxid mismatch (%u %d %d %u %u) vs. (%d %d %d %d %d)\n",(uint32_t)t->txidind,t->numvouts,t->numvins,(uint32_t)t->firstvout,(uint32_t)t->firstvin,txidind,numvouts,numvins,ramchain->H.unspentind,ramchain->H.spendind); printf("iguana_ramchain_addtxid.RO: addtxid mismatch b.%d (%u %d %d %u %u) vs. (%d %d %d %d %d)\n",bundlei,(uint32_t)t->txidind,t->numvouts,t->numvins,(uint32_t)t->firstvout,(uint32_t)t->firstvin,txidind,numvouts,numvins,ramchain->H.unspentind,ramchain->H.spendind);
//getchar(); //getchar();
return(0); return(0);
} }
@ -1126,7 +1126,7 @@ int32_t iguana_ramchain_verify(struct iguana_info *coin,struct iguana_ramchain *
return(-3); return(-3);
} }
} }
for (k=0; k<t->numvouts; k++,ramchain->H.unspentind++) for (k=0; k<t->numvouts; k++)
{ {
u = &Ux[ramchain->H.unspentind]; u = &Ux[ramchain->H.unspentind];
if ( u->txidind != ramchain->H.txidind ) if ( u->txidind != ramchain->H.txidind )
@ -1148,17 +1148,19 @@ int32_t iguana_ramchain_verify(struct iguana_info *coin,struct iguana_ramchain *
printf("%p itemind.%d pkind.%d %d unspentind?\n",p,ptr->hh.itemind,pkind,ramchain->H.unspentind); printf("%p itemind.%d pkind.%d %d unspentind?\n",p,ptr->hh.itemind,pkind,ramchain->H.unspentind);
return(-9); return(-9);
} }
ramchain->H.unspentind++;
} }
} }
else else
{ {
for (k=0; k<t->numvouts; k++,ramchain->H.unspentind++) for (k=0; k<t->numvouts; k++)
{ {
if ( U[ramchain->H.unspentind].txidind != ramchain->H.txidind ) if ( U[ramchain->H.unspentind].txidind != ramchain->H.txidind )
{ {
printf(" k.%d U.%d u->txidind.%x != txidind.%d\n",k,ramchain->H.unspentind,U[ramchain->H.unspentind].txidind,ramchain->H.txidind); printf(" k.%d U.%d u->txidind.%x != txidind.%d\n",k,ramchain->H.unspentind,U[ramchain->H.unspentind].txidind,ramchain->H.txidind);
return(-6); return(-6);
} }
ramchain->H.unspentind++;
} }
} }
ramchain->H.spendind += t->numvins; ramchain->H.spendind += t->numvins;
@ -1167,7 +1169,7 @@ int32_t iguana_ramchain_verify(struct iguana_info *coin,struct iguana_ramchain *
for (ramchain->H.txidind=rdata->firsti; ramchain->H.txidind<rdata->numtxids; ramchain->H.txidind++) for (ramchain->H.txidind=rdata->firsti; ramchain->H.txidind<rdata->numtxids; ramchain->H.txidind++)
{ {
t = &T[ramchain->H.txidind]; t = &T[ramchain->H.txidind];
for (k=0; k<t->numvins; k++,ramchain->H.spendind++) for (k=0; k<t->numvins; k++)
{ {
if ( ramchain->expanded != 0 ) if ( ramchain->expanded != 0 )
{ {
@ -1190,6 +1192,7 @@ int32_t iguana_ramchain_verify(struct iguana_info *coin,struct iguana_ramchain *
} }
} }
} }
ramchain->H.spendind++;
} }
} }
if ( ramchain->expanded != 0 && ramchain->A != ramchain->creditsA ) if ( ramchain->expanded != 0 && ramchain->A != ramchain->creditsA )
@ -1655,6 +1658,8 @@ int32_t iguana_ramchain_iterate(struct supernet_info *myinfo,struct iguana_info
printf("iguana_ramchain_iterate cant iterate without data\n"); printf("iguana_ramchain_iterate cant iterate without data\n");
return(-1); return(-1);
} }
if ( rdata->firsti != 1 )
printf("unexpected firsti.%d %s.%d\n",rdata->firsti,coin->symbol,bundlei);
if ( dest != 0 ) if ( dest != 0 )
{ {
// required to do one block at a time, all vins/vouts the same height are assumed to happen simultaneously with vouts before vins // required to do one block at a time, all vins/vouts the same height are assumed to happen simultaneously with vouts before vins
@ -1899,14 +1904,15 @@ long iguana_ramchain_data(struct supernet_info *myinfo,struct iguana_info *coin,
} }
if ( block != 0 ) if ( block != 0 )
block->fpipbits = 1; block->fpipbits = 1;
for (i=0; i<txn_count; i++,ramchain->H.txidind++) for (i=0; i<txn_count; i++)
{ {
tx = &txarray[i]; tx = &txarray[i];
iguana_ramchain_addtxid(coin,RAMCHAIN_ARG,tx->txid,tx->tx_out,tx->tx_in,tx->lock_time,tx->version,tx->timestamp,bundlei); iguana_ramchain_addtxid(coin,RAMCHAIN_ARG,tx->txid,tx->tx_out,tx->tx_in,tx->lock_time,tx->version,tx->timestamp,bundlei);
if ( tx->tx_out == 0 && tx->tx_in == 0 ) if ( tx->tx_out == 0 )
{ {
printf("strange tx without any inputs or outputs? ht.%d\n",bp->bundleheight); if ( coin->chain->zcash == 0 )
break; printf("strange tx without any inputs or outputs? ht.%d\n",bp->bundleheight);
continue;
} }
for (j=0; j<tx->tx_out; j++) for (j=0; j<tx->tx_out; j++)
{ {
@ -1915,16 +1921,18 @@ long iguana_ramchain_data(struct supernet_info *myinfo,struct iguana_info *coin,
iguana_ramchain_addunspent20(coin,addr,RAMCHAIN_ARG,tx->vouts[j].value,tx->vouts[j].pk_script,tx->vouts[j].pk_scriptlen,tx->txid,j,-1,bp,rmd160); iguana_ramchain_addunspent20(coin,addr,RAMCHAIN_ARG,tx->vouts[j].value,tx->vouts[j].pk_script,tx->vouts[j].pk_scriptlen,tx->txid,j,-1,bp,rmd160);
} }
ramchain->H.spendind += tx->tx_in; ramchain->H.spendind += tx->tx_in;
ramchain->H.txidind++;
} }
//printf("scriptoffset.%d after %d txids\n",ramchain->H.scriptoffset,txn_count); //printf("scriptoffset.%d after %d txids\n",ramchain->H.scriptoffset,txn_count);
ramchain->H.txidind = ramchain->H.spendind = rdata->firsti; ramchain->H.txidind = ramchain->H.spendind = rdata->firsti;
for (i=0; i<txn_count; i++,ramchain->H.txidind++) for (i=0; i<txn_count; i++)
{ {
tx = &txarray[i]; tx = &txarray[i];
for (j=0; j<tx->tx_in; j++) for (j=0; j<tx->tx_in; j++)
{ {
iguana_ramchain_addspend256(coin,addr,RAMCHAIN_ARG,tx->vins[j].prev_hash,tx->vins[j].prev_vout,tx->vins[j].vinscript,tx->vins[j].scriptlen,tx->vins[j].sequence,bp);//,bp->hdrsi,bundlei); iguana_ramchain_addspend256(coin,addr,RAMCHAIN_ARG,tx->vins[j].prev_hash,tx->vins[j].prev_vout,tx->vins[j].vinscript,tx->vins[j].scriptlen,tx->vins[j].sequence,bp);//,bp->hdrsi,bundlei);
} }
ramchain->H.txidind++;
} }
rdata->prevhash2 = origtxdata->zblock.RO.prev_block; rdata->prevhash2 = origtxdata->zblock.RO.prev_block;
rdata->scriptspace = scriptspace = ramchain->H.scriptoffset; rdata->scriptspace = scriptspace = ramchain->H.scriptoffset;
@ -2487,13 +2495,17 @@ int32_t iguana_mapchaininit(char *fname,struct iguana_info *coin,struct iguana_r
int32_t iguana_bundlesaveHT(struct supernet_info *myinfo,struct iguana_info *coin,struct OS_memspace *mem,struct OS_memspace *memB,struct iguana_bundle *bp,uint32_t starttime) // helper thread int32_t iguana_bundlesaveHT(struct supernet_info *myinfo,struct iguana_info *coin,struct OS_memspace *mem,struct OS_memspace *memB,struct iguana_bundle *bp,uint32_t starttime) // helper thread
{ {
static int depth; static int depth;
RAMCHAIN_DESTDECLARE; RAMCHAIN_DECLARE; RAMCHAIN_ZEROES; RAMCHAIN_DESTDECLARE; RAMCHAIN_DECLARE; RAMCHAIN_ZEROES; static struct iguana_blockRO *_destB;
void **ptrs; long *filesizes; uint32_t *ipbits; char fname[1024]; void **ptrs; long *filesizes; uint32_t *ipbits; char fname[1024];
struct iguana_ramchain *R,*mapchain,*dest,newchain; uint32_t fpipbits; bits256 prevhash2; struct iguana_ramchain *R,*mapchain,*dest,newchain; uint32_t fpipbits; bits256 prevhash2;
int32_t i,starti,endi,bp_n,numtxids,valid,sigspace,pubkeyspace,numunspents,numspends,numpkinds,numexternaltxids,scriptspace; struct iguana_block *block; long fpos; int32_t i,starti,endi,bp_n,numtxids,valid,sigspace,pubkeyspace,numunspents,numspends,numpkinds,numexternaltxids,scriptspace; struct iguana_block *block; long fpos;
struct OS_memspace HASHMEM; int32_t err,j,num,bundlei,firsti= 1,retval = -1; struct OS_memspace HASHMEM; int32_t err,j,num,bundlei,firsti= 1,retval = -1;
memset(&HASHMEM,0,sizeof(HASHMEM)); memset(&HASHMEM,0,sizeof(HASHMEM));
starti = 0, endi = bp->n - 1; starti = 0, endi = bp->n - 1;
if ( _destB == 0 )
_destB = malloc(sizeof(*_destB) * 2000);
destB = _destB;
memset(destB,0,sizeof(*destB) * bp->n);
//B = 0, Ux = 0, Sx = 0, P = 0, A = 0, X = 0, Kspace = TXbits = PKbits = 0, U = 0, S = 0, T = 0; //B = 0, Ux = 0, Sx = 0, P = 0, A = 0, X = 0, Kspace = TXbits = PKbits = 0, U = 0, S = 0, T = 0;
R = mycalloc('s',bp->n,sizeof(*R)); R = mycalloc('s',bp->n,sizeof(*R));
ptrs = mycalloc('w',bp->n,sizeof(*ptrs)); ptrs = mycalloc('w',bp->n,sizeof(*ptrs));

1
iguana/iguana_rpc.c

@ -1170,6 +1170,7 @@ void iguana_rpcloop(void *args)
sleep(3); sleep(3);
} }
printf(">>>>>>>>>> iguana_rpcloop 127.0.0.1:%d bind sock.%d iguana API enabled <<<<<<<<<\n",port,bindsock); printf(">>>>>>>>>> iguana_rpcloop 127.0.0.1:%d bind sock.%d iguana API enabled <<<<<<<<<\n",port,bindsock);
fflush(stdout);
space = calloc(1,size); space = calloc(1,size);
while ( bindsock >= 0 ) while ( bindsock >= 0 )
{ {

2
iguana/iguana_sign.c

@ -1276,7 +1276,7 @@ cJSON *bitcoin_txcreate(char *symbol,int32_t isPoS,int64_t locktime,uint32_t txv
cJSON *json = cJSON_CreateObject(); cJSON *json = cJSON_CreateObject();
jaddnum(json,"version",txversion); jaddnum(json,"version",txversion);
if ( locktime == 0 && strcmp(symbol,"KMD") == 0 ) if ( locktime == 0 && strcmp(symbol,"KMD") == 0 )
locktime = (uint32_t)time(NULL); locktime = (uint32_t)time(NULL) - 55;
jaddnum(json,"locktime",locktime); jaddnum(json,"locktime",locktime);
if ( isPoS != 0 ) if ( isPoS != 0 )
jaddnum(json,"timestamp",timestamp == 0 ? time(NULL) : timestamp); jaddnum(json,"timestamp",timestamp == 0 ? time(NULL) : timestamp);

2
iguana/m_LP_StaticNanoMsg

@ -6,7 +6,7 @@ cd secp256k1; ./m_unix; cd ..
cd ../crypto777; make -f m_LP_StaticNanoMsg all; make -f m_LP_StaticNanoMsg clean; cd ../iguana cd ../crypto777; make -f m_LP_StaticNanoMsg all; make -f m_LP_StaticNanoMsg clean; cd ../iguana
clang -g -Wno-deprecated -c -O2 -DLIQUIDITY_PROVIDER=1 -DUSE_STATIC_NANOMSG *.c ../basilisk/basilisk.c ../gecko/gecko.c ../datachain/datachain.c clang -g -Wno-deprecated -c -O2 -DLIQUIDITY_PROVIDER=1 -DUSE_STATIC_NANOMSG *.c ../basilisk/basilisk.c ../gecko/gecko.c ../datachain/datachain.c
clang -g -Wno-deprecated -c -DLIQUIDITY_PROVIDER=1 -DUSE_STATIC_NANOMSG main.c iguana777.c iguana_bundles.c ../basilisk/basilisk.c clang -g -Wno-deprecated -c -DLIQUIDITY_PROVIDER=1 -DUSE_STATIC_NANOMSG main.c iguana777.c iguana_bundles.c ../basilisk/basilisk.c iguana_ramchain.c
clang -g -o ../agents/iguana *.o ../agents/libcrypto777.a ../OSlibs/linux/$(uname -m)/libnanomsg-static.a -lcurl -lssl -lcrypto -lpthread -lz -lm -lanl -lrt -lnsl clang -g -o ../agents/iguana *.o ../agents/libcrypto777.a ../OSlibs/linux/$(uname -m)/libnanomsg-static.a -lcurl -lssl -lcrypto -lpthread -lz -lm -lanl -lrt -lnsl

28
iguana/m_mm_StaticNanoMsg

@ -0,0 +1,28 @@
# makefile for marketmaker uses static nanomsg
# author: fadedreamz@SuperNet.org
# date: Aug, 2017
LIB_ARCH=$(uname -m)
.PHONY: clean all
err:
@echo "no rule specified, use {clean,all}"
exit 1
clean:
- rm -f ../agents/iguana *.o
- rm ../agents/marketmaker
all:
@echo "Add -j(core count + 1) to speed up build - e,g make -j5 -f m_mm_StaticNanoMsg; on a quad core cpu"
+$(MAKE) -C secp256k1 -f m_unix_Makefile all
+$(MAKE) -C ../crypto777 -f m_LP_StaticNanoMsg all
+$(MAKE) -C ../crypto777 -f m_LP_StaticNanoMsg clean
$(CC) -o ../agents/marketmaker -I../crypto777 exchanges/mm.c ../crypto777/cJSON.c mini-gmp.c secp256k1.o ../agents/libcrypto777.a ../OSlibs/linux/$(shell uname -m)/libnanomsg-static.a -lcurl -lpthread -lm -lanl
@echo "==========================="
@echo " marketmaker -> `pwd`/../agents/marketmaker"
@echo "==========================="

7
iguana/secp256k1/m_unix_Makefile

@ -0,0 +1,7 @@
# author: fadedreamz@SuperNet.org
# date: August, 2017
all:
gcc -c -o ../secp256k1.o -I. -I./src -I./include -I./src -O3 -W -std=c89 -pedantic -Wall -Wextra -Wcast-align -Wnested-externs -Wshadow -Wstrict-prototypes -Wno-unused-function -Wno-long-long -Wno-overlength-strings -fvisibility=hidden -DHAVE_CONFIG_H src/secp256k1.c
.PHONY: all

2
iguana/tests/rawtx2

@ -1,2 +1,2 @@
#!/bin/bash #!/bin/bash
curl --url "http://127.0.0.1:7778" --data "{\"coin\":\"BTCD\",\"agent\":\"basilisk\",\"method\":\"rawtx\",\"vals\":{\"changeaddr\":\"RRyBxbrAPRUBCUpiJgJZYrkxqrh8x5ta9Z\",\"addresses\":[\"RFMEYcxuBL8S7UPdUbzXunPtS4p82HRcKs\", \"RRyBxbrAPRUBCUpiJgJZYrkxqrh8x5ta9Z\", \"RDBjpRUqV1AXzVJCBbbXNskgxGRj711qSc\", \"RL4aMgTBzkM1kX7d8QtE2oYXuAj2ZKabmW\", \"RDE9LBKqMaKgQgnsZM3hFCNeWfoXkHWMLs\", \"RDBjpRUqV1AXzVJCBbbXNskgxGRj711qSc\"],\"timeout\":15000,\"satoshis\":\"128700\",\"spendscript\":\"76a9142b4cf64627268ac24effd9aad5895e8ca862114288ac\",\"txfee\":\"10000\",\"burn\":0.00000000}}" curl --url "http://127.0.0.1:7778" --data "{\"coin\":\"KMD\",\"agent\":\"basilisk\",\"method\":\"rawtx\",\"vals\":{\"changeaddr\":\"RRyBxbrAPRUBCUpiJgJZYrkxqrh8x5ta9Z\",\"addresses\":[\"RFMEYcxuBL8S7UPdUbzXunPtS4p82HRcKs\", \"RRyBxbrAPRUBCUpiJgJZYrkxqrh8x5ta9Z\", \"RDBjpRUqV1AXzVJCBbbXNskgxGRj711qSc\", \"RL4aMgTBzkM1kX7d8QtE2oYXuAj2ZKabmW\", \"RDE9LBKqMaKgQgnsZM3hFCNeWfoXkHWMLs\", \"RDBjpRUqV1AXzVJCBbbXNskgxGRj711qSc\"],\"timeout\":15000,\"satoshis\":\"128700\",\"spendscript\":\"76a9142b4cf64627268ac24effd9aad5895e8ca862114288ac\",\"txfee\":\"10000\",\"burn\":0.00000000}}"

12
osx_deploy.sh

@ -6,13 +6,21 @@ TMP_DIR=~/tmp/iguana
mkdir -p $TMP_DIR mkdir -p $TMP_DIR
echo "making $TMP_DIR" echo "making $TMP_DIR"
binaries=("iguana") binaries=("iguana" "marketmaker")
for binary in "${binaries[@]}"; for binary in "${binaries[@]}";
do do
echo "copying $binary to $TMP_DIR" echo "copying $binary to $TMP_DIR"
cp agents/$binary $TMP_DIR if [ "$binary" = "iguana" ]
then
cp agents/$binary $TMP_DIR
fi
if [ "$binary" = "marketmaker" ]
then
cp iguana/$binary $TMP_DIR
fi
# find the dylibs to copy for iguana # find the dylibs to copy for iguana
DYLIBS=`otool -L $TMP_DIR/$binary | grep "/usr/local" | awk -F' ' '{ print $1 }'` DYLIBS=`otool -L $TMP_DIR/$binary | grep "/usr/local" | awk -F' ' '{ print $1 }'`

Loading…
Cancel
Save