Browse Source

Merge pull request #354 from jl777/dev

Dev
beta
jl777 7 years ago
committed by GitHub
parent
commit
2f673feb61
  1. 11
      .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. 0
      iguana/exchanges/DB/.tmpmarker
  13. 0
      iguana/exchanges/DB/ECB/.tmpmarker
  14. 0
      iguana/exchanges/DB/SWAPS/.tmpmarker
  15. 0
      iguana/exchanges/DB/TRANSACTIONS/.tmpmarker
  16. 0
      iguana/exchanges/DB/purgeable/.tmpmarker
  17. 0
      iguana/exchanges/DB/purgeable/BTC/.tmpmarker
  18. 0
      iguana/exchanges/DB/purgeable/BTCD/.tmpmarker
  19. 2
      iguana/exchanges/DEXstats.h
  20. 55
      iguana/exchanges/LP_bitcoin.c
  21. 120
      iguana/exchanges/LP_coins.c
  22. 247
      iguana/exchanges/LP_commands.c
  23. 124
      iguana/exchanges/LP_forwarding.c
  24. 59
      iguana/exchanges/LP_include.h
  25. 97
      iguana/exchanges/LP_messages.c
  26. 470
      iguana/exchanges/LP_nativeDEX.c
  27. 410
      iguana/exchanges/LP_network.c
  28. 333
      iguana/exchanges/LP_ordermatch.c
  29. 94
      iguana/exchanges/LP_peers.c
  30. 577
      iguana/exchanges/LP_portfolio.c
  31. 328
      iguana/exchanges/LP_prices.c
  32. 98
      iguana/exchanges/LP_remember.c
  33. 209
      iguana/exchanges/LP_rpc.c
  34. 320
      iguana/exchanges/LP_scan.c
  35. 115
      iguana/exchanges/LP_statemachine.c
  36. 130
      iguana/exchanges/LP_swap.c
  37. 120
      iguana/exchanges/LP_transaction.c
  38. 378
      iguana/exchanges/LP_utxos.c
  39. 0
      iguana/exchanges/SVM/.tmpmarker
  40. 0
      iguana/exchanges/SVM/models/.tmpmarker
  41. 0
      iguana/exchanges/SVM/rawfeatures/.tmpmarker
  42. 2
      iguana/exchanges/autofill
  43. 9
      iguana/exchanges/autoprice
  44. 2
      iguana/exchanges/cancelorder
  45. 4
      iguana/exchanges/coins
  46. 0
      iguana/exchanges/confs/.tmpmarker
  47. 8
      iguana/exchanges/debug
  48. 2
      iguana/exchanges/deletemessages
  49. 2
      iguana/exchanges/dividends
  50. 2
      iguana/exchanges/forward
  51. 0
      iguana/exchanges/genesis/.tmpmarker
  52. 2
      iguana/exchanges/getcoin
  53. 2
      iguana/exchanges/getmessages
  54. 4
      iguana/exchanges/goal
  55. 2
      iguana/exchanges/goals
  56. 3
      iguana/exchanges/install
  57. 2
      iguana/exchanges/lookup
  58. 2
      iguana/exchanges/message
  59. 15
      iguana/exchanges/mm.c
  60. 2
      iguana/exchanges/numutxos
  61. 2
      iguana/exchanges/portfolio
  62. 2
      iguana/exchanges/pricearray
  63. 2
      iguana/exchanges/snapshot
  64. 25
      iguana/exchanges/stats.c
  65. 0
      iguana/exchanges/tmp/.tmpmarker
  66. 19
      iguana/iguana777.c
  67. 4
      iguana/iguana_msg.c
  68. 32
      iguana/iguana_ramchain.c
  69. 2
      iguana/iguana_sign.c
  70. 2
      iguana/m_LP_StaticNanoMsg
  71. 28
      iguana/m_mm_StaticNanoMsg
  72. 7
      iguana/secp256k1/m_unix_Makefile
  73. 2
      iguana/tests/rawtx2
  74. 12
      osx_deploy.sh

11
.gitignore

@ -38,6 +38,17 @@ deprecated/.DS_Store
.DS_Store
iguana/help/.tmpmarker
iguana/genesis/.tmpmarker
iguana/help.json
iguana/autoAPI.md
iguana/basilisk.o-2ad8cb38
=======
*.pbxproj
iguana/tmp/.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

@ -223,3 +223,35 @@ sudo service ntp start
Now things should be ready. To update and run notary node:
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);
return(rawtx);
}
//printf("duplicatesTX.(%s)\n",rawtx);
printf("splitfunds tx.(%s) vins.(%s)\n",rawtx,jprint(vins,0));
if ( signedtxidp != 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_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();
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,
&sha224_init,
&sha256_process,
&sha256i_process,
&sha224_done,
&sha224_test,
NULL
@ -69,7 +69,7 @@ int sha224_done(hash_state * md, unsigned char *out)
LTC_ARGCHK(md != NULL);
LTC_ARGCHK(out != NULL);
err = sha256_done(md, buf);
err = sha256i_done(md, buf);
XMEMCPY(out, buf, 28);
#ifdef LTC_CLEAN_STACK
zeromem(buf, sizeof(buf));

86
crypto777/hmac/sha256.c

@ -17,24 +17,6 @@
//#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
/* the K array */
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
@return CRYPT_OK if successful
*/
int sha256_init(hash_state * md)
int sha256i_init(hash_state * md)
{
LTC_ARGCHK(md != NULL);
@ -227,7 +209,7 @@ int sha256_init(hash_state * md)
@param inlen The length of the data (octets)
@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
@ -235,7 +217,7 @@ HASH_PROCESS(sha256_process, sha256_compress, sha256, 64)
@param out [out] The destination of the hash (32 bytes)
@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;
@ -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)
{
hash_state md;
sha256_init(&md);
sha256_process(&md,src,len);
sha256_done(&md,hash);
sha256i_init(&md);
sha256i_process(&md,src,len);
sha256i_done(&md,hash);
if ( hashstr != 0 )
{
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)
{
hash_state md;
sha256_init(&md);
sha256_process(&md,src,len);
sha256i_init(&md);
sha256i_process(&md,src,len);
if ( src2 != 0 )
sha256_process(&md,src2,len2);
sha256_done(&md,hash);
sha256i_process(&md,src2,len2);
sha256i_done(&md,hash);
}
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;
memset(&md,0,sizeof(md));
if ( src == 0 )
sha256_init(&md);
sha256i_init(&md);
else
{
md.sha256 = *state;
sha256_process(&md,src,len);
sha256i_process(&md,src,len);
}
*state = md.sha256;
sha256_done(&md,hash);
sha256i_done(&md,hash);
}
/*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;
}
decode_hex(buf,len,pubkey);
sha256_init(&md);
sha256_process(&md,buf,len);
sha256_done(&md,sha256);
sha256i_init(&md);
sha256i_process(&md,buf,len);
sha256i_done(&md,sha256);
rmd160_init(&md);
rmd160_process(&md,sha256,256 >> 3);
@ -389,9 +371,9 @@ int sha256_test(void)
char *str;
for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
sha256_init(&md);
sha256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
sha256_done(&md, tmp);
sha256i_init(&md);
sha256i_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
sha256i_done(&md, tmp);
if (XMEMCMP(tmp, tests[i].hash, 32) != 0) {
for (j=0; j<32; j++)
printf("%02x",tmp[j]);
@ -400,16 +382,16 @@ int sha256_test(void)
strcpy(str,(char*)tests[i].msg);
reverse_hexstr(str);
printf("reversed.(%s)\n",str);
sha256_init(&md);
sha256_process(&md, (unsigned char*)str, (unsigned long)strlen(str));
sha256_done(&md, tmp);
sha256i_init(&md);
sha256i_process(&md, (unsigned char*)str, (unsigned long)strlen(str));
sha256i_done(&md, tmp);
for (j=0; j<32; j++)
printf("%02x",tmp[j]);
printf(" <- sha256(%s)\n",str);
decode_hex(buf,(int)strlen(tests[i].msg),tests[i].msg);
sha256_init(&md);
sha256_process(&md, (unsigned char*)buf, (unsigned long)strlen(tests[i].msg)/2);
sha256_done(&md, tmp);
sha256i_init(&md);
sha256i_process(&md, (unsigned char*)buf, (unsigned long)strlen(tests[i].msg)/2);
sha256i_done(&md, tmp);
for (j=0; j<32; j++)
printf("%02x",tmp[j]);
printf(" <- sha256(binary %s)\n",tests[i].msg);
@ -436,6 +418,24 @@ int sha256_test(void)
#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 $ */
/* $Revision: 1.11 $ */

8
crypto777/hmac/tomcrypt_hash.h

@ -228,9 +228,9 @@ extern const struct ltc_hash_descriptor sha384_desc;
#endif
#ifdef LTC_SHA256
int sha256_init(hash_state * md);
int sha256_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int sha256_done(hash_state * md, unsigned char *hash);
int sha256i_init(hash_state * md);
int sha256i_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int sha256i_done(hash_state * md, unsigned char *hash);
int sha256_test(void);
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
#endif
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_test(void);
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);
}
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_b (*(double *)b)
if ( double_b > double_a )
return(-1);
else if ( double_b < double_a )
return(1);
return(0);
if ( double_b > double_a )
return(-1);
else if ( double_b < double_a )
return(1);
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_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)
{
qsort(buf,num,size,_increasing_double);
return(0);
qsort(buf,num,size,_increasing_double);
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)
@ -1086,30 +1105,6 @@ void rmd160ofsha256(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len)
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)
{
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
};
static inline void sha256_init(uint32_t *state)
static inline void scrypt_sha256_init(uint32_t *state)
{
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))
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 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 */
memcpy(pad, key + 16, 16);
memcpy(pad + 4, keypad, 48);
sha256_transform(tstate, pad, 0);
scrypt_sha256_transform(tstate, pad, 0);
memcpy(ihash, tstate, 32);
sha256_init(ostate);
scrypt_sha256_init(ostate);
for (i = 0; i < 8; i++)
pad[i] = ihash[i] ^ 0x5c5c5c5c;
for (; i < 16; i++)
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++)
pad[i] = ihash[i] ^ 0x36363636;
for (; i < 16; i++)
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)
{
uint32_t istate[8], ostate2[8],ibuf[16], obuf[16]; int i, j;
memcpy(istate, tstate, 32);
sha256_transform(istate, salt, 0);
scrypt_sha256_transform(istate, salt, 0);
memcpy(ibuf, salt + 16, 16);
memcpy(ibuf + 5, innerpad, 44);
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);
ibuf[4] = i + 1;
sha256_transform(obuf, ibuf, 0);
scrypt_sha256_transform(obuf, ibuf, 0);
memcpy(ostate2, ostate, 32);
sha256_transform(ostate2, obuf, 0);
scrypt_sha256_transform(ostate2, obuf, 0);
for (j = 0; j < 8; 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)
{
uint32_t buf[16]; int i;
sha256_transform(tstate, salt, 1);
sha256_transform(tstate, salt + 16, 1);
sha256_transform(tstate, finalblk, 0);
scrypt_sha256_transform(tstate, salt, 1);
scrypt_sha256_transform(tstate, salt + 16, 1);
scrypt_sha256_transform(tstate, finalblk, 0);
memcpy(buf, tstate, 32);
memcpy(buf + 8, outerpad, 32);
sha256_transform(ostate, buf, 0);
scrypt_sha256_transform(ostate, buf, 0);
for (i = 0; i < 8; 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];
memset(midstate,0,sizeof(midstate));
memset(hash,0,32);
sha256_init(midstate);
sha256_transform(midstate,(void *)data,0);
scrypt_sha256_init(midstate);
scrypt_sha256_transform(midstate,(void *)data,0);
scratchbuf = malloc(1024 * 128 + 64);
scrypt_1024_1_1_256((void *)data,hash,midstate,scratchbuf,1024);
free(scratchbuf);
}
//010000000000000000000000000000000000000000000000000000000000000000000000d9ced4ed1130f7b7faad9be25323ffafa33232a17c3edf6cfd97bee6bafbdd97b9aa8e4ef0ff0f1ecd513f7c
//010000000000000000000000000000000000000000000000000000000000000000000000d9ced4ed1130f7b7faad9be25323ffafa33232a17c3edf6cfd97bee6bafbdd97b9aa8e4ef0ff0f1ecd513f7c00
//010000000000000000000000000000000000000000000000000000000000000000000000d9ced4ed1130f7b7faad9be25323ffafa33232a17c3edf6cfd97bee6bafbdd97b9aa8e4ef0ff0f1ecd513f7c00

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
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;
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)
{
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)
@ -2083,7 +2088,7 @@ char *bitcoin_address(char *coinaddr,uint8_t taddr,uint8_t addrtype,uint8_t *pub
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;
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);
}
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));
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 )
len = 38;
hash = bits256_doublesha256(0,buf,len - 4);
*addrtypep = *buf;
memcpy(privkeyp,buf+1,32);
*addrtypep = (wiftaddr == 0) ? *buf : buf[1];
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] )
{
//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);
}
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));
data[1 + len++] = 1;
len = base58encode_checkbuf(0,addrtype,data,len);
offset = 1 + (wiftaddr != 0);
data[offset + len++] = 1;
len = base58encode_checkbuf(wiftaddr,addrtype,data,len);
if ( bitcoin_base58encode(wifstr,data,len) == 0 )
return(-1);
if ( 1 )
{
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 )
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));
}
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;
memcpy(data+1,privkey.bytes,sizeof(privkey));
len = base58encode_checkbuf(0,addrtype,data,len);
uint8_t data[128]; int32_t offset,len = 32;
offset = 1 + (wiftaddr != 0);
memcpy(data+offset,privkey.bytes,sizeof(privkey));
len = base58encode_checkbuf(wiftaddr,addrtype,data,len);
if ( bitcoin_base58encode(wifstr,data,len) == 0 )
return(-1);
if ( 1 )
{
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 )
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);
}
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;
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 )
return(clonestr("{\"error\":\"invalid wifA\"}"));
else return(0);

120
iguana/exchanges/LP_coins.c

@ -18,7 +18,7 @@
// marketmaker
//
char *portstrs[][2] = { { "BTC", "8332" }, { "KMD", "7771" } };
char *portstrs[][3] = { { "BTC", "8332" }, { "KMD", "7771" } };
uint16_t LP_rpcport(char *symbol)
{
@ -29,6 +29,15 @@ uint16_t LP_rpcport(char *symbol)
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)
{
line += strlen(field);
@ -72,8 +81,13 @@ void LP_userpassfp(char *symbol,char *username,char *password,FILE *fp)
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());
#ifdef WIN32
strcat(fname,"\\");
@ -129,11 +143,13 @@ void LP_statefname(char *fname,char *symbol,char *assetname,char *str,char *name
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;
sprintf(confname,"%s.conf",confroot);
if ( 0 )
printf("%s (%s) %s confname.(%s) confroot.(%s)\n",symbol,assetname,name,confname,confroot);
#ifdef __APPLE__
int32_t len;
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 )
confname[len - 4] = 'C';
#endif
LP_statefname(fname,symbol,assetname,confname,name);
LP_statefname(fname,symbol,assetname,confname,name,confpath);
if ( (fp= fopen(fname,"rb")) != 0 )
{
LP_userpassfp(symbol,username,password,fp);
sprintf(userpass,"%s:%s",username,password);
fclose(fp);
if ( 0 && strcmp(symbol,"HUSH") == 0 )
printf("LP_statefname.(%s) <- %s %s %s (%s)\n",fname,name,symbol,assetname,userpass);
if ( 0 )
printf("LP_statefname.(%s) <- %s %s %s (%s) (%s)\n",fname,name,symbol,assetname,userpass,confpath);
return((int32_t)strlen(userpass));
} else printf("cant open.(%s)\n",fname);
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);
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 )
jaddstr(item,"status","inactive");
else jaddstr(item,"status","active");
@ -168,21 +192,42 @@ cJSON *LP_coinjson(struct iguana_info *coin)
jaddnum(item,"pubtype",coin->pubtype);
jaddnum(item,"p2shtype",coin->p2shtype);
jaddnum(item,"wiftype",coin->wiftype);
jaddnum(item,"estimatedrate",coin->estimatedrate);
jaddnum(item,"txfee",coin->txfee);
return(item);
}
cJSON *LP_coinsjson()
cJSON *LP_coinsjson(int32_t showwif)
{
struct iguana_info *coin,*tmp; cJSON *array = cJSON_CreateArray();
HASH_ITER(hh,LP_coins,coin,tmp)
{
jaddi(array,LP_coinjson(coin));
jaddi(array,LP_coinjson(coin,showwif));
}
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 *coin;
@ -204,7 +249,7 @@ struct iguana_info *LP_coinadd(struct iguana_info *cdata)
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;
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);
coin->isPoS = isPoS;
coin->taddr = taddr;
coin->wiftaddr = wiftaddr;
coin->longestchain = longestchain;
coin->txfee = txfee;
coin->estimatedrate = estimatedrate;
coin->pubtype = pubtype;
coin->p2shtype = p2shtype;
coin->wiftype = wiftype;
coin->inactive = (uint32_t)time(NULL);
coin->bussock = LP_coinbus(busport);
if ( strcmp(symbol,"KMD") == 0 || (assetname != 0 && assetname[0] != 0) )
name2 = 0;
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)
@ -237,13 +288,15 @@ int32_t LP_isdisabled(char *base,char *rel)
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 )
return(coin);
if ( (port= LP_rpcport(symbol)) == 0 )
return(0);
if ( (busport= LP_busport(port)) == 0 )
return(0);
isPoS = 0;
txfee = 10000;
txfee = LP_MIN_TXFEE;
estimatedrate = 20;
pubtype = 60;
p2shtype = 85;
@ -251,7 +304,7 @@ struct iguana_info *LP_coinfind(char *symbol)
assetname = "";
if ( strcmp(symbol,"BTC") == 0 )
{
txfee = 50000;
txfee = 0;
estimatedrate = 300;
pubtype = 0;
p2shtype = 5;
@ -261,17 +314,16 @@ struct iguana_info *LP_coinfind(char *symbol)
else if ( strcmp(symbol,"KMD") == 0 )
name = "komodo";
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 = 0;
else if ( strcmp(symbol,"BTC") == 0 )
{
coin->inactive = (uint32_t)time(NULL); // * !IAMLP
printf("BTC inactive.%u\n",coin->inactive);
}
coin->inactive = (uint32_t)time(NULL) * !IAMLP;
printf("BTC inactive.%u\n",coin->inactive);
}
}
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 )
{
isPoS = jint(item,"isPoS");
if ( (txfee= j64bits(item,"txfee")) == 0 )
txfee = 10000;
txfee = j64bits(item,"txfee");
if ( (estimatedrate= jdouble(item,"estimatedrate")) == 0. )
estimatedrate = 20;
if ( (pubtype= juint(item,"pubtype")) == 0 )
pubtype = 60;
pubtype = juint(item,"pubtype");
if ( (p2shtype= juint(item,"p2shtype")) == 0 )
p2shtype = 85;
if ( (wiftype= juint(item,"wiftype")) == 0 )
wiftype = 188;
if ( (assetname= jstr(item,"asset")) != 0 )
{
name = assetname;
pubtype = 60;
}
else if ( (name= jstr(item,"name")) == 0 )
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->inactive = (uint32_t)time(NULL);
} 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 ( strcmp("KMD",coin->symbol) != 0 )

247
iguana/exchanges/LP_commands.c

@ -18,11 +18,24 @@
// 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;
//printf("stats_JSON(%s)\n",jprint(argjson,0));
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));
if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 )
{
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);
peer->numutxos = othernumutxos;
}
if ( peer->sessionid == 0 )
peer->sessionid = juint(argjson,"session");
//printf("peer.(%s) found (%d %d) (%d %d) (%s)\n",peer->ipaddr,peer->numpeers,peer->numutxos,otherpeers,othernumutxos,jprint(argjson,0));
} else LP_addpeer(LP_mypeer,LP_mypubsock,ipaddr,argport,pushport,subport,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 )
@ -51,42 +66,64 @@ 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);
return(0);
}
if ( strcmp(method,"hello") == 0 )
/*if ( strcmp(method,"hello") == 0 )
{
//printf("got hello from %s:%u\n",ipaddr!=0?ipaddr:"",argport);
return(0);
}
else if ( strcmp(method,"nn_tests") == 0 )
return(clonestr("{\"result\":\"success\"}"));
else*/ if ( strcmp(method,"sendmessage") == 0 && jobj(argjson,"userpass") == 0 )
{
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 )
return(clonestr("{\"result\":\" \
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\
autoprice(base, rel, price, margin, type)\n\
goal(coin=*, val=<autocalc>)\n\
myprice(base, rel)\n\
enable(coin)\n\
disable(coin)\n\
inventory(coin)\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\
autotrade(base, rel, price, relvolume, timeout=10, duration=3600)\n\
swapstatus()\n\
swapstatus(requestid, quoteid)\n\
public API:\n \
getcoins()\n\
getcoin(coin)\n\
portfolio()\n\
getpeers()\n\
getutxos()\n\
getutxos(coin, lastn)\n\
orderbook(base, rel, duration=3600)\n\
getprices(base, rel)\n\
trust(pubkey, trust)\n\
register(pubkey,pushaddr)\n\
registerall(numnodes)\n\
lookup(pubkey)\n\
forward(pubkey,method2,<argjson>)\n\
forward(pubkey,method2=publish,<argjson>)\n\
forwardhex(pubkey,hex)\n\
sendmessage(base=coin, rel="", pubkey=zero, <argjson method2>)\n\
getmessages(firsti=0, num=100)\n\
clearmessages(firsti=0, num=100)\n\
snapshot(coin, height)\n\
dividends(coin, height, <args>)\n\
\"}"));
base = jstr(argjson,"base");
rel = jstr(argjson,"rel");
if ( USERPASS[0] != 0 && strcmp(remoteaddr,"127.0.0.1") == 0 && port != 0 )
@ -96,27 +133,64 @@ forwardhex(pubkey,hex)\n\
USERPASS_COUNTER = 1;
retjson = cJSON_CreateObject();
jaddstr(retjson,"userpass",USERPASS);
jaddbits256(retjson,"mypubkey",LP_mypubkey);
jadd(retjson,"coins",LP_coinsjson());
jaddbits256(retjson,"mypubkey",LP_mypub25519);
jadd(retjson,"coins",LP_coinsjson(LP_showwif));
return(jprint(retjson,1));
}
if ( (userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,USERPASS) != 0 )
return(clonestr("{\"error\":\"authentication error\"}"));
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());
}
if ( base != 0 && rel != 0 )
{
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\"}"));
price = jdouble(argjson,"price");
if ( strcmp(method,"setprice") == 0 )
{
if ( price > SMALLVAL )
{
if ( LP_mypriceset(base,rel,price) < 0 )
if ( LP_mypriceset(&changed,base,rel,price) < 0 )
return(clonestr("{\"error\":\"couldnt set price\"}"));
else return(LP_pricepings(ctx,myipaddr,LP_mypubsock,profitmargin,base,rel,price * LP_profitratio));
//else 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 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 )
{
if ( LP_myprice(&bid,&ask,base,rel) > SMALLVAL )
@ -132,7 +206,7 @@ forwardhex(pubkey,hex)\n\
else if ( strcmp(method,"ordermatch") == 0 )
{
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 if ( strcmp(method,"trade") == 0 )
@ -141,16 +215,14 @@ forwardhex(pubkey,hex)\n\
if ( price > SMALLVAL || jobj(argjson,"quote") != 0 )
{
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 if ( strcmp(method,"autotrade") == 0 )
{
if ( price > SMALLVAL )
{
printf("price set (%s/%s) <- %.8f\n",rel,base,1./price);
LP_mypriceset(rel,base,1./price);
return(LP_autotrade(ctx,myipaddr,pubsock,profitmargin,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration")));
return(LP_autotrade(ctx,myipaddr,pubsock,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration")));
} else return(clonestr("{\"error\":\"no price set\"}"));
}
}
@ -167,24 +239,37 @@ forwardhex(pubkey,hex)\n\
{
if ( (ptr= LP_coinsearch(coin)) != 0 )
ptr->inactive = 0;
return(jprint(LP_coinsjson(),1));
return(jprint(LP_coinsjson(0),1));
}
else if ( strcmp(method,"disable") == 0 )
{
if ( (ptr= LP_coinsearch(coin)) != 0 )
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\"}"));
}
if ( LP_isdisabled(coin,0) != 0 )
return(clonestr("{\"error\":\"coin is disabled\"}"));
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 )
{
privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,ptr,"",USERPASS_WIFSTR);
//privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,ptr,"",USERPASS_WIFSTR);
//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();
jaddstr(retjson,"result","success");
jaddstr(retjson,"coin",coin);
@ -194,7 +279,13 @@ forwardhex(pubkey,hex)\n\
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 )
{
uint32_t requestid,quoteid;
@ -207,9 +298,22 @@ forwardhex(pubkey,hex)\n\
else if ( strcmp(method,"trust") == 0 )
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\"}"));
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\"}");
else if ( strcmp(method,"reserved") == 0 )
retstr = LP_quotereceived(argjson);
@ -218,59 +322,63 @@ forwardhex(pubkey,hex)\n\
else if ( strcmp(method,"checktxid") == 0 )
retstr = LP_spentcheck(argjson);
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 )
retstr = LP_postedprice(argjson);
else if ( strcmp(method,"broadcast") == 0 )
retstr = LP_broadcasted(argjson);
else if ( strcmp(method,"encrypted") == 0 )
retstr = clonestr("{\"result\":\"success\"}");
else if ( strcmp(method,"getprices") == 0 )
return(LP_prices());
else if ( strcmp(method,"orderbook") == 0 )
return(LP_orderbook(base,rel,jint(argjson,"duration")));
else if ( strcmp(method,"registerall") == 0 )
return(LP_registerall(jint(argjson,"numnodes")));
return(clonestr("{\"error\":\"you are running an obsolete version, update\"}"));
else if ( strcmp(method,"forward") == 0 )
{
cJSON *reqjson;
if ( (reqjson= LP_dereference(argjson,"forward")) != 0 )
{
//printf("FORWARDED.(%s)\n",jprint(argjson,0));
if ( LP_forward(ctx,myipaddr,pubsock,profitmargin,jbits256(argjson,"pubkey"),jprint(reqjson,1),1) > 0 )
retstr = clonestr("{\"result\":\"success\"}");
else retstr = clonestr("{\"result\":\"error forwarding\"}");
} else retstr = clonestr("{\"result\":\"cant recurse forwards\"}");
}
return(clonestr("{\"error\":\"you are running an obsolete version, update\"}"));
else if ( strcmp(method,"keepalive") == 0 )
{
printf("got keepalive lag.%d switch.%u\n",(int32_t)time(NULL) - LP_deadman_switch,LP_deadman_switch);
LP_deadman_switch = (uint32_t)time(NULL);
return(clonestr("{\"result\":\"success\"}"));
}
return(clonestr("{\"error\":\"you are running an obsolete version, update\"}"));
else if ( strcmp(method,"getpeers") == 0 )
return(LP_peers());
else if ( strcmp(method,"getutxos") == 0 )
return(LP_utxos(1,LP_mypeer,jstr(argjson,"coin"),jint(argjson,"lastn")));
else if ( strcmp(method,"notified") == 0 )
else if ( strcmp(method,"utxo") == 0 )
{
if ( LP_utxoaddjson(1,LP_mypubsock,argjson) != 0 )
return(clonestr("{\"result\":\"success\",\"notifyutxo\":\"received\"}"));
else return(clonestr("{\"result\":\"couldnt add utxo\"}"));
retstr = clonestr("{\"result\":\"success\",\"utxo\":\"received\"}");
else retstr = clonestr("{\"result\":\"couldnt add utxo\"}");
}
else
{
if ( IAMLP != 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"));
//printf("got (%s) from register\n",retstr!=0?retstr:"");
return(retstr);
bits256 zero; char *cipherstr; int32_t cipherlen; uint8_t cipher[LP_ENCRYPTED_MAXSIZE];
if ( (reqjson= LP_dereference(argjson,"broadcast")) != 0 )
{
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 )
{
if ( myipaddr == 0 || myipaddr[0] == 0 || strcmp(myipaddr,"127.0.0.1") == 0 )
@ -279,25 +387,30 @@ forwardhex(pubkey,hex)\n\
myipaddr = LP_mypeer->ipaddr;
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 )
retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}");
}
else
{
if ( strcmp(method,"register") == 0 )
if ( strcmp(method,"psock") == 0 )
{
printf("nonLP got (%s)\n",jprint(argjson,0));
retstr = clonestr("{\"result\":\"success\",\"register\":\"received\"}");
//printf("nonLP got (%s)\n",jprint(argjson,0));
retstr = clonestr("{\"result\":\"success\"}");
}
}
}
if ( retstr == 0 )
printf("ERROR.(%s)\n",jprint(argjson,0));
if ( reqjson != 0 )
free_json(reqjson);
if ( retstr != 0 )
{
free(retstr);
return(0);
}
printf("ERROR.(%s)\n",jprint(argjson,0));
return(0);
}

124
iguana/exchanges/LP_forwarding.c

@ -18,6 +18,19 @@
// 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
{
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 ( 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++;
}
//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);
return(n);
@ -218,18 +220,6 @@ char *LP_registerall(int32_t numnodes)
return(jprint(retjson,1));
}
cJSON *LP_dereference(cJSON *argjson,char *excludemethod)
{
cJSON *reqjson = 0;
if ( jstr(argjson,"method2") != 0 && strncmp(excludemethod,jstr(argjson,"method2"),strlen(excludemethod)) != 0 )
{
reqjson = jduplicate(argjson);
jdelete(reqjson,"method");
jaddstr(reqjson,"method",jstr(argjson,"method2"));
}
return(reqjson);
}
char *LP_forwardhex(void *ctx,int32_t pubsock,bits256 pubkey,char *hexstr)
{
struct LP_forwardinfo *ptr=0; uint8_t *data; int32_t datalen=0,sentbytes=0; char *msg,*retstr=0; cJSON *retjson=0,*argjson=0,*reqjson=0;
@ -245,7 +235,7 @@ char *LP_forwardhex(void *ctx,int32_t pubsock,bits256 pubkey,char *hexstr)
if ( reqjson != 0 )
{
retstr = LP_command_process(ctx,LP_mypeer != 0 ? LP_mypeer->ipaddr : "127.0.0.1",LP_mypubsock,reqjson,0,0,LP_profitratio - 1.);
printf("LP_forwardhex.(%s) -> (%s)\n",jprint(reqjson,0),retstr!=0?retstr:"");
//printf("LP_forwardhex.(%s) -> (%s)\n",jprint(reqjson,0),retstr!=0?retstr:"");
if ( pubsock >= 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 )
{
if ( ptr->pushsock >= 0 )//&& ptr->hello != 0 )
if ( ptr->pushsock >= 0 )
{
printf("%s forwardhex.(%s)\n",ptr->pushaddr,(char *)data);
sentbytes = LP_send(ptr->pushsock,(char *)data,datalen,0);
}
retjson = cJSON_CreateObject();
if ( sentbytes == datalen )
if ( sentbytes >= 0 )
{
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);
}
else
@ -294,11 +288,12 @@ char *LP_forwardhex(void *ctx,int32_t pubsock,bits256 pubkey,char *hexstr)
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 )
return(-1);
len = (int32_t)strlen(jsonstr) + 1;
if ( bits256_nonz(pubkey) != 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);
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_json(argjson);
}
if ( freeflag != 0 )
free(jsonstr);
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);
len = (int32_t)strlen(jsonstr);
if ( LP_send(ptr->pushsock,jsonstr,(int32_t)strlen(jsonstr)+1,0) == len+1 )
if ( LP_send(ptr->pushsock,jsonstr,len,freeflag) == len )
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)
{
if ( bits256_nonz(pubkey) != 0 )
{
if ( (retstr= issue_LP_lookup(peer->ipaddr,peer->port,pubkey)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( jint(retjson,"forwarding") != 0 && peer->pushsock >= 0 )
retval = 0;
free_json(retjson);
}
free(retstr);
}
} else retval = 0;
if ( retval >= 0 && peer->pushsock >= 0 )
{
printf("found LPnode.(%s) forward.(%s)\n",peer->ipaddr,jsonstr);
len = (int32_t)strlen(jsonstr) + 1;
hexstr = malloc(len*2 + 1);
init_hexbytes_noT(hexstr,(uint8_t *)jsonstr,len);
if ( freeflag != 0 )
free(jsonstr);
reqjson = cJSON_CreateObject();
jaddstr(reqjson,"method","forwardhex");
jaddstr(reqjson,"hex",hexstr);
jaddbits256(reqjson,"pubkey",pubkey);
free(hexstr);
msg = jprint(reqjson,1);
return(LP_send(peer->pushsock,msg,(int32_t)strlen(msg)+1,1));
} else retval = -1;
//printf("found LPnode.(%s) forward.(%s)\n",peer->ipaddr,msg);
if ( LP_send(peer->pushsock,msg,mlen,0) == mlen )
n++;
if ( n >= 8 )//sizeof(default_LPnodes)/sizeof(*default_LPnodes) )
break;
}
if ( freeflag != 0 )
free(jsonstr);
return(-1);
if ( msg != 0 )
free(msg);
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));
return(clonestr("{\"result\":\"need to update broadcast messages\"}"));
}
*/

59
iguana/exchanges/LP_include.h

@ -21,12 +21,16 @@
#ifndef LP_INCLUDE_H
#define LP_INCLUDE_H
//#define LP_STRICTPEERS
#define LP_COMMAND_SENDSOCK NN_PUSH
#define LP_COMMAND_RECVSOCK NN_PULL
#define LP_ENCRYPTED_MAXSIZE (4096 + 2 + crypto_box_NONCEBYTES + crypto_box_ZEROBYTES)
#define LP_MAXPUBKEY_ERRORS 3
#define PSOCK_KEEPALIVE 3600
#define MAINLOOP_PERSEC 10
#define MAINLOOP_PERSEC 100
#define MAX_PSOCK_PORT 60000
#define MIN_PSOCK_PORT 10000
#define LP_MEMPOOL_TIMEINCR 10
@ -38,11 +42,13 @@
#define LP_MINPEER_GOOD 20
#define LP_PEERGOOD_ERRORDECAY 0.9
#define LP_SWAPSTEP_TIMEOUT 3
#define LP_AUTOTRADE_TIMEOUT 10
#define LP_SWAPSTEP_TIMEOUT 30
#define LP_AUTOTRADE_TIMEOUT 60
#define LP_MIN_TXFEE 10000
#define LP_MINVOL 10
#define LP_MINCLIENTVOL 20
#define LP_MINSIZE_TXFEEMULT 10
#define LP_REQUIRED_TXFEE 0.95
#define LP_DEXFEE(destsatoshis) ((destsatoshis) / INSTANTDEX_INSURANCEDIV)
#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_RESERVETIME 60
#define LP_AVETXSIZE 200
#define LP_AVETXSIZE 256
#define LP_CACHEDURATION 60
#define BASILISK_DEFAULT_NUMCONFIRMS 1
#define DEX_SLEEP 3
@ -145,7 +151,7 @@ struct basilisk_swapinfo
bits256 myhash,otherhash,orderhash;
uint32_t statebits,otherstatebits,started,expiration,finished,dead,reftime,putduration,callduration;
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;
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;
};
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
{
@ -169,25 +175,37 @@ struct LP_transaction
struct LP_outpoint outpoints[];
};
struct LP_address
{
UT_hash_handle hh;
int64_t balance;
char coinaddr[40];
};
struct iguana_info
{
UT_hash_handle hh;
portable_mutex_t txmutex; struct LP_transaction *transactions;
uint64_t txfee; double estimatedrate,profitmargin;
int32_t longestchain,firstrefht,firstscanht,lastscanht; uint32_t counter,inactive,lastmempool,lastgetinfo;
uint8_t pubtype,p2shtype,isPoS,wiftype,taddr;
portable_mutex_t txmutex; struct LP_transaction *transactions; struct LP_address *addresses;
uint64_t txfee;
int32_t longestchain,firstrefht,firstscanht,lastscanht,bussock; uint16_t busport;
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];
// 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_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_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
{
@ -207,8 +225,7 @@ struct LP_peerinfo
{
UT_hash_handle hh;
uint64_t ip_port;
double profitmargin;
uint32_t ipbits,errortime,errors,numpeers,numutxos,lasttime,connected,lastutxos,lastpeers,diduquery,good;
uint32_t ipbits,errortime,errors,numpeers,numutxos,lasttime,connected,lastutxos,lastpeers,diduquery,good,sessionid;
int32_t pushsock,subsock;
uint16_t port;
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);
int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys);
void LP_quotesinit(char *base,char *rel);
int32_t LP_forward(void *ctx,char *myipaddr,int32_t pubsock,double profitmargin,bits256 pubkey,char *jsonstr,int32_t freeflag);
int32_t LP_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_isavailable(struct LP_utxoinfo *utxo);
struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port);
char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin);
char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen);
void LP_availableset(struct LP_utxoinfo *utxo);
int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2,bits256 pubkey);
int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsock,int32_t pullsock,double profitmargin);
int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2);
int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsock,int32_t pullsock);
uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired);
void LP_utxo_clientpublish(struct LP_utxoinfo *utxo);
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

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

470
iguana/exchanges/LP_nativeDEX.c

@ -13,25 +13,32 @@
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
//
// LP_nativeDEX.c
// marketmaker
//
// activate orderbook timeouts
// verify bid volumes
// new features:
// bittrex balancing
// detect port conflicts on enable
// 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 "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;
#include "LP_network.c"
struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2];
struct LP_peerinfo *LP_peerinfos,*LP_mypeer;
struct LP_forwardinfo *LP_forwardinfos;
struct iguana_info *LP_coins;
#include "LP_network.c"
char *activecoins[] = { "BTC", "KMD" };
char GLOBAL_DBDIR[] = { "DB" };
@ -40,12 +47,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" }; //
uint32_t LP_deadman_switch;
//uint32_t LP_deadman_switch;
uint16_t LP_fixed_pairport,LP_publicport;
int32_t LP_mybussock = -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.;
bits256 LP_mypubkey;
bits256 LP_mypub25519,LP_mypriv25519;
// stubs
@ -82,122 +92,134 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_
#include "LP_utxos.c"
#include "LP_forwarding.c"
#include "LP_ordermatch.c"
#include "LP_portfolio.c"
#include "LP_messages.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;
if ( jobj(argjson,"result") != 0 || jobj(argjson,"error") != 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);
if ( pubsock >= 0 ) //strncmp("{\"error\":",retstr,strlen("{\"error\":")) != 0 &&
LP_send(pubsock,retstr,(int32_t)strlen(retstr)+1,0);
//if ( pubsock >= 0 ) //strncmp("{\"error\":",retstr,strlen("{\"error\":")) != 0 &&
//LP_send(pubsock,retstr,(int32_t)strlen(retstr)+1,0);
}
}
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;
if ( (datalen= is_hexstr((char *)ptr,0)) > 0 )
uint8_t decoded[LP_ENCRYPTED_MAXSIZE + crypto_box_ZEROBYTES],*nonce,*cipher; int32_t recvlen,cipherlen; char *jsonstr = 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;
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 )
if ( (jsonstr= (char *)_SuperNET_decipher(nonce,cipher,decoded,cipherlen,GENESIS_PUBKEY,LP_mypriv25519)) != 0 )
{
//printf("got forwardhex\n");
if ( (retstr= LP_forwardhex(ctx,pubsock,jbits256(argjson,"pubkey"),jstr(argjson,"hex"))) != 0 )
recvlen = (cipherlen - crypto_box_ZEROBYTES);
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");
if ( jobj(argjson,"method2") != 0 )
jdelete(argjson,"method2");
jaddstr(argjson,"method2","broadcast");
if ( pubsock >= 0 && (reqjson= LP_dereference(argjson,"publish")) != 0 )
{
msg = jprint(reqjson,1);
LP_send(pubsock,msg,(int32_t)strlen(msg)+1,1);
}
}
else if ( (retstr= LP_command_process(ctx,myipaddr,pubsock,argjson,&((uint8_t *)ptr)[len],recvlen - len,profitmargin)) != 0 )
datalen >>= 1;
jsonstr = malloc(datalen + 1);
decode_hex((void *)jsonstr,datalen,(char *)ptr);
jsonstr[datalen] = 0;
} else jsonstr = (char *)ptr;
if ( jsonstr != 0 && (argjson= cJSON_Parse(jsonstr)) != 0 )
{
}
portable_mutex_unlock(&LP_commandmutex);
if ( LP_COMMAND_RECVSOCK == NN_REP )
{
if ( retstr != 0 )
uint8_t decoded[LP_ENCRYPTED_MAXSIZE + crypto_box_ZEROBYTES];
//printf("[%s]\n",jsonstr);
cipherlen = 0;
if ( (cipherstr= jstr(argjson,"cipher")) != 0 && (cipherlen= is_hexstr(cipherstr,0)) > 32 && cipherlen <= sizeof(decoded)*2 )
{
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);
LP_send(recvsock,retstr,(int32_t)strlen(retstr)+1,0);
}
cipherlen >>= 1;
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));
LP_send(recvsock,"{\"result\":null}",(int32_t)strlen("{\"result\":null}")+1,0);
len = (int32_t)strlen(jsonstr) + 1;
if ( (retstr= LP_command_process(ctx,myipaddr,pubsock,argjson,&((uint8_t *)ptr)[len],recvlen - len)) != 0 )
{
}
free_json(argjson);
}
}
free_json(argjson);
} else printf("error parsing(%s)\n",jsonstr);
if ( (void *)jsonstr != ptr )
} //else printf("DUPLICATE.(%s)\n",(char *)ptr);
portable_mutex_unlock(&LP_commandmutex);
if ( jsonstr != 0 && (void *)jsonstr != (void *)ptr && encrypted == 0 )
free(jsonstr);
if ( ptr != 0 )
nn_freemsg(ptr), ptr = 0;
return(retstr);
}
int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsock,int32_t pullsock,double profitmargin)
{
void *ptr; int32_t recvlen=-1,nonz = 0;
*retstrp = 0;
if ( pullsock >= 0 )
{
while ( (recvlen= nn_recv(pullsock,&ptr,NN_MSG,0)) > 0 )
{
nonz++;
*retstrp = LP_process_message(ctx,"PULL",myipaddr,pubsock,profitmargin,ptr,recvlen,pullsock);
}
}
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)
void LP_utxo_spentcheck(int32_t pubsock,struct LP_utxoinfo *utxo)
{
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);
if ( utxo->T.spentflag == 0 && now > utxo->T.lastspentcheck+60 )
{
@ -216,13 +238,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_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;
if ( peer->lastutxos < now-interval )
@ -234,16 +256,75 @@ int32_t LP_peer_utxosquery(struct LP_peerinfo *mypeer,uint16_t myport,int32_t pu
{
peer->lastutxos = now;
//printf("query utxos from %s\n",peer->ipaddr);
n = LP_utxosquery(mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,profitmargin);
n = LP_utxosquery(mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,maxentries);
}
} //else printf("LP_peer_utxosquery skip.(%s) %u\n",peer->ipaddr,peer->lastutxos);
return(n);
}
int32_t LP_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;
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;
static uint32_t counter,numpeers,lastresync; //lastforward
struct LP_utxoinfo *utxo,*utmp; cJSON *retjson; struct iguana_info *coin,*ctmp; char *retstr,*origipaddr; struct LP_peerinfo *peer,*tmp,*mostpeer; uint32_t id,now; int32_t mostutxos,nonz = 0,n=0,num,lastn=-1;
now = (uint32_t)time(NULL);
if ( (origipaddr= myipaddr) == 0 )
origipaddr = "127.0.0.1";
@ -251,90 +332,88 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
myipaddr = "127.0.0.1";
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d peers\n",counter,LP_canbind);
numpeers = LP_numpeers();
mostutxos = 0;
mostpeer = 0;
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
if ( peer->errors >= LP_MAXPEER_ERRORS )
{
if ( (rand() % 10000) == 0 )
{
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 ( IAMLP != 0 )
printf("numpeers.%d updatepeer.%s lag.%d\n",numpeers,peer->ipaddr,now-peer->lastpeers);
//if ( IAMLP != 0 )
// printf("numpeers.%d updatepeer.%s lag.%d\n",numpeers,peer->ipaddr,now-peer->lastpeers);
peer->lastpeers = now;
if ( IAMLP != 0 && peer->numpeers != numpeers )
printf("%s num.%d vs %d\n",peer->ipaddr,peer->numpeers,numpeers);
//if ( IAMLP != 0 && peer->numpeers != numpeers )
// printf("%s num.%d vs %d\n",peer->ipaddr,peer->numpeers,numpeers);
if ( strcmp(peer->ipaddr,myipaddr) != 0 )
LP_peersquery(mypeer,pubsock,peer->ipaddr,peer->port,myipaddr,myport,profitmargin);
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 ( lastn != n || n < 20 )
{
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);
peer->diduquery = now;
}
nonz += LP_subsock_check(ctx,origipaddr,pubsock,peer->subsock,profitmargin);
}
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d forwarding\n",counter,LP_canbind);
if ( (counter % 600) == 20 )
{
LP_myutxo_updates(ctx,pubsock,passphrase,profitmargin);
if ( lastforward < now-3600 )
if ( peer->numutxos > mostutxos )
{
if ( (retstr= LP_registerall(0)) != 0 )
free(retstr);
LP_forwarding_register(LP_mypubkey,pushaddr,pushport,10);
lastforward = now;
mostutxos = peer->numutxos;
mostpeer = peer;
}
}
//if ( LP_canbind == 0 ) printf("counter.%d canbind.%d utxos\n",counter,LP_canbind);
if ( (counter % 600) == 60 )
//printf("numutxos vs mine.%d\n",LP_mypeer != 0 ? LP_mypeer->numutxos : -1);
if ( LP_mypeer != 0 && LP_mypeer->numutxos < mostutxos && mostpeer != 0 && time(NULL) > lastresync+180 )
{
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)
{
LP_utxo_spentcheck(pubsock,utxo,profitmargin);
LP_utxo_spentcheck(pubsock,utxo);
}
HASH_ITER(hh,LP_utxoinfos[1],utxo,utmp)
{
//char str[65];
LP_utxo_spentcheck(pubsock,utxo,profitmargin);
if ( utxo->T.lasttime == 0 )
LP_utxo_spentcheck(pubsock,utxo);
if ( LP_isunspent(utxo) > 0 && utxo->T.lasttime == 0 && LP_ismine(utxo) > 0 )
{
char str[65]; printf("publish mybob %s\n",bits256_str(str,utxo->payment.txid));
LP_utxo_clientpublish(utxo);
//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
@ -367,9 +446,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);
coin->lastscanht = coin->firstscanht = coin->firstrefht;
}
if ( coin->lastscanht == coin->longestchain )
if ( coin->lastscanht == coin->longestchain+1 )
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);
LP_undospends(coin,coin->longestchain-1);
@ -379,7 +458,7 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
coin->lastscanht = coin->firstscanht;
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 )
{
printf("blockinit.%s %d error\n",coin->symbol,coin->lastscanht);
@ -388,6 +467,14 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int
coin->lastscanht++;
break;
}
if ( (counter % 6000) == 60 )
{
if ( (retstr= basilisk_swapentry(0,0)) != 0 )
{
//printf("SWAPS.(%s)\n",retstr);
free(retstr);
}
}
counter++;
return(nonz);
}
@ -415,12 +502,12 @@ void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins,char *passphrase)
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;
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 )
{
printf("couldnt get myipaddr or null mypeer.%p\n",mypeer);
@ -430,11 +517,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++)
{
if ( (rand() % 100) > 25 )
continue;
LP_peersquery(mypeer,pubsock,default_LPnodes[i],myport,mypeer->ipaddr,myport,profitmargin);
//if ( (rand() % 100) > 25 )
// continue;
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
{
@ -449,15 +536,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++)
{
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 )
{
printf("jeezy says we cant use the nullstring as passphrase and I agree\n");
@ -471,7 +559,6 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profit
exit(-1);
}
#endif
LP_profitratio += profitmargin;
OS_randombytes((void *)&n,sizeof(n));
if ( jobj(argjson,"gui") != 0 )
safecopy(LP_gui,jstr(argjson,"gui"),sizeof(LP_gui));
@ -511,11 +598,10 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profit
portable_mutex_init(&LP_psockmutex);
portable_mutex_init(&LP_coinmutex);
portable_mutex_init(&LP_pubkeymutex);
if ( profitmargin == 0. || profitmargin == 0.01 )
{
profitmargin = 0.01 + (double)(rand() % 100)/100000;
printf("default profit margin %f\n",profitmargin);
}
portable_mutex_init(&LP_messagemutex);
portable_mutex_init(&LP_portfoliomutex);
LP_sessionid = (uint32_t)time(NULL);
printf("getting myipaddr sessionid.%u\n",LP_sessionid);
if ( system("curl -s4 checkip.amazonaws.com > /tmp/myipaddr") == 0 )
{
if ( (myipaddr= OS_filestr(&filesize,"/tmp/myipaddr")) != 0 && myipaddr[0] != 0 )
@ -548,12 +634,16 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profit
printf(">>>>>>>>> myipaddr.%s (%s) pullsock.%d\n",myipaddr,subaddr,pubsock);
LP_mypubsock = pubsock;
}
LP_initpeers(pubsock,mypeer,myipaddr,myport,jstr(argjson,"seednode"),profitmargin);
pullsock = LP_initpublicaddr(ctx,&mypullport,pushaddr,myipaddr,mypullport,0);
printf("got %s, initpeers\n",myipaddr);
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);
LP_publicport = mypullport;
LP_deadman_switch = (uint32_t)time(NULL);
printf("canbind.%d my command address is (%s) pullsock.%d pullport.%u\n",LP_canbind,pushaddr,pullsock,mypullport);
LP_mybussock = LP_coinbus(mybusport);
//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);
if ( IAMLP != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_psockloop,(void *)&myipaddr) != 0 )
{
@ -565,28 +655,28 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profit
printf("error launching stats rpcloop for port.%u\n",myport);
exit(-1);
}
if ( (retstr= basilisk_swapentry(0,0)) != 0 )
free(retstr);
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)command_rpcloop,(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 *)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 )
{
//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);
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)
{
sprintf(str,"tcp://%s:%u",bindflag == 0 ? ipaddr : "*",port);
sprintf(str,"tcp://%s:%u",bindflag == 0 ? ipaddr : "*",port); // ws is worse
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 )
{
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);
return(-1);
}
//len = (int32_t)strlen(msg) + 1;
for (i=0; i<1000; i++) // 1000 * (1 ms + 1000 us) = 2 seconds
if ( (sentbytes= nn_send(sock,msg,sendlen,0)) != sendlen )
printf("LP_send sent %d instead of %d\n",sentbytes,sendlen);
//else printf("SENT.(%s)\n",msg);
if ( freeflag != 0 )
free(msg);
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;
pfd.events = NN_POLLOUT;
//portable_mutex_lock(&LP_networkmutex);
if ( nn_poll(&pfd,1,1) > 0 )
total++;
for (i=0; i<sizeof(crcs)/sizeof(*crcs); i++)
{
if ( (sentbytes= nn_send(sock,msg,sendlen,0)) != sendlen )
printf("LP_send sent %d instead of %d\n",sentbytes,sendlen);
//else printf("SENT.(%s)\n",msg);
if ( freeflag != 0 )
free(msg);
//portable_mutex_unlock(&LP_networkmutex);
return(sentbytes);
if ( crc32 == crcs[i] )
{
if ( i > 0 )
{
crcs[i] = crcs[i >> 1];
crcs[i >> 1] = crc32;
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);
}
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])
{
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);
}
void LP_psockloop(void *_ptr)
void LP_psockloop(void *_ptr) // printouts seem to be needed for forwarding to work
{
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 )
{
now = (uint32_t)time(NULL);
@ -105,15 +367,8 @@ void LP_psockloop(void *_ptr)
{
if ( size > 0 )
{
if ( (sentbytes= LP_send(sendsock,buf,size,0)) > 0 )
{
//printf("PSOCKS (%d %d %d) (%s) -> %d/%d bytes %s\n",ptr->publicsock,ptr->sendsock,sendsock,(char *)buf,size,sentbytes,ptr->sendaddr);
}
else
{
ptr->errors++;
printf("send error.%d to %s\n",ptr->errors,ptr->sendaddr);
}
if ( (sentbytes= nn_send(sendsock,buf,size,0)) != size ) // need tight loop
printf("LP_psockloop sent %d instead of %d\n",sentbytes,size);
if ( buf != 0 )
{
if ( buf != keepalive )
@ -150,7 +405,7 @@ void LP_psockloop(void *_ptr)
}
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 )
{
ptr->lasttime = now;
@ -201,7 +456,7 @@ void LP_psockloop(void *_ptr)
if ( retval != 0 )
printf("nn_poll retval.%d\n",retval);
break;
} // else printf("num pfds.%d retval.%d\n",n,retval);
} else printf("num pfds.%d retval.%d\n",n,retval);
}
}
//free(pfds);
@ -232,11 +487,14 @@ void LP_psockloop(void *_ptr)
else if ( now > ptr->lastping+PSOCK_KEEPALIVE/2 && ptr->errors < 3 )
{
ptr->lastping = now;
sendsock = ptr->sendsock;
sprintf(keepalive,"{\"method\":\"keepalive\",\"endpoint\":\"%s\"}",ptr->sendaddr);
size = (int32_t)strlen(keepalive) + 1;
buf = keepalive;
printf("send keepalive.(%s)\n",keepalive);
if ( 0 )
{
sendsock = ptr->sendsock;
sprintf(keepalive,"{\"method\":\"keepalive\",\"endpoint\":\"%s\"}",ptr->sendaddr);
size = (int32_t)strlen(keepalive) + 1;
buf = keepalive;
printf("send keepalive.(%s)\n",keepalive);
}
break;
}
}
@ -287,7 +545,7 @@ int32_t LP_psockmark(char *publicaddr)
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();
publicport = Psockport++;
subport = Psockport++;
@ -306,12 +564,11 @@ char *LP_psock(char *myipaddr,int32_t ispaired)
{
timeout = 1;
nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
timeout = 1;
nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout));
if ( ispaired != 0 )
{
maxsize = 1024 * 1024;
nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVBUF,&maxsize,sizeof(maxsize));
//maxsize = 1024 * 1024;
//nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVBUF,&maxsize,sizeof(maxsize));
}
//if ( ispaired != 0 )
{
@ -354,36 +611,42 @@ char *LP_psock(char *myipaddr,int32_t ispaired)
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;
printf("nn_tests.(%s)\n",pushaddr);
if ( (sock= nn_socket(AF_SP,nnother)) >= 0 )
uint16_t publicport = 0; char *retstr,*addr; cJSON *retjson; struct LP_peerinfo *peer,*tmp;
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
if ( nn_connect(sock,pushaddr) < 0 )
printf("connect error %s\n",nn_strerror(nn_errno()));
else
connectaddr[0] = publicaddr[0] = 0;
if ( peer->errors < LP_MAXPEER_ERRORS && (retstr= issue_LP_psock(peer->ipaddr,peer->port,ispaired)) != 0 )
{
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 )
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
free(retstr);
retval = 0;
printf("from %s:%u (%s)\n",peer->ipaddr,peer->port,retstr);
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);
}
}
nn_close(sock);
printf("got.(%s) connect.%s public.%s\n",retstr,connectaddr,publicaddr);
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)
@ -404,6 +667,11 @@ int32_t LP_initpublicaddr(void *ctx,uint16_t *mypullportp,char *publicaddr,char
else
{
*mypullportp = 0;
if ( ispaired == 0 )
{
strcpy(publicaddr,"127.0.0.1");
return(-1);
}
while ( *mypullportp == 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;
nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout));
timeout = 1;
nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
//maxsize = 2 * 1024 * 1024;
//nn_setsockopt(pullsock,NN_SOL_SOCKET,NN_RCVBUF,&maxsize,sizeof(maxsize));
if ( nntype == NN_SUB )
nn_setsockopt(pullsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0);
}
if ( LP_canbind != 0 || ispaired != 0 || nn_tests(ctx,pullsock,publicaddr,NN_PUSH) >= 0 )
break;
printf("nn_tests failed, try again\n");
sleep(3);
//if ( LP_canbind != 0 || ispaired != 0 || nn_tests(ctx,pullsock,publicaddr,NN_PUSH) >= 0 )
// break;
//printf("nn_tests failed, try again\n");
//sleep(3);
break;
if ( pullsock >= 0 )
nn_close(pullsock);
}

333
iguana/exchanges/LP_ordermatch.c

@ -19,6 +19,43 @@
// 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)
{
@ -120,15 +157,15 @@ int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson)
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));
if ( qp->timestamp == 0 )
qp->timestamp = (uint32_t)time(NULL);
safecopy(qp->destcoin,destcoin,sizeof(qp->destcoin));
if ( (qp->txfee= LP_getestimatedrate(utxo->coin)*LP_AVETXSIZE) < LP_MIN_TXFEE )
qp->txfee = LP_MIN_TXFEE;
qp->satoshis = destsatoshis / price + 0.49;
LP_txfees(&qp->txfee,&qp->desttxfee,utxo->coin,qp->destcoin);
qp->satoshis = satoshis;//(destsatoshis / price) + 0.49;
qp->destsatoshis = destsatoshis;
if ( utxo->iambob == 0 || qp->txfee >= qp->satoshis || qp->txfee >= utxo->deposit.value || utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis) )
{
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->txid2 = utxo->deposit.txid;
qp->vout2 = utxo->deposit.vout;
qp->destsatoshis = destsatoshis;
if ( (qp->desttxfee= LP_getestimatedrate(qp->destcoin) * LP_AVETXSIZE) < LP_MIN_TXFEE )
qp->desttxfee = LP_MIN_TXFEE;
if ( qp->desttxfee >= qp->destsatoshis )
{
printf("quoteinit desttxfee %.8f < %.8f destsatoshis\n",dstr(qp->desttxfee),dstr(qp->destsatoshis));
@ -167,7 +201,7 @@ char *LP_quotereceived(cJSON *argjson)
{
struct LP_cacheinfo *ptr; double price; struct LP_quoteinfo Q;
LP_quoteparse(&Q,argjson);
price = (double)(Q.destsatoshis + Q.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 )
{
ptr->Q = Q;
@ -176,27 +210,17 @@ char *LP_quotereceived(cJSON *argjson)
} 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();
jaddbits256(reqjson,"pubkey",LP_mypubkey);
memset(zero.bytes,0,sizeof(zero));
jaddbits256(reqjson,"pubkey",LP_mypub25519);
jaddstr(reqjson,"base",base);
jaddstr(reqjson,"rel",rel);
jaddnum(reqjson,"price",price);
if ( pubsock >= 0 )
{
jaddstr(reqjson,"method","postprice");
//printf("%d pricepings.(%s)\n",pubsock,jprint(reqjson,0));
msg = jprint(reqjson,1);
LP_send(pubsock,msg,(int32_t)strlen(msg)+1,1);
}
else
{
jaddstr(reqjson,"method","forward");
jaddstr(reqjson,"method2","postprice");
memset(zero.bytes,0,sizeof(zero));
LP_forward(ctx,myipaddr,pubsock,profitmargin,zero,jprint(reqjson,1),1);
}
jaddstr(reqjson,"method","postprice");
msg = jprint(reqjson,1);
LP_broadcast_message(pubsock,base,rel,zero,msg);
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 qprice; uint64_t srcvalue,srcvalue2,destvalue,destvalue2;
double qprice; uint64_t txfee,desttxfee,srcvalue,srcvalue2,destvalue,destvalue2;
*autxop = *butxop = 0;
if ( LP_iseligible(&srcvalue,&srcvalue2,1,qp->srccoin,qp->txid,qp->vout,qp->satoshis,qp->txid2,qp->vout2,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");
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);
return(-3);
@ -269,17 +293,20 @@ double LP_quote_validate(struct LP_utxoinfo **autxop,struct LP_utxoinfo **butxop
return(-11);
}
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);
}
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);
}
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);
}
@ -295,7 +322,7 @@ int32_t LP_arrayfind(cJSON *array,bits256 txid,int32_t vout)
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;
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);
if ( bits256_nonz(qp->desthash) != 0 )
flag = 1;
//printf("QUERY.(%s)\n",jprint(reqjson,0));
if ( IAMLP != 0 )
{
jaddstr(reqjson,"method",method);
msg = jprint(reqjson,1);
LP_send(LP_mypubsock,msg,(int32_t)strlen(msg)+1,1);
}
else
{
jaddstr(reqjson,"method2",method);
jaddstr(reqjson,"method","forward");
jaddbits256(reqjson,"pubkey",qp->srchash);
LP_forward(ctx,myipaddr,mypubsock,profitmargin,qp->srchash,jprint(reqjson,1),1);
}
jaddbits256(reqjson,"pubkey",qp->srchash);
jaddstr(reqjson,"method",method);
msg = jprint(reqjson,1);
printf("QUERY.(%s)\n",msg);
LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,qp->srchash,msg);
for (i=0; i<30; i++)
{
if ( (price= LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout)) > SMALLVAL )
{
if ( flag == 0 || bits256_nonz(qp->desthash) != 0 )
{
//printf("break out of loop.%d price %.8f\n",i,price);
printf("break out of loop.%d price %.8f %s/%s\n",i,price,qp->srccoin,qp->destcoin);
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 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 ( (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);
if ( nn_bind(pairsock,bindaddr) >= 0 )
{
timeout = 100;
nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout));
//timeout = 1;
//nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
//nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout));
printf("nanobind %s to %d\n",pairstr,pairsock);
return(pairsock);
} else printf("error binding to %s for %s\n",bindaddr,pairstr);
@ -372,10 +390,10 @@ int32_t LP_nanobind(void *ctx,char *pairstr)
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;
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);
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);
}
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 )
{
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->N.pair = pair;
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);
jaddnum(retjson,"requestid",qp->R.requestid);
jaddnum(retjson,"quoteid",qp->R.quoteid);
char str[65]; printf("BOB pubsock.%d sends to (%s)\n",pubsock,bits256_str(str,utxo->S.otherpubkey));
if ( pubsock >= 0 )
{
msg = jprint(retjson,0);
LP_send(pubsock,msg,(int32_t)strlen(msg)+1,1);
}
jdelete(retjson,"method");
jaddstr(retjson,"method2","connected");
jaddstr(retjson,"method","forward");
LP_forward(ctx,myipaddr,pubsock,profitmargin,utxo->S.otherpubkey,jprint(retjson,1),1);
char str[65]; printf("BOB pubsock.%d binds to %d (%s)\n",pubsock,pair,bits256_str(str,utxo->S.otherpubkey));
msg = jprint(retjson,1);
LP_broadcast_message(pubsock,base,rel,utxo->S.otherpubkey,msg);
retval = 0;
} else printf("error launching swaploop\n");
} else printf("couldnt bind to any port %s\n",pairstr);
}
else
{
printf("dest %.8f vs required %.8f (%d %d %d %d %d)\n",dstr(qp->destsatoshis),dstr(price*(utxo->S.satoshis-qp->txfee)),bits256_nonz(privkey) != 0 ,qp->timestamp == utxo->T.swappending-LP_RESERVETIME,qp->quotetime >= qp->timestamp-3,qp->quotetime < utxo->T.swappending,bits256_cmp(LP_mypubkey,qp->srchash) == 0);
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 )
{
@ -428,33 +439,39 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ
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 )
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\"}"));
printf("CONNECTED.(%s)\n",jprint(argjson,0));
if ( (qprice= LP_quote_validate(&autxo,&butxo,&Q,0)) <= SMALLVAL )
{
LP_availableset(autxo);
LP_pendingswaps--;
printf("quote validate error %.0f\n",qprice);
return(clonestr("{\"error\":\"quote validation error\"}"));
}
if ( (price= LP_myprice(&bid,&ask,Q.destcoin,Q.srccoin)) <= SMALLVAL || ask <= SMALLVAL )
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);
LP_availableset(autxo);
LP_pendingswaps--;
return(clonestr("{\"error\":\"no price set\"}"));
}
price = 1. / ask;
if ( qprice > price+0.00000001 )
printf("%s/%s bid %.8f ask %.8f\n",Q.srccoin,Q.destcoin,bid,ask);
//if ( (price= ask) == 0. )
price = bid;
/*if ( SATOSHIDEN*qprice > (SATOSHIDEN * price) * 1.001 + 10 )
{
printf("qprice %.8f too big vs %.8f\n",qprice,price);
LP_availableset(autxo);
LP_pendingswaps--;
return(clonestr("{\"error\":\"quote price too expensive\"}"));
}
}*/
if ( (coin= LP_coinfind(Q.destcoin)) == 0 )
{
LP_pendingswaps--;
return(clonestr("{\"error\":\"cant get alicecoin\"}"));
}
Q.privkey = LP_privkey(Q.destaddr,coin->taddr);
@ -465,10 +482,10 @@ char *LP_connectedalice(cJSON *argjson) // alice
jaddstr(retjson,"error","couldnt create pairsock");
else if ( nn_connect(pairsock,pairstr) >= 0 )
{
timeout = 100;
nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout));
LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis,Q.destcoin,Q.destsatoshis,Q.timestamp,Q.quotetime,DEXselector);
//timeout = 1;
//nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
//nn_setsockopt(pairsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout));
LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-Q.txfee,Q.destcoin,Q.destsatoshis-Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector);
swap = LP_swapinit(0,0,Q.privkey,&Q.R,&Q);
swap->N.pair = pairsock;
autxo->S.swap = swap;
@ -485,6 +502,7 @@ char *LP_connectedalice(cJSON *argjson) // alice
printf("connected result.(%s)\n",jprint(retjson,0));
if ( jobj(retjson,"error") != 0 )
LP_availableset(autxo);
else LP_pendingswaps++;
return(jprint(retjson,1));
}
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;
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;
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 )
{
@ -515,7 +533,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
printf("quote validate error %.0f\n",qprice);
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);
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,"pubkey",butxo->S.otherpubkey);
jaddstr(retjson,"method","reserved");
if ( pubsock >= 0 )
{
msg = jprint(retjson,0);
LP_send(pubsock,msg,(int32_t)strlen(msg)+1,1);
}
jdelete(retjson,"method");
jaddstr(retjson,"method2","reserved");
jaddstr(retjson,"method","forward");
LP_forward(ctx,myipaddr,pubsock,profitmargin,butxo->S.otherpubkey,jprint(retjson,1),1);
msg = jprint(retjson,1);
printf("set swappending.%u accept qprice %.8f, min %.8f\n(%s)",butxo->T.swappending,qprice,price,msg);
LP_broadcast_message(pubsock,Q.srccoin,Q.destcoin,butxo->S.otherpubkey,msg);
butxo->T.lasttime = (uint32_t)time(NULL);
printf("set swappending.%u accept qprice %.8f, min %.8f\n",butxo->T.swappending,qprice,price);
} else printf("warning swappending.%u swap.%p\n",butxo->T.swappending,butxo->S.swap);
}
else if ( strcmp(method,"connect") == 0 ) // bob
{
retval = 4;
if ( butxo->T.swappending != 0 && butxo->S.swap == 0 )
LP_connectstartbob(ctx,pubsock,butxo,argjson,myipaddr,Q.srccoin,Q.destcoin,profitmargin,qprice,&Q);
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));
}
}
@ -560,19 +571,16 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
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.;
*bestdestsatoshisp = 0;
*bestsatoshisp = *bestdestsatoshisp = 0;
if ( duration <= 0 )
duration = LP_ORDERBOOK_DURATION;
if ( maxprice <= 0. || LP_priceinfofind(base) == 0 )
return(0);
if ( (desttxfee= LP_getestimatedrate(autxo->coin) * LP_AVETXSIZE) < LP_MIN_TXFEE )
desttxfee = LP_MIN_TXFEE;
if ( (txfee= LP_getestimatedrate(base) * LP_AVETXSIZE) < LP_MIN_TXFEE )
txfee = LP_MIN_TXFEE;
LP_txfees(&txfee,&desttxfee,base,autxo->coin);
if ( (obookstr= LP_orderbook(base,autxo->coin,duration)) != 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++)
{
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;
if ( price > maxprice )
price = maxprice;
//price *= 1.0001;
//if ( price > maxprice )
// price = maxprice;
pubkey = jbits256(item,"pubkey");
if ( bits256_cmp(pubkey,LP_mypubkey) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 && pubp->numerrors < LP_MAXPUBKEY_ERRORS )
if ( bits256_cmp(pubkey,LP_mypub25519) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 && pubp->numerrors < LP_MAXPUBKEY_ERRORS )
{
if ( bestprice == 0. ) // assumes price ordered asks
bestprice = price;
@ -599,33 +608,59 @@ struct LP_utxoinfo *LP_bestutxo(double *ordermatchpricep,int64_t *bestdestsatosh
metric = price / bestprice;
if ( (butxo= LP_utxofind(1,txid,vout)) != 0 && (long long)(vol*SATOSHIDEN) == butxo->S.satoshis && LP_isavailable(butxo) > 0 && LP_ismine(butxo) == 0 )//&& butxo->T.bestflag == 0 )
{
destsatoshis = ((butxo->S.satoshis - txfee) * price);
if ( destsatoshis > autxo->payment.value-desttxfee-1 )
destsatoshis = autxo->payment.value-desttxfee-1;
satoshis = (destsatoshis / price + 0.0000000049) - txfee;
if ( metric < 1.2 && destsatoshis > desttxfee && destsatoshis-desttxfee > (autxo->payment.value / LP_MINCLIENTVOL) && satoshis-txfee > (butxo->S.satoshis / LP_MINVOL) && satoshis <= butxo->payment.value-txfee )
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 )
{
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 )
destsatoshis = ((butxo->S.satoshis - txfee) * price);
satoshis = (destsatoshis / price + 0.49) - txfee;
if ( satoshis <= 0 )
continue;
qprice = (double)destsatoshis / satoshis;
n = (int32_t)((double)destsatoshis / desttxfee);
if ( n < 10 )
n = 10;
else n = 3;
for (j=0; j<n; j++)
{
bestutxo = butxo;
*ordermatchpricep = price;
*bestdestsatoshisp = destsatoshis;
bestmetric = metric;
printf("set best!\n");
if ( (qprice= LP_qprice_calc(&destsatoshis,&satoshis,(price*(100.+j))/100.,butxo->S.satoshis,txfee,autxo->payment.value,maxdestsatoshis,desttxfee)) > price+SMALLVAL )
break;
}
} 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
{
if ( butxo != 0 )
printf("%llu %llu %d %d %d: ",(long long)(vol*SATOSHIDEN),(long long)butxo->S.satoshis,vol*SATOSHIDEN == butxo->S.satoshis,LP_isavailable(butxo) > 0,LP_ismine(butxo) == 0);
printf("cant find butxo.%p or value mismatch %.8f != %.8f or bestflag.%d\n",butxo,vol,butxo!=0?dstr(butxo->S.satoshis):0,butxo->T.bestflag);
//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 break;
}
else
{
if ( i == 0 )
printf("maxprice %.8f vs %.8f\n",maxprice,price);
break;
}
}
}
free_json(orderbook);
@ -634,6 +669,8 @@ struct LP_utxoinfo *LP_bestutxo(double *ordermatchpricep,int64_t *bestdestsatosh
}
if ( bestutxo == 0 || *ordermatchpricep == 0. || *bestdestsatoshisp == 0 )
return(0);
int32_t changed;
LP_mypriceset(&changed,autxo->coin,base,1. / *ordermatchpricep);
return(bestutxo);
}
@ -647,47 +684,43 @@ char *LP_bestfit(char *rel,double relvolume)
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;
if ( desttxfee == 0 && (desttxfee= LP_getestimatedrate(rel) * LP_AVETXSIZE) < LP_MIN_TXFEE )
desttxfee = LP_MIN_TXFEE;
if ( txfee == 0 && (txfee= LP_getestimatedrate(base) * LP_AVETXSIZE) < LP_MIN_TXFEE )
txfee = LP_MIN_TXFEE;
struct LP_quoteinfo Q; int64_t bestsatoshis=0,bestdestsatoshis = 0; double ordermatchprice = 0.; struct LP_utxoinfo *autxo,*bestutxo;
txfee = LP_txfeecalc(base,txfee);
desttxfee = LP_txfeecalc(rel,desttxfee);
if ( (autxo= LP_utxopairfind(0,txid,vout,feetxid,feevout)) == 0 )
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\"}"));
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\"}"));
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(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 )
{
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\"}"));
}
printf("aliceutxo.%p\n",aliceutxo);
if ( (bobutxo= LP_utxopairfind(1,qp->txid,qp->vout,qp->txid2,qp->vout2)) == 0 )
return(clonestr("{\"error\":\"cant find bob utxopair\"}"));
printf("bobutxo.%p\n",bobutxo);
bobutxo->T.bestflag = (uint32_t)time(NULL);
if ( (retstr= LP_registerall(0)) != 0 )
free(retstr);
price = LP_query(ctx,myipaddr,mypubsock,profitmargin,"request",qp);
//if ( (retstr= LP_registerall(0)) != 0 )
// free(retstr);
price = LP_query(ctx,myipaddr,mypubsock,"request",qp);
bestitem = LP_quotejson(qp);
if ( price > SMALLVAL )
if ( LP_pricevalid(price) > 0 )
{
if ( price <= maxprice )
{
price = LP_query(ctx,myipaddr,mypubsock,profitmargin,"connect",qp);
LP_requestinit(&qp->R,qp->srchash,qp->desthash,bobutxo->coin,qp->satoshis,qp->destcoin,qp->destsatoshis,qp->timestamp,qp->quotetime,DEXselector);
price = LP_query(ctx,myipaddr,mypubsock,"connect",qp);
LP_requestinit(&qp->R,qp->srchash,qp->desthash,bobutxo->coin,qp->satoshis-qp->txfee,qp->destcoin,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector);
expiration = (uint32_t)time(NULL) + timeout;
while ( time(NULL) < expiration )
{
@ -724,9 +757,9 @@ char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,double profitmargin,st
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 )
duration = LP_ORDERBOOK_DURATION;
if ( timeout <= 0 )
@ -735,21 +768,23 @@ char *LP_autotrade(void *ctx,char *myipaddr,int32_t mypubsock,double profitmargi
return(clonestr("{\"error\":\"invalid parameter\"}"));
if ( (autxo= LP_utxo_bestfit(rel,SATOSHIDEN * relvolume)) == 0 )
return(clonestr("{\"error\":\"cant find utxo that is big enough\"}"));
if ( (desttxfee= LP_getestimatedrate(rel) * LP_AVETXSIZE) < LP_MIN_TXFEE )
desttxfee = LP_MIN_TXFEE;
if ( (txfee= LP_getestimatedrate(base) * LP_AVETXSIZE) < LP_MIN_TXFEE )
txfee = LP_MIN_TXFEE;
if ( (bestutxo= LP_bestutxo(&ordermatchprice,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 )
LP_txfees(&txfee,&desttxfee,base,rel);
if ( (bestutxo= LP_bestutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,SATOSHIDEN*relvolume)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 )
{
printf("bestutxo.%p ordermatchprice %.8f bestdestsatoshis %.8f\n",bestutxo,ordermatchprice,dstr(bestdestsatoshis));
return(clonestr("{\"error\":\"cant find ordermatch utxo\"}"));
}
if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestdestsatoshis) < 0 )
if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestsatoshis,bestdestsatoshis) < 0 )
return(clonestr("{\"error\":\"cant set ordermatch quote\"}"));
if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,LP_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\"}"));
if ( (qprice= LP_quote_validate(&autxo,&butxo,&Q,0)) <= SMALLVAL )
{
printf("quote validate error %.0f\n",qprice);
return(clonestr("{\"error\":\"quote validation error\"}"));
}
printf("do quote.(%s)\n",jprint(LP_quotejson(&Q),1));
return(LP_trade(ctx,myipaddr,mypubsock,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();
jaddstr(item,"ipaddr",peer->ipaddr);
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);
}
@ -48,26 +54,32 @@ char *LP_peers()
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);
expand_ipbits(checkip,ipbits);
if ( strcmp(checkip,ipaddr) == 0 )
{
if ( (peer= LP_peerfind(ipbits,port)) != 0 )
{
if ( profitmargin != 0. )
peer->profitmargin = profitmargin;
if ( numpeers > peer->numpeers )
/*if ( numpeers > peer->numpeers )
peer->numpeers = numpeers;
if ( numutxos > peer->numutxos )
peer->numutxos = numutxos;
if ( peer->sessionid == 0 )
peer->sessionid = sessionid;*/
}
else
{
printf("LPaddpeer %s\n",ipaddr);
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;
strcpy(peer->ipaddr,ipaddr);
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);
if ( nn_connect(pushsock,pushaddr) >= 0 )
{
timeout = 100;
timeout = 1;
nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
maxsize = 2 * 1024 * 1024;
nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDBUF,&maxsize,sizeof(maxsize));
//maxsize = 2 * 1024 * 1024;
//nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDBUF,&maxsize,sizeof(maxsize));
printf("connected to push.(%s) %d\n",pushaddr,pushsock);
peer->connected = (uint32_t)time(NULL);
peer->pushsock = pushsock;
@ -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);
}
} else printf("%s pushport.%u subport.%u pushsock.%d\n",ipaddr,pushport,subport,pushsock);
peer->profitmargin = profitmargin;
//peer->profitmargin = profitmargin;
peer->ipbits = ipbits;
peer->port = port;
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);
} else peer->numpeers = 1; // will become mypeer
portable_mutex_unlock(&LP_peermutex);
if ( mypubsock >= 0 )
if ( IAMLP != 0 && mypubsock >= 0 )
{
char *msg = jprint(LP_peerjson(peer),1);
LP_send(mypubsock,msg,(int32_t)strlen(msg)+1,1);
struct iguana_info *coin,*ctmp; bits256 zero; char *msg,busaddr[64];
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);
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)
{
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);
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 )
{
@ -158,11 +214,11 @@ int32_t LP_peersparse(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipa
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;
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);
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 )
{
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++;
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);
}
}

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];
uint64_t coinbits;
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 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];
int32_t LP_numpriceinfos;
@ -49,6 +54,13 @@ struct LP_pubkeyinfo
uint32_t timestamp,istrusted,numerrors;
} *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)
{
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;
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();
jaddistr(item,base);
@ -197,7 +210,7 @@ char *LP_prices()
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");
if ( bits256_nonz(pubkey) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 )
{
@ -210,10 +223,18 @@ void LP_prices_parse(cJSON *obj)
base = jstri(item,0);
rel = jstri(item,1);
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);
pubp->matrix[basepp->ind][relid] = askprice;
if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 )
{
char str[65]; printf("%s %s/%s (%d/%d) %.8f\n",bits256_str(str,pubkey),base,rel,basepp->ind,relid,askprice);
pubp->matrix[basepp->ind][relid] = askprice;
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;
if ( ptr->price == 0. && ptr->Q.satoshis != 0 )
{
printf("LP_pricecache: null ptr->price? ");
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);
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)
{
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);
//dxblend(&relpp->relvals[basepp->ind],1. / price,0.9);
basepp->relvals[relpp->ind] = price;
relpp->relvals[basepp->ind] = 1. / price;
if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
//dxblend(&basepp->relvals[relpp->ind],price,0.9);
//dxblend(&relpp->relvals[basepp->ind],1. / price,0.9);
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.;
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;
return((*askp + *bidp) * 0.5);
@ -290,7 +318,8 @@ double LP_myprice(double *bidp,double *askp,char *base,char *rel)
}
else
{
if ( (val= relpp->myprices[basepp->ind]) > SMALLVAL )
val = relpp->myprices[basepp->ind];
if ( LP_pricevalid(val) > 0 )
{
*bidp = 1. / val;
*askp = 0.;
@ -325,14 +354,18 @@ char *LP_myprices()
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;
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
//printf("LP_mypriceset base.%s rel.%s <- price %.8f\n",base,rel,price);
//relpp->myprices[basepp->ind] = (1. / price); // bid
if ( (pubp= LP_pubkeyadd(LP_mypubkey)) != 0 )
if ( (pubp= LP_pubkeyadd(LP_mypub25519)) != 0 )
{
pubp->matrix[basepp->ind][relpp->ind] = 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;
if ( base == 0 || rel == 0 )
return(0);
if ( (ptr= LP_cachefind(base,rel,txid,vout)) == 0 )
if ( LP_pricevalid(price) > 0 )
{
ptr = calloc(1,sizeof(*ptr));
if ( LP_cachekey(ptr->key,base,rel,txid,vout) == sizeof(ptr->key) )
if ( (ptr= LP_cachefind(base,rel,txid,vout)) == 0 )
{
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 = calloc(1,sizeof(*ptr));
if ( LP_cachekey(ptr->key,base,rel,txid,vout) == sizeof(ptr->key) )
{
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);
}
@ -475,7 +511,7 @@ static int _cmp_orderbook(const void *a,const void *b)
cJSON *LP_orderbookjson(struct LP_orderbookentry *op)
{
cJSON *item = cJSON_CreateObject();
if ( op->price > SMALLVAL )
if ( LP_pricevalid(op->price) > 0 )
{
jaddnum(item,"price",op->price);
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);
}
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)
{
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 )
baseid = basepp->ind;
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_iseligible(&val,&val2,utxo->iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,utxo->deposit.txid,utxo->deposit.vout) == 0 )
continue;
if ( polarity > 0 )
basesatoshis = utxo->S.satoshis;
else basesatoshis = utxo->S.satoshis * price;
@ -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)[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);
}
}
@ -595,13 +607,13 @@ char *LP_orderbook(char *base,char *rel,int32_t duration)
qsort(bids,numbids,sizeof(*bids),_cmp_orderbook);
if ( numasks > 1 )
{
for (i=0; i<numasks; i++)
printf("%.8f ",asks[i]->price);
printf(" -> ");
//for (i=0; i<numasks; i++)
// printf("%.8f ",asks[i]->price);
//printf(" -> ");
qsort(asks,numasks,sizeof(*asks),_cmp_orderbook);
for (i=0; i<numasks; i++)
printf("%.8f ",asks[i]->price);
printf("sorted asks.%d\n",numasks);
//for (i=0; i<numasks; i++)
// printf("%.8f ",asks[i]->price);
//printf("sorted asks.%d\n",numasks);
}
for (i=0; i<numbids; i++)
{
@ -639,12 +651,12 @@ char *LP_pricestr(char *base,char *rel,double origprice)
if ( origprice > SMALLVAL && origprice < price )
price = origprice;
}
if ( price > SMALLVAL )
if ( LP_pricevalid(price) > 0 )
{
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"method","postprice");
jaddbits256(retjson,"pubkey",LP_mypubkey);
jaddbits256(retjson,"pubkey",LP_mypub25519);
jaddstr(retjson,"base",base);
jaddstr(retjson,"rel",rel);
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);
}
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)
{
struct LP_priceinfo *basepp,*relpp; struct LP_pubkeyinfo *pubp; char str[65];
if ( price > SMALLVAL && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
struct LP_priceinfo *basepp,*relpp; uint32_t now; uint64_t price64; struct LP_pubkeyinfo *pubp; char str[65],fname[512]; FILE *fp;
//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 )
{
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);
} 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);
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 )
{
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);
sentflags[alicespent] = 1;
sentflags[bobspent] = 0;
txids[alicespent] = spendtxid;
}
else if ( bobaddr != 0 && strcmp(destaddr,bobaddr) == 0 )
{
//printf("BOB spent.(%s) -> %s\n",bits256_str(str,txid),destaddr);
sentflags[bobspent] = 1;
sentflags[alicespent] = 0;
txids[bobspent] = spendtxid;
}
else
@ -278,11 +280,13 @@ bits256 basilisk_swap_spendupdate(char *symbol,int32_t *sentflags,bits256 *txids
if ( aliceaddr != 0 )
{
sentflags[bobspent] = 1;
sentflags[alicespent] = 0;
txids[bobspent] = spendtxid;
}
else if ( bobaddr != 0 )
{
sentflags[alicespent] = 1;
sentflags[bobspent] = 0;
txids[alicespent] = spendtxid;
}
}
@ -365,13 +369,43 @@ int32_t basilisk_swap_isfinished(int32_t iambob,bits256 *txids,int32_t *sentflag
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)
{
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 )
ctx = bitcoin_ctx();
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(txids,0,sizeof(txids));
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(" <- %s dest33\n",dest33);
}
plocktime = juint(item,"plocktime");
dlocktime = juint(item,"dlocktime");
if ( (plocktime= juint(item,"plocktime")) == 0 )
plocktime = LP_extract(requestid,quoteid,fname,"plocktime");
if ( (dlocktime= juint(item,"dlocktime")) == 0 )
dlocktime = LP_extract(requestid,quoteid,fname,"dlocktime");
r = juint(item,"requestid");
q = juint(item,"quoteid");
Atxfee = j64bits(item,"Atxfee");
Btxfee = j64bits(item,"Btxfee");
pubA0 = jbits256(item,"pubA0");
pubB0 = jbits256(item,"pubB0");
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);
if ( (fstr= OS_filestr(&fsize,fname)) != 0 )
{
if ( finishedflag == 0 )
if ( 0 && finishedflag == 0 )
printf("%s\n",fname);
//printf("%s -> (%s)\n",fname,fstr);
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"));
//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 )
value = jdouble(txobj,"value") * SATOSHIDEN;
values[i] = value;
@ -552,12 +600,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
}
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");
free(fstr);
} else if ( finishedflag == 0 )
} else if ( 0 && finishedflag == 0 )
printf("%s not finished\n",fname);
}
//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;
if ( bobcoin[0] == 0 || alicecoin[0] == 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("privBn.(%s) %p/%p\n",bits256_str(str,privBn),Bdest,ABdest);
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;
}
}
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 )
{
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];
//revcalc_rmd160_sha256(secretAm,rev);//privAm);
//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);
{
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++)
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]);
}
}
@ -657,11 +721,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
{
//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 )
{
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]);
}
}
@ -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);
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]);
}
}
@ -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 ( (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]);
}
}
@ -737,7 +803,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
if ( redeemlen > 0 )
{
len = basilisk_swapuserdata(userdata,zero,1,myprivs[1],redeemscript,redeemlen);
if ( (txbytes[BASILISK_BOBRECLAIM]= basilisk_swap_bobtxspend(&signedtxid,txfee,"bobrefund",bobcoin,bob->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;
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));
redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,dlocktime,pubA0,pubB0,pubB1,privAm,privBn,secretAm,secretAm256,secretBn,secretBn256);
len = basilisk_swapuserdata(userdata,privBn,0,myprivs[0],redeemscript,redeemlen);
if ( (txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend(&signedtxid,txfee,"bobrefund",bobcoin,bob->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]);
}
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];
}
}
} 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);
}
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];
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);
return(LP_issue_curl("getpeers",destip,port,url));
char url[512],*retstr;
sprintf(url,"http://%s:%u/api/stats/getpeers?ipaddr=%s&port=%u&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,numpeers,numutxos);
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];
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(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);
}
change to nanomsg write only, enforce fee, comms api
char *issue_LP_notify(char *destip,uint16_t destport,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos)
char *issue_LP_notify(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers,int32_t numutxos,uint32_t sessionid)
{
char url[512],*retstr;
if ( (retstr= LP_isitme(destip,destport)) != 0 )
{
free(retstr);
return(0);
}
sprintf(url,"http://%s:%u/api/stats/notify?ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,profitmargin,numpeers,numutxos);
return(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(LP_issue_curl("notify",destip,destport,url));
//return(issue_curlt(url,LP_HTTP_TIMEOUT));
}
char *issue_LP_notifyutxo(char *destip,uint16_t destport,struct LP_utxoinfo *utxo)
{
char url[4096],str[65],str2[65],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 url[512];
@ -186,7 +109,7 @@ cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params)
if ( coin != 0 )
{
//printf("issue.(%s, %s, %s, %s, %s)\n",coin->symbol,coin->serverport,coin->userpass,method,params);
if ( coin->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);
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);
free(retstr);
}
//usleep(1000);
//usleep(100);
//printf("dpow_gettxout.(%s)\n",retstr);
} else retjson = cJSON_Parse("{\"result\":\"disabled\"}");
} 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));
}
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)
{
struct iguana_info *coin = LP_coinfind(symbol);
@ -219,10 +175,19 @@ cJSON *LP_getmempool(char *symbol)
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)
{
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));
}
@ -250,7 +215,7 @@ cJSON *LP_getblockhashstr(char *symbol,char *blockhashstr)
cJSON *LP_listunspent(char *symbol,char *coinaddr)
{
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));
}
@ -266,15 +231,35 @@ cJSON *LP_listtransactions(char *symbol,char *coinaddr,int32_t count,int32_t ski
cJSON *LP_validateaddress(char *symbol,char *address)
{
char buf[512]; struct iguana_info *coin = LP_coinfind(symbol);
sprintf(buf,"\"%s\"",address);
sprintf(buf,"[\"%s\"]",address);
return(bitcoin_json(coin,"validateaddress",buf));
}
cJSON *LP_importprivkey(char *symbol,char *wifstr,char *label,int32_t flag)
{
char buf[512]; struct iguana_info *coin = LP_coinfind(symbol);
sprintf(buf,"[\"%s\", \"%s\", %s]",wifstr,label,flag < 0 ? "false" : "true");
return(bitcoin_json(coin,"importprivkey",buf));
static void *ctx;
char buf[512],address[64]; cJSON *retjson; struct iguana_info *coin; int32_t doneflag = 0;
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)
@ -307,27 +292,27 @@ int32_t LP_importaddress(char *symbol,char *address)
double LP_getestimatedrate(char *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);
if ( (retstr= bitcoind_passthru(symbol,coin->serverport,coin->userpass,"estimatefee",buf)) != 0 )
{
if ( retstr[0] != '-' )
{
coin->estimatedrate = rate = atof(retstr) / 1024.;
printf("estimated rate.(%s) %s -> %.8f\n",symbol,retstr,rate);
rate = atof(retstr) / 1024.;
//printf("estimated rate.(%s) %s -> %.8f\n",symbol,retstr,rate);
}
free(retstr);
}
}
return(rate);
} else return((double)coin->txfee / LP_AVETXSIZE);
return(SATOSHIDEN * rate);
}
uint64_t LP_txfee(char *symbol)
{
uint64_t txfee = 0;
if ( strcmp(symbol,"BTC") != 0 )
txfee = 10000;
txfee = LP_MIN_TXFEE;
return(txfee);
}
@ -412,7 +397,7 @@ cJSON *LP_blockjson(int32_t *heightp,char *symbol,char *blockhashstr,int32_t hei
*heightp = juint(json,"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;
free_json(json);
json = 0;

320
iguana/exchanges/LP_scan.c

@ -18,6 +18,31 @@
// 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 *tx;
@ -119,23 +144,24 @@ uint64_t LP_txinterestvalue(uint64_t *interestp,char *destaddr,struct iguana_inf
if ( n > 1 )
printf("LP_txinterestvalue warning: violation of 1 output assumption n.%d\n",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);
}
} else { char str[65]; printf("null gettxout return %s/v%d\n",bits256_str(str,txid),vout); }
return(value);
}
int32_t LP_transactioninit(struct iguana_info *coin,bits256 txid)
int32_t 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];
if ( (txobj=LP_gettx(coin->symbol,txid)) != 0 )
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 )
{
//printf("TX.(%s)\n",jprint(txobj,0));
height = LP_txheight(&timestamp,&blocktime,coin,txid);
if ( timestamp == 0 && height > 0 )
timestamp = blocktime;
vins = jarray(&numvins,txobj,"vin");
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++)
{
@ -143,15 +169,32 @@ int32_t LP_transactioninit(struct iguana_info *coin,bits256 txid)
if ( (tx->outpoints[i].value= SATOSHIDEN * jdouble(vout,"value")) == 0 )
tx->outpoints[i].value = SATOSHIDEN * jdouble(vout,"amount");
tx->outpoints[i].interest = SATOSHIDEN * jdouble(vout,"interest");
if ( (sobj= jobj(vout,"scriptPubKey")) != 0 )
{
if ( (addresses= jarray(&n,sobj,"addresses")) != 0 && n > 0 )
{
//printf("%s\n",jprint(addresses,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);
if ( 0 && strcmp(address,"RXzsovGBQ3W97xnVC6JnWxXsV4qb7p7iBi") == 0 )
printf("%s %.8f at height.%d\n",address,dstr(tx->outpoints[i].value),height);
}
}
}
}
}
if ( vins != 0 )
if ( iter == 1 && vins != 0 )
{
for (i=0; i<numvins; i++)
{
vin = jitem(vins,i);
spenttxid = jbits256(vin,"txid");
spentvout = jint(vin,"vout");
if ( i == 0 && bits256_nonz(spenttxid) == 0 )
continue;
if ( (tx= LP_transactionfind(coin,spenttxid)) != 0 )
{
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].spendheight = 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);
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);
}
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,iter,numtx,checkht=-1; cJSON *blockobj,*txs; bits256 txid; struct LP_transaction *tx;
if ( (blockobj= LP_blockjson(&checkht,coin->symbol,0,height)) != 0 )
{
if ( (txs= jarray(&numtx,blockobj,"tx")) != 0 )
{
for (iter=0; iter<2; iter++)
for (i=0; i<numtx; i++)
{
txid = jbits256i(txs,i);
@ -189,7 +235,9 @@ int32_t LP_blockinit(struct iguana_info *coin,int32_t height)
printf("LP_blockinit: tx->height %d != %d\n",tx->height,height);
tx->height = height;
}
} else LP_transactioninit(coin,txid);
if ( iter == 1 )
LP_transactioninit(coin,txid,iter);
} else LP_transactioninit(coin,txid,iter);
}
}
free_json(blockobj);
@ -199,6 +247,234 @@ int32_t LP_blockinit(struct iguana_info *coin,int32_t height)
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);
}
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));
}
cJSON *LP_snapshot(struct iguana_info *coin,int32_t height)
{
static char lastcoin[16]; static int32_t maxsnapht;
struct LP_transaction *tx,*tmp; struct LP_address *ap,*atmp; int32_t i,n,skipflag=0,startht,endht,ht; uint64_t balance=0,noaddr_balance=0; cJSON *retjson,*array,*item;
//LP_blockinit(coin,421011);
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;
}
HASH_ITER(hh,coin->transactions,tx,tmp)
{
if ( tx->height < height )
{
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);
jaddnum(retjson,"numaddresses",n);
jaddnum(retjson,"total",dstr(balance));
jaddnum(retjson,"noaddr_total",dstr(noaddr_balance));
return(retjson);
}
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)
{
char destaddr[64]; uint64_t value,interest = 0; struct iguana_info *coin;
@ -222,22 +498,23 @@ uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout)
{
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);
}
else
{
if ( coinaddr != 0 && strcmp(symbol,"KMD") == 0 )
{
if ( coinaddr != 0 )
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));
return(tx->outpoints[vout].value + tx->outpoints[vout].interest);
}
} else printf("vout.%d >= tx->numvouts.%d\n",vout,tx->numvouts);
}
if ( tx == 0 )
LP_transactioninit(coin,txid);
{
LP_transactioninit(coin,txid,0);
LP_transactioninit(coin,txid,1);
}
if ( coinaddr == 0 )
coinaddr = _coinaddr;
value = LP_txinterestvalue(&interest,coinaddr,coin,txid,vout);
@ -277,7 +554,10 @@ int32_t LP_mempoolscan(char *symbol,bits256 searchtxid)
{
txid = jbits256i(array,i);
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 )
{
char str[65]; printf("found %s tx.(%s) in mempool slot.%d\n",symbol,bits256_str(str,txid),i);
@ -290,7 +570,7 @@ int32_t LP_mempoolscan(char *symbol,bits256 searchtxid)
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;
//#ifndef BASILISK_DISABLEWAITTX
@ -303,7 +583,7 @@ int32_t LP_numconfirms(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx)
numconfirms = jint(txobj,"confirmations");
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;
//#endif
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);
}
/*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)
{
@ -685,7 +788,7 @@ int32_t basilisk_swapiteration(struct basilisk_swap *swap,uint8_t *data,int32_t
}
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;
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);
printf("Bob spends alicepayment aliceconfirms.%d\n",swap->I.aliceconfirms);
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");
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");
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");
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 )
{
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");
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 )
{
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");
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 )
{
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++)
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))
{
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 )
{
//printf("start wait\n");
if ( (datalen= nn_recv(pairsock,&data,NN_MSG,0)) >= 0 )
memset(&pfd,0,sizeof(pfd));
pfd.fd = pairsock;
pfd.events = NN_POLLIN;
if ( nn_poll(&pfd,1,1) > 0 )
{
//printf("wait for got.%d\n",datalen);
retval = (*verify)(swap,data,datalen);
nn_freemsg(data);
//printf("retval.%d\n",retval);
return(retval);
} // else printf("error nn_recv\n");
//printf("start wait\n");
if ( (datalen= nn_recv(pairsock,&data,NN_MSG,0)) >= 0 )
{
//printf("wait for got.%d\n",datalen);
retval = (*verify)(swap,data,datalen);
nn_freemsg(data);
//printf("retval.%d\n",retval);
return(retval);
} // else printf("error nn_recv\n");
}
}
printf("waitfor timedout\n");
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 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 )
{
printf("waited for %s\n",statename);
//printf("waited for %s\n",statename);
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;
} else printf("send %s error\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);
if ( (datalen= (*datagen)(swap,data,maxlen)) > 0 )
{
//printf("generated %d for %s\n",datalen,statename);
if ( (sendlen= nn_send(pairsock,data,datalen,0)) == datalen )
//printf("generated %d for %s, timeout.%d\n",datalen,statename,timeout);
if ( (sendlen= swap_nn_send(pairsock,data,datalen,0,timeout)) == datalen )
{
//printf("sendwait.%s sent %d\n",statename,sendlen);
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);
retval = 0;
} 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);
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)
{
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++)
otherhash.bytes[i] = recvbuf[offset++];
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 )
{
rawtx->I.actualtxid = rawtx->I.signedtxid;
//char str[65]; printf("got %s txid.%s (%s)\n",rawtx->name,bits256_str(str,rawtx->I.signedtxid),jprint(txobj,0));
rawtx->I.locktime = rawtx->msgtx.lock_time;
if ( (vouts= jarray(&n,txobj,"vout")) != 0 && v < n )
{
vout = jitem(vouts,v);
if ( j64bits(vout,"satoshis") == rawtx->I.amount && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 )
if ( 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) )
{
decode_hex(rawtx->spendscript,hexlen,hexstr);
rawtx->I.spendlen = hexlen;
bitcoin_address(rawtx->p2shaddr,rawtx->coin->taddr,rawtx->coin->p2shtype,rawtx->spendscript,hexlen);
//if ( swap != 0 )
// basilisk_txlog(swap->myinfoptr,swap,rawtx,-1); // bobdeposit, bobpayment or alicepayment
retval = 0;
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);
}
@ -659,14 +694,14 @@ int32_t LP_swapwait(uint32_t requestid,uint32_t quoteid,int32_t duration,int32_t
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");
maxlen = 1024*1024 + sizeof(*swap);
data = malloc(maxlen);
expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT;
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");
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");
@ -681,11 +716,11 @@ void LP_bobloop(void *_swap)
basilisk_bobdeposit_refund(swap,swap->I.putduration);
//printf("depositlen.%d\n",swap->bobdeposit.I.datalen);
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");
else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x200,data,maxlen,&swap->bobdeposit,0x100,0) == 0 )
printf("error sending bobdeposit\n");
else if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT,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");
else
{
@ -693,7 +728,10 @@ void LP_bobloop(void *_swap)
printf("error bobscripts payment\n");
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));
sleep(3);
@ -717,14 +755,14 @@ void LP_bobloop(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);
data = malloc(maxlen);
expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT;
if ( swap != 0 )
{
fprintf(stderr,"start swap iamalice pair.%d\n",swap->N.pair);
if ( LP_sendwait("pubkeys",LP_SWAPSTEP_TIMEOUT,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 )
if ( LP_sendwait("pubkeys",60,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 )
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 )
printf("error LP_sendwait choosei\n");
@ -737,30 +775,33 @@ void LP_aliceloop(void *_swap)
LP_swapsfp_update(&swap->I.req);
if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x80,data,maxlen,&swap->myfee,0x40,0) == 0 )
printf("error sending alicefee\n");
else if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT,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");
else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0) == 0 )
printf("error sending alicepayment\n");
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));
sleep(LP_SWAPSTEP_TIMEOUT);
}
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");
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));
sleep(LP_SWAPSTEP_TIMEOUT);
}
if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x20000,data,maxlen,&swap->alicespend,0x40000,0) == 0 )
printf("error sending alicespend\n");
while ( (n= LP_numconfirms(swap,&swap->alicespend)) < swap->I.aliceconfirms )
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));
sleep(LP_SWAPSTEP_TIMEOUT);
@ -775,7 +816,11 @@ void LP_aliceloop(void *_swap)
free(swap);
}
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)
@ -865,8 +910,8 @@ void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx *
rawtx->coin = coin;
strcpy(rawtx->I.coinstr,coin->symbol);
rawtx->I.numconfirms = numconfirms;
if ( (rawtx->I.amount= satoshis) < 10000 )
rawtx->I.amount = 10000;
if ( (rawtx->I.amount= satoshis) < LP_MIN_TXFEE )
rawtx->I.amount = LP_MIN_TXFEE;
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
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];
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;
if ( optionduration < 0 )
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.bobsatoshis = swap->I.req.srcamount;
swap->I.alicesatoshis = swap->I.req.destamount;
if ( (swap->I.bobinsurance= (swap->I.bobsatoshis / INSTANTDEX_INSURANCEDIV)) < 10000 )
swap->I.bobinsurance = 10000;
if ( (swap->I.aliceinsurance= (swap->I.alicesatoshis / INSTANTDEX_INSURANCEDIV)) < 10000 )
swap->I.aliceinsurance = 10000;
if ( (swap->I.bobinsurance= (swap->I.bobsatoshis / INSTANTDEX_INSURANCEDIV)) < LP_MIN_TXFEE )
swap->I.bobinsurance = LP_MIN_TXFEE;
if ( (swap->I.aliceinsurance= (swap->I.alicesatoshis / INSTANTDEX_INSURANCEDIV)) < LP_MIN_TXFEE )
swap->I.aliceinsurance = LP_MIN_TXFEE;
strcpy(swap->I.bobstr,swap->I.req.src);
strcpy(swap->I.alicestr,swap->I.req.dest);
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];
swap = calloc(1,sizeof(*swap));
swap->I.req.quoteid = rp->quoteid;
swap->ctx = bitcoin_ctx();
vcalc_sha256(0,swap->I.orderhash.bytes,(uint8_t *)rp,sizeof(*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);
pubkey25519 = curve25519(privkey,curve25519_basepoint9());
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 )
{
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 )
{
@ -44,7 +45,7 @@ bits256 LP_broadcast(char *txname,char *symbol,char *txbytes,bits256 expectedtxi
}
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);
}
if ( sentflag != 0 )
@ -230,7 +231,7 @@ int32_t iguana_interpreter(struct iguana_info *coin,cJSON *logarray,int64_t nLoc
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;
memset(&privkey,0,sizeof(privkey));
@ -239,7 +240,7 @@ bits256 iguana_str2priv(char *str)
n = (int32_t)strlen(str) >> 1;
if ( n == sizeof(bits256) && is_hexstr(str,sizeof(bits256)) > 0 )
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 )
// privkey = waddr->privkey;
@ -393,7 +394,7 @@ int64_t iguana_lockval(int32_t finalized,int64_t locktime)
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;
maxsize = 1000000;
@ -428,7 +429,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t taddr,uint8_t p
privkeystr = jstr(item,0);
if ( privkeystr == 0 || privkeystr[0] == 0 )
continue;
privkeys[i] = privkey = iguana_str2priv(privkeystr);
privkeys[i] = privkey = iguana_str2priv(wiftaddr,privkeystr);
bitcoin_pubkey33(ctx,pubkeys[i],privkey);
//if ( bits256_nonz(privkey) != 0 )
// 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);
}
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;
*destamountp = 0;
@ -545,12 +546,37 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch
#endif
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 )
change = value - (satoshis + txfee);
printf("utxo %.8f, destamount %.8f change %.8f txfee %.8f\n",dstr(value),dstr(satoshis),dstr(change),dstr(txfee));
} else if ( 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 )
*destamountp = satoshis;
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;
bitcoin_pubkey33(ctx,V[0].signers[1].pubkey,*privkey2p);
bitcoin_priv2wif(wifstr,*privkey2p,wiftype);
bitcoin_priv2wif(wiftaddr,wifstr,*privkey2p,wiftype);
jaddistr(privkeys,wifstr);
V[0].N = V[0].M = 2;
} else V[0].N = V[0].M = 1;
V[0].signers[0].privkey = privkey;
bitcoin_pubkey33(ctx,V[0].signers[0].pubkey,privkey);
bitcoin_priv2wif(wifstr,privkey,wiftype);
bitcoin_priv2wif(wiftaddr,wifstr,privkey,wiftype);
jaddistr(privkeys,wifstr);
V[0].suppress_pubkeys = suppress_pubkeys;
V[0].ignore_cltverr = ignore_cltverr;
@ -631,7 +657,7 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch
completed = 0;
memset(signedtxidp,0,sizeof(*signedtxidp));
//printf("locktime.%u sequenceid.%x rawtx.(%s) vins.(%s)\n",locktime,sequenceid,rawtxbytes,jprint(vins,0));
if ( (completed= iguana_signrawtransaction(ctx,symbol,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 )
printf("couldnt sign transaction.%s %s\n",name,bits256_str(str,*signedtxidp));
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);
//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++)
{
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;
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 )
return(retval);
len = rawtx->I.datalen;
if ( coin->estimatedrate == 0. )
coin->estimatedrate = LP_getestimatedrate(coin->symbol);
newtxfee = coin->estimatedrate * len;
if ( newtxfee < LP_MIN_TXFEE )
newtxfee = LP_MIN_TXFEE;
newtxfee = LP_txfeecalc(coin->symbol,0);
printf("txfee %.8f -> newtxfee %.8f\n",dstr(txfee),dstr(newtxfee));
} else break;
if ( strcmp(str,"myfee") == 0 )
break;
}
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 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;
else if ( dest == &swap->bobreclaim )
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 )
{
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++)
{
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;
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);
}
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;
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;
for (i=0; i<32; i++)
privBn.bytes[i] = rev.bytes[31 - i];*/
txfee = LP_txfee(symbol);
signedtx = basilisk_swap_bobtxspend(&signedtxid,txfee,name,symbol,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= Atxfee) == 0 )
{
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);
}
@ -816,6 +847,7 @@ int32_t basilisk_swap_getsigscript(char *symbol,uint8_t *script,int32_t maxlen,b
return(scriptlen);
}
#ifdef notnow
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;
@ -868,6 +900,7 @@ bits256 _LP_swap_spendtxid(char *symbol,char *destaddr,char *coinaddr,bits256 ut
}
return(spendtxid);
}
#endif
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);
return(spendtxid);
//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}]}}]
LP_swap_getcoinaddr(symbol,coinaddr,utxotxid,vout);
/*LP_swap_getcoinaddr(symbol,coinaddr,utxotxid,vout);
if ( coinaddr[0] != 0 )
spendtxid = _LP_swap_spendtxid(symbol,destaddr,coinaddr,utxotxid,vout);
spendtxid = _LP_swap_spendtxid(symbol,destaddr,coinaddr,utxotxid,vout);*/
}
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);
memcpy(swap->I.userdata_bobreclaim,userdata,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++)
// 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);
memcpy(swap->I.userdata_bobrefund,userdata,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++)
printf("%02x",swap->bobrefund.txbytes[i]);
@ -1278,7 +1311,7 @@ void basilisk_alicepayment(struct basilisk_swap *swap,struct iguana_info *coin,s
printf(" rmd160, ");*/
bitcoin_address(coinaddr,coin->taddr,coin->pubtype,swap->changermd160,20);
//printf("%s suppress.%d fee.%d\n",coinaddr,alicepayment->I.suppress_pubkeys,swap->myfee.I.suppress_pubkeys);
basilisk_rawtx_gen(swap->ctx,"alicepayment",swap->I.started,swap->persistent_pubkey33,0,1,alicepayment,alicepayment->I.locktime,alicepayment->spendscript,alicepayment->I.spendlen,coin->txfee,1,0,swap->persistent_privkey,swap->changermd160,coinaddr);
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)
@ -1303,11 +1336,11 @@ int32_t basilisk_alicetxs(int32_t pairsock,struct basilisk_swap *swap,uint8_t *d
}
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);
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);
LP_unspents_mark(swap->I.iambob!=0?swap->bobcoin.symbol:swap->alicecoin.symbol,swap->myfee.vins);
//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)
{
// add verification and broadcast
memcpy(swap->otherfee.txbytes,data,datalen);
swap->otherfee.I.datalen = datalen;
swap->otherfee.I.actualtxid = swap->otherfee.I.signedtxid = bits256_doublesha256(0,data,datalen);
return(0);
if ( LP_rawtx_spendscript(swap,swap->bobcoin.longestchain,&swap->otherfee,0,data,datalen,0) == 0 )
{
printf("otherfee amount %.8f -> %s vs %s\n",dstr(swap->otherfee.I.amount),swap->otherfee.p2shaddr,swap->otherfee.I.destaddr);
if ( strcmp(swap->otherfee.I.destaddr,swap->otherfee.p2shaddr) == 0 )
{
printf("dexfee verified\n");
return(0);
}
}
return(-1);
}
/* 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);
if ( bits256_nonz(swap->bobdeposit.I.signedtxid) != 0 )
swap->depositunconf = 1;
basilisk_dontforget_update(swap,&swap->bobdeposit);
len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen);
memcpy(swap->I.userdata_aliceclaim,userdata,len);
swap->I.userdata_aliceclaimlen = len;
bitcoin_address(swap->bobdeposit.p2shaddr,swap->bobcoin.taddr,swap->bobcoin.p2shtype,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen);
strcpy(swap->bobdeposit.I.destaddr,swap->bobdeposit.p2shaddr);
basilisk_dontforget_update(swap,&swap->bobdeposit);
//LP_importaddress(swap->bobcoin.symbol,swap->bobdeposit.I.destaddr);
/*for (i=0; i<swap->bobdeposit.I.datalen; 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);
bitcoin_address(swap->aliceclaim.I.destaddr,swap->alicecoin.taddr,swap->alicecoin.pubtype,swap->persistent_pubkey33,33);
retval = 0;
if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.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++)
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);
if ( bits256_nonz(swap->bobpayment.I.signedtxid) != 0 )
swap->paymentunconf = 1;
basilisk_dontforget_update(swap,&swap->bobpayment);
for (i=0; i<32; i++)
revAm.bytes[i] = swap->I.privAm.bytes[31-i];
len = basilisk_swapuserdata(userdata,revAm,0,swap->I.myprivs[0],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen);
bitcoin_address(swap->bobpayment.p2shaddr,swap->bobcoin.taddr,swap->bobcoin.p2shtype,swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen);
strcpy(swap->bobpayment.I.destaddr,swap->bobpayment.p2shaddr);
basilisk_dontforget_update(swap,&swap->bobpayment);
//LP_importaddress(swap->bobcoin.symbol,swap->bobpayment.I.destaddr);
/*for (i=0; i<swap->bobpayment.I.datalen; 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);
bitcoin_address(swap->alicespend.I.destaddr,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->persistent_pubkey33,33);
//char str[65],str2[65]; printf("bobpaid privAm.(%s) myprivs[0].(%s)\n",bits256_str(str,swap->I.privAm),bits256_str(str2,swap->I.myprivs[0]));
if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->alicespend,&swap->bobpayment,swap->I.myprivs[0],0,userdata,len,1,swap->changermd160,swap->alicepayment.I.destaddr)) == 0 )
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++)
printf("%02x",swap->bobpayment.txbytes[i]);

378
iguana/exchanges/LP_utxos.c

@ -20,7 +20,7 @@
int32_t LP_ismine(struct LP_utxoinfo *utxo)
{
if ( utxo != 0 && bits256_cmp(utxo->pubkey,LP_mypubkey) == 0 )
if ( utxo != 0 && bits256_cmp(utxo->pubkey,LP_mypub25519) == 0 )
return(1);
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 iambob,n = 0; struct LP_utxoinfo *utxo; struct _LP_utxoinfo u;
if ( refutxo == 0 )
return(0);
portable_mutex_lock(&LP_utxomutex);
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)
{
struct LP_utxoinfo *ptrs[8]; int32_t i,n,count = 0; struct _LP_utxoinfo u;
memset(ptrs,0,sizeof(ptrs));
if ( (n= LP_utxocollisions(ptrs,utxo)) > 0 )
{
for (i=0; i<n; i++)
count += _LP_availableset(ptrs[i]);
}
count += _LP_availableset(utxo);
if ( count > 0 )
if ( utxo != 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);
memset(ptrs,0,sizeof(ptrs));
if ( (n= LP_utxocollisions(ptrs,utxo)) > 0 )
{
for (i=0; i<n; i++)
count += _LP_availableset(ptrs[i]);
}
count += _LP_availableset(utxo);
if ( count > 0 )
{
u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee;
char str[65],str2[65]; printf("UTXO.[%d] AVAIL %s/v%d %s/v%d collisions.%d\n",utxo->iambob,bits256_str(str,utxo->payment.txid),utxo->payment.vout,bits256_str(str2,u.txid),u.vout,n);
}
}
}
int32_t LP_utxopurge(int32_t allutxos)
{
char str[65]; struct LP_utxoinfo *utxo,*tmp; int32_t iambob,n = 0;
printf("LP_utxopurge mypub.(%s)\n",bits256_str(str,LP_mypubkey));
printf("LP_utxopurge mypub.(%s)\n",bits256_str(str,LP_mypub25519));
portable_mutex_lock(&LP_utxomutex);
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)
{
struct _LP_utxoinfo u;
jaddstr(item,"method","notified");
jaddstr(item,"method","utxo");
if ( utxo == 0 )
return(item);
if ( utxo->gui[0] != 0 )
jaddstr(item,"gui",utxo->gui);
jaddstr(item,"coin",utxo->coin);
jaddnum(item,"now",time(NULL));
//jaddnum(item,"now",time(NULL));
jaddnum(item,"iambob",utxo->iambob);
jaddstr(item,"address",utxo->coinaddr);
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);
if ( utxo->iambob != 0 )
{
jaddbits256(item,"srchash",LP_mypubkey);
jaddbits256(item,"srchash",utxo->pubkey);//LP_mypub25519);
if ( bits256_nonz(utxo->S.otherpubkey) != 0 )
jaddbits256(item,"desthash",utxo->S.otherpubkey);
}
else
{
jaddbits256(item,"desthash",LP_mypubkey);
jaddbits256(item,"desthash",utxo->pubkey);//LP_mypub25519);
if ( bits256_nonz(utxo->S.otherpubkey) != 0 )
jaddbits256(item,"srchash",utxo->S.otherpubkey);
}
@ -264,6 +271,7 @@ cJSON *LP_inventoryjson(cJSON *item,struct LP_utxoinfo *utxo)
jaddstr(item,"swap","in progress");
if ( utxo->T.spentflag != 0 )
jaddnum(item,"spent",utxo->T.spentflag);
jaddnum(item,"session",utxo->T.sessionid);
return(item);
}
@ -272,24 +280,34 @@ cJSON *LP_utxojson(struct LP_utxoinfo *utxo)
cJSON *item = cJSON_CreateObject();
item = LP_inventoryjson(item,utxo);
jaddbits256(item,"pubkey",utxo->pubkey);
jaddnum(item,"profit",utxo->S.profitmargin);
//jaddnum(item,"profit",utxo->S.profitmargin);
jaddstr(item,"base",utxo->coin);
jaddstr(item,"script",utxo->spendscript);
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;
if ( (val= LP_txvalue(destaddr,symbol,txid,vout)) >= satoshis )
{
threshold = (iambob != 0) ? LP_DEPOSITSATOSHIS(satoshis) : LP_DEXFEE(satoshis);
if ( (val2= LP_txvalue(destaddr2,symbol,txid2,vout2)) >= threshold )
if ( coin != 0 && IAMLP != 0 && coin->inactive != 0 )
bypass = 1;
if ( bypass != 0 )
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);
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));
else
{
@ -297,8 +315,36 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol
*val2p = val2;
return(1);
}
} else printf("no val2\n");
} else printf("mismatched %s txid value %.8f < %.8f\n",symbol,dstr(val),dstr(satoshis));
} // else printf("no val2\n");
}
// char str[65],str2[65]; printf("spent.%d %s txid or value %.8f < %.8f or val2 %.8f < %.8f, %s/v%d %s/v%d or < 10x txfee %.8f\n",iambob,symbol,dstr(val),dstr(satoshis),dstr(val2),dstr(threshold),bits256_str(str,txid),vout,bits256_str(str2,txid2),vout2,dstr(txfee));
/*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;
*val2p = val2;
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)
{
int32_t i,firsti,n; 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;
int32_t i,n,m; uint64_t val,val2; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray();
//n = mypeer != 0 ? mypeer->numutxos : 0;
if ( lastn <= 0 )
lastn = LP_PROPAGATION_SLACK * 2;
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)
{
//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 )
{
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);
continue;
} else jaddi(utxosjson,LP_utxojson(utxo));
}
}
if ( (n= cJSON_GetArraySize(utxosjson)) > lastn )
{
m = n - lastn;
for (i=0; i<m; i++)
cJSON_DeleteItemFromArray(utxosjson,0);
}
return(jprint(utxosjson,1));
}
@ -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 *utxo,*tmp,*bestutxo = 0;
uint64_t srcvalue,srcvalue2; struct LP_utxoinfo *utxo,*tmp,*bestutxo = 0;
if ( symbol == 0 || destsatoshis == 0 )
{
printf("LP_utxo_bestfit error symbol.%p %.8f\n",symbol,dstr(destsatoshis));
return(0);
}
HASH_ITER(hh,LP_utxoinfos[0],utxo,tmp)
{
//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);
if ( strcmp(symbol,utxo->coin) == 0 && LP_isavailable(utxo) > 0 && LP_ismine(utxo) > 0 )
//char str[65]; printf("s%u %d [%.8f vs %.8f] check %s.%s avail.%d ismine.%d >= %d\n",utxo->T.spentflag,LP_iseligible(&srcvalue,&srcvalue2,utxo->iambob,symbol,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,utxo->fee.txid,utxo->fee.vout),dstr(destsatoshis),dstr(utxo->S.satoshis),utxo->coin,bits256_str(str,utxo->payment.txid),LP_isavailable(utxo) > 0,LP_ismine(utxo) > 0,utxo->S.satoshis >= destsatoshis);
if ( strcmp(symbol,utxo->coin) != 0 )
continue;
if ( LP_isavailable(utxo) > 0 && LP_ismine(utxo) > 0 )
{
if ( utxo->S.satoshis >= destsatoshis && (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;
} //else printf("skip alice utxo %.8f vs dest %.8f\n",dstr(utxo->S.satoshis),dstr(destsatoshis));
}
}
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)
{
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);
if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 )
LP_mypeer->numutxos--;
if ( LP_mypubsock >= 0 )
/*if ( LP_mypubsock >= 0 )
{
argjson = cJSON_CreateObject();
jaddstr(argjson,"method","checktxid");
@ -385,8 +445,8 @@ void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector)
jaddnum(argjson,"checkvout",u.vout);
}
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)
@ -420,40 +480,96 @@ char *LP_spentcheck(cJSON *argjson)
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)
{
bits256 zero; char *msg;
if ( LP_isunspent(utxo) > 0 )
{
memset(zero.bytes,0,sizeof(zero));
msg = jprint(LP_utxojson(utxo),1);
LP_broadcast_message(LP_mypubsock,utxo->coin,"",zero,msg);
}
/*struct LP_peerinfo *peer,*tmp; cJSON *retjson; char *retstr; int32_t n = 0;
HASH_ITER(hh,LP_peerinfos,peer,tmp)
{
if ( (retstr= issue_LP_notifyutxo(peer->ipaddr,peer->port,utxo)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( jobj(retjson,"error") == 0 )
{
utxo->T.lasttime = (uint32_t)time(NULL);
n++;
}
free_json(retjson);
}
free(retstr);
}
//if ( utxo->T.lasttime != 0 )
// return(0);
}
return(n);*/
}
struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bits256 txid,int32_t vout,int64_t value,bits256 txid2,int32_t vout2,int64_t value2,char *spendscript,char *coinaddr,bits256 pubkey,char *gui,uint32_t sessionid)
{
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;
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 )
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("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);
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);
}
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);
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 )
tmpsatoshis = (((value2 - bigtxfee) / 9) << 3);
if ( value2 > 2*txfee )
tmpsatoshis = (((value2 - 2*txfee) / 9) << 3);
else return(0);
} else tmpsatoshis = value;
} else tmpsatoshis = (value - txfee);
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);
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));
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 )
printf("%.8f %.8f %s iambob.%d %s utxoadd.(%.8f %.8f) %s %s\n",dstr(val),dstr(val2),coinaddr,iambob,symbol,dstr(value),dstr(value2),bits256_str(str,txid),bits256_str(str2,txid2));
dispflag = 1;
if ( (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);
}
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++;
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 )
utxo->T.spentflag = (uint32_t)time(NULL);
printf("original utxo pair not valid\n");
if ( dispflag != 0 )
printf("error on subsequent utxo iambob.%d %.8f %.8f add.(%s %s) when.(%s %s) %d %d %d %d %d %d %d %d %d %d %d pubkeys.(%s vs %s)\n",iambob,dstr(val),dstr(val2),bits256_str(str,txid),bits256_str(str2,txid2),bits256_str(str3,utxo->payment.txid),bits256_str(str4,utxo->deposit.txid),bits256_cmp(txid,utxo->payment.txid) != 0,bits256_cmp(txid2,u.txid) != 0,vout != utxo->payment.vout,tmpsatoshis != utxo->S.satoshis,vout2 != u.vout,value2 != u.value,strcmp(symbol,utxo->coin) != 0,strcmp(spendscript,utxo->spendscript) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,bits256_cmp(pubkey,utxo->pubkey) != 0,value != utxo->payment.value,bits256_str(str5,pubkey),bits256_str(str6,utxo->pubkey));
utxo = 0;
}
}
else if ( profitmargin > SMALLVAL )
utxo->S.profitmargin = profitmargin;
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);
}
}
utxo = calloc(1,sizeof(*utxo));
utxo->S.profitmargin = profitmargin;
//utxo->S.profitmargin = profitmargin;
utxo->pubkey = pubkey;
safecopy(utxo->gui,gui,sizeof(utxo->gui));
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->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);
HASH_ADD_KEYPTR(hh,LP_utxoinfos[iambob],utxo->key,sizeof(utxo->key),utxo);
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);
if ( iambob != 0 )
{
if ( mypubsock >= 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 )
if ( LP_mypeer != 0 )
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);
}
@ -535,7 +661,12 @@ struct LP_utxoinfo *LP_utxoaddjson(int32_t iambob,int32_t pubsock,cJSON *argjson
return(0);
}
portable_mutex_lock(&LP_UTXOmutex);
utxo = LP_utxoadd(iambob,pubsock,jstr(argjson,"coin"),jbits256(argjson,"txid"),jint(argjson,"vout"),j64bits(argjson,"value"),jbits256(argjson,"txid2"),jint(argjson,"vout2"),j64bits(argjson,"value2"),jstr(argjson,"script"),jstr(argjson,"address"),jbits256(argjson,"pubkey"),jdouble(argjson,"profit"),jstr(argjson,"gui"));
utxo = LP_utxoadd(iambob,pubsock,jstr(argjson,"coin"),jbits256(argjson,"txid"),jint(argjson,"vout"),j64bits(argjson,"value"),jbits256(argjson,"txid2"),jint(argjson,"vout2"),j64bits(argjson,"value2"),jstr(argjson,"script"),jstr(argjson,"address"),jbits256(argjson,"pubkey"),jstr(argjson,"gui"),juint(argjson,"session"));
if ( LP_ismine(utxo) > 0 && utxo->T.lasttime == 0 )
{
utxo->T.lasttime = (uint32_t)time(NULL);
printf("set lasttime!\n");
}
portable_mutex_unlock(&LP_UTXOmutex);
return(utxo);
}
@ -559,18 +690,14 @@ int32_t LP_utxosparse(char *destipaddr,uint16_t destport,char *retstr,uint32_t n
subport = argport + 2;
argipbits = (uint32_t)calc_ipbits(argipaddr);
if ( (peer= LP_peerfind(argipbits,argport)) == 0 )
peer = LP_addpeer(0,-1,argipaddr,argport,pushport,subport,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 )
{
txid = jbits256(item,"txid");
//printf("parse.(%s)\n",jprint(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;
}
}
}
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);
}
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;
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 = "";
//printf("utxo query.(%s)\n",destipaddr);
if ( IAMLP != 0 )
retstr = issue_LP_getutxos(destipaddr,destport,coin,lastn,myipaddr,myport,myprofit,mypeer != 0 ? mypeer->numpeers : 0,mypeer != 0 ? mypeer->numutxos : 0);
else retstr = issue_LP_clientgetutxos(destipaddr,destport,coin,100);
retstr = issue_LP_getutxos(destipaddr,destport,coin,lastn,myipaddr,myport,mypeer != 0 ? mypeer->numpeers : 0,maxentries);
else retstr = issue_LP_clientgetutxos(destipaddr,destport,coin,maxentries);
if ( retstr != 0 )
{
now = (uint32_t)time(NULL);
@ -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)
{
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();
if ( LP_mypeer != 0 )
myipaddr = LP_mypeer->ipaddr;
else myipaddr = "127.0.0.1";
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 )
{
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));
}
//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);
@ -650,14 +788,15 @@ int32_t LP_maxvalue(uint64_t *values,int32_t n)
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);
for (i=0; i<n; i++)
{
dist = (values[i] - targetval);
if ( dist < 0 && -dist < values[i]/10 )
if ( iambob != 0 && dist < 0 && -dist < values[i]/10 )
dist = -dist;
//printf("(%.8f %.8f %.8f).%d ",dstr(values[i]),dstr(dist),dstr(mindist),mini);
if ( dist >= 0 && dist < mindist )
{
mini = i;
@ -667,9 +806,9 @@ int32_t LP_nearestvalue(uint64_t *values,int32_t n,uint64_t targetval)
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 )
{
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);
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 )
{
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);
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;
else used++;
} else used++;
//printf("%.8f ",dstr(satoshis));
}
//printf("array.%d\n",n);
while ( used < n-1 )
{
//for (i=0; i<n; i++)
// printf("%.8f ",dstr(values[i]));
//printf("used.%d of n.%d\n",used,n);
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];
values[i] = 0, used++;
if ( iambob == 0 )
targetval = (depositval / 776) + 100000;
else targetval = (depositval / 9) * 8 + 100000;
//printf("i.%d %.8f target %.8f\n",i,dstr(depositval),dstr(targetval));
if ( (i= LP_nearestvalue(values,n,targetval)) < 0 && iambob != 0 )
targetval /= 4;
if ( (i= LP_nearestvalue(values,n,targetval)) >= 0 )
targetval = (depositval / 776) + txfee;
else targetval = (depositval / 9) * 8 + 2*txfee;
if ( depositval < (1+LP_MINSIZE_TXFEEMULT)*txfee )
continue;
//printf("iambob.%d i.%d %.8f target %.8f\n",iambob,i,dstr(depositval),dstr(targetval));
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);
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);
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
{
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);
total += value;
}
}
} else printf("scriptmismatch.(%s) vs %s\n",script,jprint(item,0));
} //else printf("nothing near i.%d\n",i);
} else break;
}
if ( iambob == 1 )
@ -756,26 +910,39 @@ uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypr
bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguana_info *coin,char *passphrase,char *wifstr)
{
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 )
conv_NXTpassword(privkey.bytes,pubkeyp->bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase));
else
{
privkey = iguana_wif2privkey(wifstr);
//printf("WIF.(%s) -> %s\n",wifstr,bits256_str(str,privkey));
bitcoin_wif2priv(coin->wiftaddr,&tmptype,&privkey,wifstr);
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 )
{
coin->counter++;
bitcoin_priv2wif(tmpstr,privkey,coin->wiftype);
bitcoin_priv2wif(coin->wiftaddr,tmpstr,privkey,coin->wiftype);
bitcoin_addr2rmd160(coin->taddr,&tmptype,rmd160,coin->smartaddr);
LP_privkeyadd(privkey,rmd160);
if ( 0 && (coin->pubtype != 60 || strcmp(coin->symbol,"KMD") == 0) )
printf("%s (%s) %d wif.(%s) (%s)\n",coin->symbol,coin->smartaddr,coin->pubtype,tmpstr,passphrase);
if ( counter++ == 0 )
{
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));
userpub = curve25519(userpass,curve25519_basepoint9());
printf("userpass.(%s)\n",bits256_str(USERPASS,userpub));
@ -789,8 +956,9 @@ bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguan
}
}
}
LP_mypubkey = *pubkeyp = curve25519(privkey,curve25519_basepoint9());
//printf("privkey.(%s) -> LP_mypubkey.(%s)\n",bits256_str(str,privkey),bits256_str(str2,LP_mypubkey));
LP_mypub25519 = *pubkeyp = curve25519(privkey,curve25519_basepoint9());
LP_mypriv25519 = privkey;
//printf("privkey.(%s) -> LP_mypub25519.(%s)\n",bits256_str(str,privkey),bits256_str(str2,LP_mypub25519));
return(privkey);
}
@ -805,7 +973,7 @@ void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase,int32_t inito
if ( bits256_nonz(privkey) == 0 || coin->smartaddr[0] == 0 )
privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,coin,passphrase,"");
if ( coin->inactive == 0 && initonly == 0 )
LP_privkey_init(pubsock,coin,privkey,pubkey,pubkey33);
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}"

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 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
echo now in dexscripts directory where you can make customized scripts that wont conflict with git pull
#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

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

15
iguana/exchanges/mm.c

@ -24,7 +24,7 @@
#include <stdint.h>
#include "OS_portable.h"
#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"
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));
}*/
/*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];
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);
return(issue_curl(url));
}*/
@ -790,15 +790,20 @@ void LP_main(void *ptr)
if ( (passphrase= jstr(argjson,"passphrase")) != 0 )
{
profitmargin = jdouble(argjson,"profitmargin");
LPinit(7779,7780,7781,profitmargin,passphrase,jint(argjson,"client"),jstr(argjson,"userhome"),argjson);
LP_profitratio += profitmargin;
LPinit(7779,7780,7781,7782,passphrase,jint(argjson,"client"),jstr(argjson,"userhome"),argjson);
}
}
int main(int argc, const char * argv[])
{
char *base,*rel,*name,*exchange,*apikey,*apisecret,*blocktrail,*retstr,*baseaddr,*reladdr,*passphrase;
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;
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 ( (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}"

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

25
iguana/exchanges/stats.c

@ -21,11 +21,12 @@
#include <stdio.h>
#include <stdint.h>
#include "OS_portable.h"
#include "../../crypto777/OS_portable.h"
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define STATS_DESTDIR "/var/www/html"
#define STATS_DEST "/var/www/html/DEXstats.json"
#include "DEXstats.h"
char *stats_JSON(void *ctx,char *myipaddr,int32_t mypubsock,cJSON *argjson,char *remoteaddr,uint16_t port);
#ifndef WIN32
#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)
{
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);
if ( ctx == 0 )
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 )
jaddstr(argjson,"userpass",userpass);
//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 )
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));
if ( userpass != 0 && jstr(arg,"userpass") == 0 )
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(json);
@ -558,7 +559,7 @@ void stats_rpcloop(void *args)
uint16_t port; char filetype[128],content_type[128];
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;
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 )
port = 7779;
if ( jsonbuf == 0 )
@ -665,9 +666,11 @@ void stats_rpcloop(void *args)
if ( retstr != 0 )
{
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 ( retstr == 0 )
retstr = clonestr("{}");
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));
response[0] = '\0';
@ -677,6 +680,7 @@ void stats_rpcloop(void *args)
if ( retstr != space )
free(retstr);
retstr = response;
//printf("RET.(%s)\n",retstr);
}
remains = (int32_t)strlen(retstr);
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)
{
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];
//static bits256 zeroes;
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[3],sizeof(valuesize),&valuesize);
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)
{
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 )
{
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 )
errs++;
if ( 0 && matched != 0 )
if ( (0) && matched != 0 )
{
int32_t i; for (i=0; i<olen; 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(symbol,"KMD");
}
return(n);
}
char *stats_update(FILE *logfp,char *destdir,char *statefname,char *komodofname)

0
iguana/exchanges/tmp/.tmpmarker

19
iguana/iguana777.c

@ -105,25 +105,6 @@ void iguana_recvalloc(struct iguana_info *coin,int32_t 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)
{
int32_t duration; double metric = addr->recvblocks * addr->recvtotal;

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_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);
if ( maxsize-len <= 0 )
return(-1);
@ -671,7 +671,7 @@ int32_t iguana_rwtx(struct supernet_info *myinfo,uint8_t zcash,int32_t rwflag,st
return(-1);
}
//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);
for (i=0; i<msg->tx_out; i++)
{

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 )
{
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();
return(0);
}
@ -1126,7 +1126,7 @@ int32_t iguana_ramchain_verify(struct iguana_info *coin,struct iguana_ramchain *
return(-3);
}
}
for (k=0; k<t->numvouts; k++,ramchain->H.unspentind++)
for (k=0; k<t->numvouts; k++)
{
u = &Ux[ramchain->H.unspentind];
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);
return(-9);
}
ramchain->H.unspentind++;
}
}
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 )
{
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);
}
ramchain->H.unspentind++;
}
}
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++)
{
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 )
{
@ -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 )
@ -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");
return(-1);
}
if ( rdata->firsti != 1 )
printf("unexpected firsti.%d %s.%d\n",rdata->firsti,coin->symbol,bundlei);
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
@ -1899,14 +1904,15 @@ long iguana_ramchain_data(struct supernet_info *myinfo,struct iguana_info *coin,
}
if ( block != 0 )
block->fpipbits = 1;
for (i=0; i<txn_count; i++,ramchain->H.txidind++)
for (i=0; i<txn_count; 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);
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);
break;
if ( coin->chain->zcash == 0 )
printf("strange tx without any inputs or outputs? ht.%d\n",bp->bundleheight);
continue;
}
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);
}
ramchain->H.spendind += tx->tx_in;
ramchain->H.txidind++;
}
//printf("scriptoffset.%d after %d txids\n",ramchain->H.scriptoffset,txn_count);
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];
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);
}
ramchain->H.txidind++;
}
rdata->prevhash2 = origtxdata->zblock.RO.prev_block;
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
{
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];
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;
struct OS_memspace HASHMEM; int32_t err,j,num,bundlei,firsti= 1,retval = -1;
memset(&HASHMEM,0,sizeof(HASHMEM));
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;
R = mycalloc('s',bp->n,sizeof(*R));
ptrs = mycalloc('w',bp->n,sizeof(*ptrs));

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();
jaddnum(json,"version",txversion);
if ( locktime == 0 && strcmp(symbol,"KMD") == 0 )
locktime = (uint32_t)time(NULL);
locktime = (uint32_t)time(NULL) - 55;
jaddnum(json,"locktime",locktime);
if ( isPoS != 0 )
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
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

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
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
echo "making $TMP_DIR"
binaries=("iguana")
binaries=("iguana" "marketmaker")
for binary in "${binaries[@]}";
do
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
DYLIBS=`otool -L $TMP_DIR/$binary | grep "/usr/local" | awk -F' ' '{ print $1 }'`

Loading…
Cancel
Save