From ac3d4780316697a99c16f719b9b5cb1c09df38e6 Mon Sep 17 00:00:00 2001 From: jl777 Date: Fri, 2 Jun 2017 16:26:02 +0300 Subject: [PATCH] Test --- iguana/exchanges/LP_bitcoin.c | 307 +++++++++++ iguana/exchanges/LP_coins.c | 196 +++++++ iguana/exchanges/LP_commands.c | 35 +- iguana/exchanges/LP_include.h | 375 ++----------- iguana/exchanges/LP_nativeDEX.c | 839 +---------------------------- iguana/exchanges/LP_network.c | 229 -------- iguana/exchanges/LP_peers.c | 188 +++++++ iguana/exchanges/LP_prices.c | 162 +++++- iguana/exchanges/LP_remember.c | 139 ----- iguana/exchanges/LP_rpc.c | 50 +- iguana/exchanges/LP_statemachine.c | 311 +++++++++++ iguana/exchanges/LP_transaction.c | 31 -- iguana/exchanges/LP_utxos.c | 327 +++++++++++ iguana/exchanges/mm.c | 2 +- 14 files changed, 1617 insertions(+), 1574 deletions(-) create mode 100644 iguana/exchanges/LP_coins.c create mode 100644 iguana/exchanges/LP_peers.c create mode 100644 iguana/exchanges/LP_utxos.c diff --git a/iguana/exchanges/LP_bitcoin.c b/iguana/exchanges/LP_bitcoin.c index 4b6309ac7..c7ee8b218 100644 --- a/iguana/exchanges/LP_bitcoin.c +++ b/iguana/exchanges/LP_bitcoin.c @@ -18,6 +18,313 @@ // marketmaker // +union iguana_stacknum { int32_t val; int64_t val64; uint8_t rmd160[20]; bits256 hash2; uint8_t pubkey[33]; uint8_t sig[74]; }; +struct iguana_stackdata { uint8_t *data; uint16_t size; union iguana_stacknum U; }; + +char *bitcoin_base58encode(char *coinaddr,uint8_t *data,int32_t datalen); +int32_t bitcoin_base58decode(uint8_t *data,char *coinaddr); + +#define IGUANA_MAXSCRIPTSIZE 10001 +#define IGUANA_SEQUENCEID_FINAL 0xfffffffe + +#define IGUANA_SCRIPT_NULL 0 +#define IGUANA_SCRIPT_76AC 1 +#define IGUANA_SCRIPT_76A988AC 2 +#define IGUANA_SCRIPT_P2SH 3 +#define IGUANA_SCRIPT_OPRETURN 4 +#define IGUANA_SCRIPT_3of3 5 +#define IGUANA_SCRIPT_2of3 6 +#define IGUANA_SCRIPT_1of3 7 +#define IGUANA_SCRIPT_2of2 8 +#define IGUANA_SCRIPT_1of2 9 +#define IGUANA_SCRIPT_MSIG 10 +#define IGUANA_SCRIPT_DATA 11 +#define IGUANA_SCRIPT_AC 12 +#define IGUANA_SCRIPT_1of1 13 +#define IGUANA_SCRIPT_STRANGE 15 + +#define MAX_SCRIPT_ELEMENT_SIZE 520 +#define MAX_OPS_PER_SCRIPT 201 // Maximum number of non-push operations per script +#define MAX_PUBKEYS_PER_MULTISIG 20 // Maximum number of public keys per multisig + +#define IGUANA_MAXSTACKITEMS ((int32_t)(IGUANA_MAXSCRIPTSIZE / sizeof(uint32_t))) +#define IGUANA_MAXSTACKDEPTH 128 +struct iguana_interpreter +{ + int32_t active,ifdepth,elsedepth,codeseparator,stackdepth,altstackdepth,maxstackdepth; + int8_t lastpath[IGUANA_MAXSTACKDEPTH]; + cJSON *logarray; + struct iguana_stackdata stack[]; +}; +static struct bitcoin_opcode { UT_hash_handle hh; uint8_t opcode,flags,stackitems; int8_t extralen; } *OPTABLE; static char *OPCODES[0x100]; static int32_t OPCODELENS[0x100]; + +#define SIGHASH_ALL 1 +#define SIGHASH_NONE 2 +#define SIGHASH_SINGLE 3 +#define SIGHASH_ANYONECANPAY 0x80 + +#define SCRIPT_OP_NOP 0x00 +#define SCRIPT_OP_TRUE 0x51 +#define SCRIPT_OP_2 0x52 +#define SCRIPT_OP_3 0x53 +#define SCRIPT_OP_4 0x54 +#define SCRIPT_OP_IF 0x63 +#define SCRIPT_OP_ELSE 0x67 +#define SCRIPT_OP_RETURN 0x6a +#define SCRIPT_OP_DUP 0x76 +#define SCRIPT_OP_ENDIF 0x68 +#define SCRIPT_OP_DROP 0x75 +#define SCRIPT_OP_EQUALVERIFY 0x88 +#define SCRIPT_OP_SHA256 0xa8 +#define SCRIPT_OP_HASH160 0xa9 + +#define SCRIPT_OP_EQUAL 0x87 +#define SCRIPT_OP_CHECKSIG 0xac +#define SCRIPT_OP_CHECKMULTISIG 0xae +#define SCRIPT_OP_CHECKSEQUENCEVERIFY 0xb2 +#define SCRIPT_OP_CHECKLOCKTIMEVERIFY 0xb1 +#define IGUANA_OP_0 0x00 +#define IGUANA_OP_PUSHDATA1 0x4c +#define IGUANA_OP_PUSHDATA2 0x4d +#define IGUANA_OP_PUSHDATA4 0x4e +#define IGUANA_OP_1NEGATE 0x4f +#define IGUANA_OP_1 0x51 +#define IGUANA_OP_16 0x60 +#define IGUANA_OP_NOP 0x61 +#define IGUANA_OP_IF 0x63 +#define IGUANA_OP_NOTIF 0x64 +#define IGUANA_OP_ELSE 0x67 +#define IGUANA_OP_ENDIF 0x68 +#define IGUANA_OP_VERIFY 0x69 +#define IGUANA_OP_RETURN 0x6a + +#define IGUANA_OP_TOALTSTACK 0x6b +#define IGUANA_OP_FROMALTSTACK 0x6c +#define IGUANA_OP_2DROP 0x6d +#define IGUANA_OP_2DUP 0x6e +#define IGUANA_OP_3DUP 0x6f +#define IGUANA_OP_2OVER 0x70 +#define IGUANA_OP_2ROT 0x71 +#define IGUANA_OP_2SWAP 0x72 +#define IGUANA_OP_IFDUP 0x73 +#define IGUANA_OP_DEPTH 0x74 +#define IGUANA_OP_DROP 0x75 +#define IGUANA_OP_DUP 0x76 +#define IGUANA_OP_NIP 0x77 +#define IGUANA_OP_OVER 0x78 +#define IGUANA_OP_PICK 0x79 +#define IGUANA_OP_ROLL 0x7a +#define IGUANA_OP_ROT 0x7b +#define IGUANA_OP_SWAP 0x7c +#define IGUANA_OP_TUCK 0x7d + +#define IGUANA_OP_EQUAL 0x87 +#define IGUANA_OP_EQUALVERIFY 0x88 + +#define IGUANA_OP_1ADD 0x8b +#define IGUANA_OP_1SUB 0x8c +#define IGUANA_OP_NEGATE 0x8f +#define IGUANA_OP_ABS 0x90 +#define IGUANA_OP_NOT 0x91 +#define IGUANA_OP_0NOTEQUAL 0x92 +#define IGUANA_OP_ADD 0x93 +#define IGUANA_OP_SUB 0x94 + +#define IGUANA_OP_BOOLAND 0x9a +#define IGUANA_OP_BOOLOR 0x9b +#define IGUANA_OP_NUMEQUAL 0x9c +#define IGUANA_OP_NUMEQUALVERIFY 0x9d +#define IGUANA_OP_NUMNOTEQUAL 0x9e +#define IGUANA_OP_LESSTHAN 0x9f +#define IGUANA_OP_GREATERTHAN 0xa0 +#define IGUANA_OP_LESSTHANOREQUAL 0xa1 +#define IGUANA_OP_GREATERTHANOREQUAL 0xa2 +#define IGUANA_OP_MIN 0xa3 +#define IGUANA_OP_MAX 0xa4 +#define IGUANA_OP_WITHIN 0xa5 + +#define IGUANA_OP_RIPEMD160 0xa6 +#define IGUANA_OP_SHA1 0xa7 +#define IGUANA_OP_SHA256 0xa8 +#define IGUANA_OP_HASH160 0xa9 +#define IGUANA_OP_HASH256 0xaa +#define IGUANA_OP_CODESEPARATOR 0xab +#define IGUANA_OP_CHECKSIG 0xac +#define IGUANA_OP_CHECKSIGVERIFY 0xad +#define IGUANA_OP_CHECKMULTISIG 0xae +#define IGUANA_OP_CHECKMULTISIGVERIFY 0xaf + +#define IGUANA_OP_NOP1 0xb0 +#define IGUANA_OP_CHECKLOCKTIMEVERIFY 0xb1 +#define IGUANA_OP_CHECKSEQUENCEVERIFY 0xb2 +#define IGUANA_OP_NOP10 0xb9 + +#define IGUANA_OP_COMBINEPUBKEYS 0xc0 +#define IGUANA_OP_CHECKSCHNORR 0xc1 +#define IGUANA_OP_CHECKSCHNORRVERIFY 0xc2 + +// https://github.com/TierNolan/bips/blob/cpkv/bip-cprkv.mediawiki +#define IGUANA_OP_CHECKPRIVATEKEY 0xc3 +#define IGUANA_OP_CHECKPRIVATEKEYVERIFY 0xc4 + +#define IGUANA_NOPFLAG 1 +#define IGUANA_ALWAYSILLEGAL 2 +#define IGUANA_EXECUTIONILLEGAL 4 +#define IGUANA_POSTVERIFY 8 +#define IGUANA_CRYPTOFLAG 16 +#define IGUANA_MATHFLAG 32 +#define IGUANA_CONTROLFLAG 64 +#define IGUANA_STACKFLAG 128 + +enum opcodetype +{ + // push value + OP_0 = 0x00, + OP_FALSE = OP_0, + OP_PUSHDATA1 = 0x4c, + OP_PUSHDATA2 = 0x4d, + OP_PUSHDATA4 = 0x4e, + OP_1NEGATE = 0x4f, + OP_RESERVED = 0x50, + OP_1 = 0x51, + OP_TRUE=OP_1, + OP_2 = 0x52, + OP_3 = 0x53, + OP_4 = 0x54, + OP_5 = 0x55, + OP_6 = 0x56, + OP_7 = 0x57, + OP_8 = 0x58, + OP_9 = 0x59, + OP_10 = 0x5a, + OP_11 = 0x5b, + OP_12 = 0x5c, + OP_13 = 0x5d, + OP_14 = 0x5e, + OP_15 = 0x5f, + OP_16 = 0x60, + + // control + OP_NOP = 0x61, + OP_VER = 0x62, + OP_IF = 0x63, + OP_NOTIF = 0x64, + OP_VERIF = 0x65, + OP_VERNOTIF = 0x66, + OP_ELSE = 0x67, + OP_ENDIF = 0x68, + OP_VERIFY = 0x69, + OP_RETURN = 0x6a, + + // stack ops + OP_TOALTSTACK = 0x6b, + OP_FROMALTSTACK = 0x6c, + OP_2DROP = 0x6d, + OP_2DUP = 0x6e, + OP_3DUP = 0x6f, + OP_2OVER = 0x70, + OP_2ROT = 0x71, + OP_2SWAP = 0x72, + OP_IFDUP = 0x73, + OP_DEPTH = 0x74, + OP_DROP = 0x75, + OP_DUP = 0x76, + OP_NIP = 0x77, + OP_OVER = 0x78, + OP_PICK = 0x79, + OP_ROLL = 0x7a, + OP_ROT = 0x7b, + OP_SWAP = 0x7c, + OP_TUCK = 0x7d, + + // splice ops + OP_CAT = 0x7e, + OP_SUBSTR = 0x7f, + OP_LEFT = 0x80, + OP_RIGHT = 0x81, + OP_SIZE = 0x82, + + // bit logic + OP_INVERT = 0x83, + OP_AND = 0x84, + OP_OR = 0x85, + OP_XOR = 0x86, + OP_EQUAL = 0x87, + OP_EQUALVERIFY = 0x88, + OP_RESERVED1 = 0x89, + OP_RESERVED2 = 0x8a, + + // numeric + OP_1ADD = 0x8b, + OP_1SUB = 0x8c, + OP_2MUL = 0x8d, + OP_2DIV = 0x8e, + OP_NEGATE = 0x8f, + OP_ABS = 0x90, + OP_NOT = 0x91, + OP_0NOTEQUAL = 0x92, + + OP_ADD = 0x93, + OP_SUB = 0x94, + OP_MUL = 0x95, + OP_DIV = 0x96, + OP_MOD = 0x97, + OP_LSHIFT = 0x98, + OP_RSHIFT = 0x99, + + OP_BOOLAND = 0x9a, + OP_BOOLOR = 0x9b, + OP_NUMEQUAL = 0x9c, + OP_NUMEQUALVERIFY = 0x9d, + OP_NUMNOTEQUAL = 0x9e, + OP_LESSTHAN = 0x9f, + OP_GREATERTHAN = 0xa0, + OP_LESSTHANOREQUAL = 0xa1, + OP_GREATERTHANOREQUAL = 0xa2, + OP_MIN = 0xa3, + OP_MAX = 0xa4, + + OP_WITHIN = 0xa5, + + // crypto + OP_RIPEMD160 = 0xa6, + OP_SHA1 = 0xa7, + OP_SHA256 = 0xa8, + OP_HASH160 = 0xa9, + OP_HASH256 = 0xaa, + OP_CODESEPARATOR = 0xab, + OP_CHECKSIG = 0xac, + OP_CHECKSIGVERIFY = 0xad, + OP_CHECKMULTISIG = 0xae, + OP_CHECKMULTISIGVERIFY = 0xaf, + + // expansion + OP_NOP1 = 0xb0, + OP_CHECKLOCKTIMEVERIFY = 0xb1, + OP_CHECKSEQUENCEVERIFY = 0xb2, + OP_NOP4 = 0xb3, + OP_NOP5 = 0xb4, + OP_NOP6 = 0xb5, + OP_NOP7 = 0xb6, + OP_NOP8 = 0xb7, + OP_NOP9 = 0xb8, + OP_NOP10 = 0xb9, + + OP_COMBINEPUBKEYS = 0xc0, + OP_CHECKSCHNORR = 0xc1, + OP_CHECKSCHNORRVERIFY = 0xc2, + OP_CHECKPRIVATEKEY = 0xc3, + OP_CHECKPRIVATEKEYVERIFY = 0xc4, + + // template matching params + //OP_SMALLINTEGER = 0xfa, + //OP_PUBKEYS = 0xfb, + //OP_PUBKEYHASH = 0xfd, + //OP_PUBKEY = 0xfe, + + OP_INVALIDOPCODE = 0xff, +}; + struct { bits256 privkey; uint8_t rmd160[20]; } LP_privkeys[100]; int32_t LP_numprivkeys; bits256 LP_privkeyfind(uint8_t rmd160[20]) diff --git a/iguana/exchanges/LP_coins.c b/iguana/exchanges/LP_coins.c new file mode 100644 index 000000000..d3f136c00 --- /dev/null +++ b/iguana/exchanges/LP_coins.c @@ -0,0 +1,196 @@ + +/****************************************************************************** + * 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_coins.c +// marketmaker +// + + +char *parse_conf_line(char *line,char *field) +{ + line += strlen(field); + for (; *line!='='&&*line!=0; line++) + break; + if ( *line == 0 ) + return(0); + if ( *line == '=' ) + line++; + while ( line[strlen(line)-1] == '\r' || line[strlen(line)-1] == '\n' || line[strlen(line)-1] == ' ' ) + line[strlen(line)-1] = 0; + //printf("LINE.(%s)\n",line); + _stripwhite(line,0); + return(clonestr(line)); +} + +void LP_userpassfp(char *username,char *password,FILE *fp) +{ + char *rpcuser,*rpcpassword,*str,line[8192]; + rpcuser = rpcpassword = 0; + username[0] = password[0] = 0; + while ( fgets(line,sizeof(line),fp) != 0 ) + { + if ( line[0] == '#' ) + continue; + //printf("line.(%s) %p %p\n",line,strstr(line,(char *)"rpcuser"),strstr(line,(char *)"rpcpassword")); + if ( (str= strstr(line,(char *)"rpcuser")) != 0 ) + rpcuser = parse_conf_line(str,(char *)"rpcuser"); + else if ( (str= strstr(line,(char *)"rpcpassword")) != 0 ) + rpcpassword = parse_conf_line(str,(char *)"rpcpassword"); + } + if ( rpcuser != 0 && rpcpassword != 0 ) + { + strcpy(username,rpcuser); + strcpy(password,rpcpassword); + } + //printf("rpcuser.(%s) rpcpassword.(%s) KMDUSERPASS.(%s) %u\n",rpcuser,rpcpassword,KMDUSERPASS,port); + if ( rpcuser != 0 ) + free(rpcuser); + if ( rpcpassword != 0 ) + free(rpcpassword); +} + +void LP_statefname(char *fname,char *symbol,char *assetname,char *str) +{ + sprintf(fname,"%s",LP_getdatadir()); +#ifdef WIN32 + strcat(fname,"\\"); +#else + strcat(fname,"/"); +#endif + if ( strcmp(symbol,"BTC") == 0 ) + strcat(fname,".bitcoin"); + else if ( strcmp(symbol,"LTC") == 0 ) + strcat(fname,".litecoin"); + else + { + strcat(fname,".komodo"); + if ( strcmp(symbol,"KMD") != 0 ) + { +#ifdef WIN32 + strcat(fname,"\\"); +#else + strcat(fname,"/"); +#endif + strcat(fname,assetname); + } + } +#ifdef WIN32 + strcat(fname,"\\"); +#else + strcat(fname,"/"); +#endif + strcat(fname,str); + printf("LP_statefname.(%s) <- %s %s %s\n",fname,symbol,assetname,str); +} + +int32_t LP_userpass(char *userpass,char *symbol,char *assetname,char *confroot) +{ + FILE *fp; char fname[512],username[512],password[512],confname[16]; + userpass[0] = 0; + sprintf(confname,"%s.conf",confroot); +#ifdef __APPLE__ + confname[0] = toupper(confname[0]); +#endif + LP_statefname(fname,symbol,assetname,confname); + if ( (fp= fopen(fname,"rb")) != 0 ) + { + LP_userpassfp(username,password,fp); + sprintf(userpass,"%s:%s",username,password); + fclose(fp); + return((int32_t)strlen(userpass)); + } + return(-1); +} + +uint32_t LP_assetmagic(char *symbol,uint64_t supply) +{ + uint8_t buf[512]; int32_t len = 0; + if ( strcmp(symbol,"KMD") == 0 ) + return(0x8de4eef9); + len = iguana_rwnum(1,&buf[len],sizeof(supply),(void *)&supply); + strcpy((char *)&buf[len],symbol); + len += strlen(symbol); + return(calc_crc32(0,buf,len)); +} + +uint16_t LP_assetport(uint32_t magic) +{ + if ( magic == 0x8de4eef9 ) + return(7771); + else return(8000 + (magic % 7777)); +} + +uint16_t LP_rpcport(char *symbol,uint64_t supply,uint32_t *magicp) +{ + if ( symbol == 0 || symbol[0] == 0 || strcmp("KMD",symbol) == 0 ) + { + *magicp = 0x8de4eef9; + return(7771); + } + else if ( strcmp("BTC",symbol) == 0 ) + return(8332); + else if ( strcmp("LTC",symbol) == 0 ) + return(9332); + *magicp = LP_assetmagic(symbol,supply); + return(LP_assetport(*magicp)+1); +} + +struct iguana_info *LP_coinfind(char *symbol) +{ + static struct iguana_info *LP_coins; static int32_t LP_numcoins; + struct iguana_info *coin,cdata; int32_t i; uint32_t magic; uint16_t port; + for (i=0; iQ = Q; return(clonestr("{\"result\":\"updated\"}")); - } - else return(clonestr("{\"error\":\"nullptr\"}")); + } else return(clonestr("{\"error\":\"nullptr\"}")); } double LP_query(char *method,struct LP_quoteinfo *qp,char *ipaddr,uint16_t port,char *base,char *rel,bits256 mypub) @@ -213,7 +212,7 @@ double LP_query(char *method,struct LP_quoteinfo *qp,char *ipaddr,uint16_t port, break; } } - usleep(250000); + usleep(100000); } } else printf("no pushsock for peer.%s:%u\n",ipaddr,port); } else printf("cant find/create peer.%s:%u\n",ipaddr,port); @@ -360,6 +359,27 @@ cJSON *LP_bestprice(struct LP_utxoinfo *myutxo,char *base) return(bestitem); } +int32_t LP_priceping(int32_t pubsock,struct LP_utxoinfo *utxo,char *rel,double profitmargin) +{ + double price; uint32_t now; cJSON *retjson; struct LP_quoteinfo Q; char *retstr; + if ( (now= (uint32_t)time(NULL)) > utxo->swappending ) + utxo->swappending = 0; + if ( now > utxo->published+60 && utxo->swappending == 0 && utxo->pair < 0 && utxo->swap == 0 && (price= LP_price(utxo->coin,rel)) != 0. ) + { + price *= (1. + profitmargin); + if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 ) + return(-1); + Q.timestamp = (uint32_t)time(NULL); + retjson = LP_quotejson(&Q); + jaddstr(retjson,"method","quote"); + retstr = jprint(retjson,1); + LP_send(pubsock,retstr,1); + utxo->published = now; + return(0); + } + return(-1); +} + int32_t LP_command(struct LP_peerinfo *mypeer,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin) { char *method,*base,*rel,*retstr,pairstr[512]; cJSON *retjson; double price; bits256 privkey,txid; struct LP_utxoinfo *utxo; int32_t retval = -1,DEXselector = 0; uint64_t destvalue; struct basilisk_request R; struct LP_quoteinfo Q; @@ -368,7 +388,7 @@ int32_t LP_command(struct LP_peerinfo *mypeer,int32_t pubsock,cJSON *argjson,uin txid = jbits256(argjson,"txid"); if ( (utxo= LP_utxofind(txid,jint(argjson,"vout"))) != 0 && strcmp(utxo->ipaddr,mypeer->ipaddr) == 0 && utxo->port == mypeer->port && (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 && strcmp(base,utxo->coin) == 0 ) { - printf("LP_command.(%s)\n",jprint(argjson,0)); + //printf("LP_command.(%s)\n",jprint(argjson,0)); if ( time(NULL) > utxo->swappending ) utxo->swappending = 0; if ( strcmp(method,"price") == 0 || strcmp(method,"request") == 0 ) @@ -399,6 +419,7 @@ int32_t LP_command(struct LP_peerinfo *mypeer,int32_t pubsock,cJSON *argjson,uin else jaddstr(retjson,"method","quote"); retstr = jprint(retjson,1); LP_send(pubsock,retstr,1); + utxo->published = (uint32_t)time(NULL); } else printf("null price\n"); } else printf("swappending.%u pair.%d\n",utxo->swappending,utxo->pair); } @@ -496,7 +517,7 @@ char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port } printf("CMD.(%s)\n",jprint(argjson,0)); if ( strcmp(method,"quote") == 0 || strcmp(method,"reserved") == 0 ) - retstr = LP_quote(argjson); + retstr = LP_quotereceived(argjson); else if ( IAMCLIENT != 0 && strcmp(method,"connected") == 0 ) { int32_t pairsock = -1; char *pairstr; @@ -518,6 +539,8 @@ char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port } else if ( IAMCLIENT == 0 && strcmp(method,"getprice") == 0 ) retstr = LP_pricestr(jstr(argjson,"base"),jstr(argjson,"rel")); + else if ( strcmp(method,"orderbook") == 0 ) + retstr = LP_orderbook(jstr(argjson,"base"),jstr(argjson,"rel")); else if ( IAMCLIENT == 0 && strcmp(method,"getpeers") == 0 ) retstr = LP_peers(); else if ( IAMCLIENT == 0 && strcmp(method,"getutxos") == 0 && (coin= jstr(argjson,"coin")) != 0 ) diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index 568a65511..4cfacff3f 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -21,70 +21,30 @@ #ifndef LP_INCLUDE_H #define LP_INCLUDE_H +#define INSTANTDEX_DECKSIZE 1000 +#define INSTANTDEX_LOCKTIME (3600*2 + 300*2) +#define INSTANTDEX_INSURANCEDIV 777 +#define INSTANTDEX_PUBKEY "03bc2c7ba671bae4a6fc835244c9762b41647b9827d4780a89a949b984a8ddcc06" +#define INSTANTDEX_RMD160 "ca1e04745e8ca0c60d8c5881531d51bec470743f" +#define JUMBLR_RMD160 "5177f8b427e5f47342a4b8ab5dac770815d4389e" +#define TIERNOLAN_RMD160 "daedddd8dbe7a2439841ced40ba9c3d375f98146" +#define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu" +#define INSTANTDEX_BTCD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf" + #define BASILISK_DISABLEWAITTX #define BASILISK_DISABLESENDTX +#define LP_PROPAGATION_SLACK 10 // txid ordering is not enforced, so getting extra recent txid #define LP_RESERVETIME 60 #define LP_AVETXSIZE 200 #define LP_CACHEDURATION 60 - #define BASILISK_DEFAULT_NUMCONFIRMS 5 #define DEX_SLEEP 3 -#define BASILISK_DEXDURATION 300 -#define BASILISK_MSGDURATION 30 -#define BASILISK_AUCTION_DURATION 5 - -#define BASILISK_MAXFUTUREBLOCK 60 #define BASILISK_KEYSIZE ((int32_t)(2*sizeof(bits256)+sizeof(uint32_t)*2)) extern char GLOBAL_DBDIR[]; extern int32_t IAMCLIENT; -void *bitcoin_ctx(); -int32_t bitcoin_verify(void *ctx,uint8_t *sig,int32_t siglen,bits256 txhash2,uint8_t *pubkey,int32_t plen); -int32_t bitcoin_recoververify(void *ctx,char *symbol,uint8_t *sig,bits256 messagehash2,uint8_t *pubkey,size_t plen); -int32_t bitcoin_sign(void *ctx,char *symbol,uint8_t *sig,bits256 txhash2,bits256 privkey,int32_t recoverflag); -bits256 bitcoin_pubkey33(void *ctx,uint8_t *data,bits256 privkey); -bits256 bitcoin_pub256(void *ctx,bits256 *privkeyp,uint8_t odd_even); - -char *bitcoin_base58encode(char *coinaddr,uint8_t *data,int32_t datalen); -int32_t bitcoin_base58decode(uint8_t *data,char *coinaddr); - -#define IGUANA_MAXSCRIPTSIZE 10001 -#define IGUANA_SEQUENCEID_FINAL 0xfffffffe - -#define IGUANA_SCRIPT_NULL 0 -#define IGUANA_SCRIPT_76AC 1 -#define IGUANA_SCRIPT_76A988AC 2 -#define IGUANA_SCRIPT_P2SH 3 -#define IGUANA_SCRIPT_OPRETURN 4 -#define IGUANA_SCRIPT_3of3 5 -#define IGUANA_SCRIPT_2of3 6 -#define IGUANA_SCRIPT_1of3 7 -#define IGUANA_SCRIPT_2of2 8 -#define IGUANA_SCRIPT_1of2 9 -#define IGUANA_SCRIPT_MSIG 10 -#define IGUANA_SCRIPT_DATA 11 -#define IGUANA_SCRIPT_AC 12 -#define IGUANA_SCRIPT_1of1 13 -#define IGUANA_SCRIPT_STRANGE 15 - -#define BASILISK_TIMEOUT 3000 -#define BASILISK_MINFANOUT 8 -#define BASILISK_MAXFANOUT 64 -#define BASILISK_DEFAULTDIFF 0x1effffff -#define BASILISK_HDROFFSET ((int32_t)(sizeof(bits256)+sizeof(struct iguana_msghdr)+sizeof(uint32_t))) - -#define INSTANTDEX_DECKSIZE 1000 -#define INSTANTDEX_LOCKTIME (3600*2 + 300*2) -#define INSTANTDEX_INSURANCEDIV 777 -#define INSTANTDEX_PUBKEY "03bc2c7ba671bae4a6fc835244c9762b41647b9827d4780a89a949b984a8ddcc06" -#define INSTANTDEX_RMD160 "ca1e04745e8ca0c60d8c5881531d51bec470743f" -#define JUMBLR_RMD160 "5177f8b427e5f47342a4b8ab5dac770815d4389e" -#define TIERNOLAN_RMD160 "daedddd8dbe7a2439841ced40ba9c3d375f98146" -#define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu" -#define INSTANTDEX_BTCD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf" - struct iguana_msgvin { bits256 prev_hash; uint8_t *vinscript,*userdata,*spendscript,*redeemscript; uint32_t prev_vout,sequence; uint16_t scriptlen,p2shlen,userdatalen,spendlen; }; struct iguana_msgvout { uint64_t value; uint32_t pk_scriptlen; uint8_t *pk_script; }; @@ -107,7 +67,7 @@ struct vin_info struct iguana_msgvin vin; uint64_t amount; cJSON *extras; bits256 sigtxid; int32_t M,N,validmask,spendlen,type,p2shlen,numpubkeys,numsigs,height,hashtype,userdatalen,suppress_pubkeys,ignore_cltverr; uint32_t sequence,unspentind; struct vin_signer signers[16]; char coinaddr[65]; - uint8_t rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE],p2shscript[IGUANA_MAXSCRIPTSIZE],userdata[IGUANA_MAXSCRIPTSIZE]; + uint8_t rmd160[20],spendscript[10000],p2shscript[10000],userdata[10000]; }; struct basilisk_swapmessage @@ -199,6 +159,31 @@ struct basilisk_swap }; +struct LP_utxoinfo +{ + UT_hash_handle hh; + bits256 txid,txid2,feetxid,otherpubkey,mypub; + void *swap; + uint64_t satoshis,satoshis2; + uint8_t key[sizeof(bits256) + sizeof(int32_t)]; + int32_t vout,vout2,pair; + uint32_t lasttime,errors,swappending,published; + double profitmargin; + char ipaddr[64],coinaddr[64],spendscript[256],coin[16]; + uint16_t port; +}; + +struct LP_peerinfo +{ + UT_hash_handle hh; + uint64_t ip_port; + double profitmargin; + uint32_t ipbits,errortime,errors,numpeers,numutxos,lasttime,connected; + int32_t pushsock,subsock; + uint16_t port; + char ipaddr[64]; +}; + struct LP_quoteinfo { struct basilisk_request R; @@ -208,297 +193,11 @@ struct LP_quoteinfo char srccoin[16],coinaddr[64],destcoin[16],destaddr[64]; }; -union iguana_stacknum { int32_t val; int64_t val64; uint8_t rmd160[20]; bits256 hash2; uint8_t pubkey[33]; uint8_t sig[74]; }; -struct iguana_stackdata { uint8_t *data; uint16_t size; union iguana_stacknum U; }; - -#define MAX_SCRIPT_ELEMENT_SIZE 520 -#define MAX_OPS_PER_SCRIPT 201 // Maximum number of non-push operations per script -#define MAX_PUBKEYS_PER_MULTISIG 20 // Maximum number of public keys per multisig - -#define IGUANA_MAXSTACKITEMS ((int32_t)(IGUANA_MAXSCRIPTSIZE / sizeof(uint32_t))) -#define IGUANA_MAXSTACKDEPTH 128 -struct iguana_interpreter -{ - int32_t active,ifdepth,elsedepth,codeseparator,stackdepth,altstackdepth,maxstackdepth; - int8_t lastpath[IGUANA_MAXSTACKDEPTH]; - cJSON *logarray; - struct iguana_stackdata stack[]; -}; -static struct bitcoin_opcode { UT_hash_handle hh; uint8_t opcode,flags,stackitems; int8_t extralen; } *OPTABLE; static char *OPCODES[0x100]; static int32_t OPCODELENS[0x100]; - -#define SIGHASH_ALL 1 -#define SIGHASH_NONE 2 -#define SIGHASH_SINGLE 3 -#define SIGHASH_ANYONECANPAY 0x80 - -#define SCRIPT_OP_NOP 0x00 -#define SCRIPT_OP_TRUE 0x51 -#define SCRIPT_OP_2 0x52 -#define SCRIPT_OP_3 0x53 -#define SCRIPT_OP_4 0x54 -#define SCRIPT_OP_IF 0x63 -#define SCRIPT_OP_ELSE 0x67 -#define SCRIPT_OP_RETURN 0x6a -#define SCRIPT_OP_DUP 0x76 -#define SCRIPT_OP_ENDIF 0x68 -#define SCRIPT_OP_DROP 0x75 -#define SCRIPT_OP_EQUALVERIFY 0x88 -#define SCRIPT_OP_SHA256 0xa8 -#define SCRIPT_OP_HASH160 0xa9 - -#define SCRIPT_OP_EQUAL 0x87 -#define SCRIPT_OP_CHECKSIG 0xac -#define SCRIPT_OP_CHECKMULTISIG 0xae -#define SCRIPT_OP_CHECKSEQUENCEVERIFY 0xb2 -#define SCRIPT_OP_CHECKLOCKTIMEVERIFY 0xb1 -#define IGUANA_OP_0 0x00 -#define IGUANA_OP_PUSHDATA1 0x4c -#define IGUANA_OP_PUSHDATA2 0x4d -#define IGUANA_OP_PUSHDATA4 0x4e -#define IGUANA_OP_1NEGATE 0x4f -#define IGUANA_OP_1 0x51 -#define IGUANA_OP_16 0x60 -#define IGUANA_OP_NOP 0x61 -#define IGUANA_OP_IF 0x63 -#define IGUANA_OP_NOTIF 0x64 -#define IGUANA_OP_ELSE 0x67 -#define IGUANA_OP_ENDIF 0x68 -#define IGUANA_OP_VERIFY 0x69 -#define IGUANA_OP_RETURN 0x6a - -#define IGUANA_OP_TOALTSTACK 0x6b -#define IGUANA_OP_FROMALTSTACK 0x6c -#define IGUANA_OP_2DROP 0x6d -#define IGUANA_OP_2DUP 0x6e -#define IGUANA_OP_3DUP 0x6f -#define IGUANA_OP_2OVER 0x70 -#define IGUANA_OP_2ROT 0x71 -#define IGUANA_OP_2SWAP 0x72 -#define IGUANA_OP_IFDUP 0x73 -#define IGUANA_OP_DEPTH 0x74 -#define IGUANA_OP_DROP 0x75 -#define IGUANA_OP_DUP 0x76 -#define IGUANA_OP_NIP 0x77 -#define IGUANA_OP_OVER 0x78 -#define IGUANA_OP_PICK 0x79 -#define IGUANA_OP_ROLL 0x7a -#define IGUANA_OP_ROT 0x7b -#define IGUANA_OP_SWAP 0x7c -#define IGUANA_OP_TUCK 0x7d - -#define IGUANA_OP_EQUAL 0x87 -#define IGUANA_OP_EQUALVERIFY 0x88 - -#define IGUANA_OP_1ADD 0x8b -#define IGUANA_OP_1SUB 0x8c -#define IGUANA_OP_NEGATE 0x8f -#define IGUANA_OP_ABS 0x90 -#define IGUANA_OP_NOT 0x91 -#define IGUANA_OP_0NOTEQUAL 0x92 -#define IGUANA_OP_ADD 0x93 -#define IGUANA_OP_SUB 0x94 - -#define IGUANA_OP_BOOLAND 0x9a -#define IGUANA_OP_BOOLOR 0x9b -#define IGUANA_OP_NUMEQUAL 0x9c -#define IGUANA_OP_NUMEQUALVERIFY 0x9d -#define IGUANA_OP_NUMNOTEQUAL 0x9e -#define IGUANA_OP_LESSTHAN 0x9f -#define IGUANA_OP_GREATERTHAN 0xa0 -#define IGUANA_OP_LESSTHANOREQUAL 0xa1 -#define IGUANA_OP_GREATERTHANOREQUAL 0xa2 -#define IGUANA_OP_MIN 0xa3 -#define IGUANA_OP_MAX 0xa4 -#define IGUANA_OP_WITHIN 0xa5 - -#define IGUANA_OP_RIPEMD160 0xa6 -#define IGUANA_OP_SHA1 0xa7 -#define IGUANA_OP_SHA256 0xa8 -#define IGUANA_OP_HASH160 0xa9 -#define IGUANA_OP_HASH256 0xaa -#define IGUANA_OP_CODESEPARATOR 0xab -#define IGUANA_OP_CHECKSIG 0xac -#define IGUANA_OP_CHECKSIGVERIFY 0xad -#define IGUANA_OP_CHECKMULTISIG 0xae -#define IGUANA_OP_CHECKMULTISIGVERIFY 0xaf - -#define IGUANA_OP_NOP1 0xb0 -#define IGUANA_OP_CHECKLOCKTIMEVERIFY 0xb1 -#define IGUANA_OP_CHECKSEQUENCEVERIFY 0xb2 -#define IGUANA_OP_NOP10 0xb9 - -#define IGUANA_OP_COMBINEPUBKEYS 0xc0 -#define IGUANA_OP_CHECKSCHNORR 0xc1 -#define IGUANA_OP_CHECKSCHNORRVERIFY 0xc2 - -// https://github.com/TierNolan/bips/blob/cpkv/bip-cprkv.mediawiki -#define IGUANA_OP_CHECKPRIVATEKEY 0xc3 -#define IGUANA_OP_CHECKPRIVATEKEYVERIFY 0xc4 - -#define IGUANA_NOPFLAG 1 -#define IGUANA_ALWAYSILLEGAL 2 -#define IGUANA_EXECUTIONILLEGAL 4 -#define IGUANA_POSTVERIFY 8 -#define IGUANA_CRYPTOFLAG 16 -#define IGUANA_MATHFLAG 32 -#define IGUANA_CONTROLFLAG 64 -#define IGUANA_STACKFLAG 128 - -enum opcodetype -{ - // push value - OP_0 = 0x00, - OP_FALSE = OP_0, - OP_PUSHDATA1 = 0x4c, - OP_PUSHDATA2 = 0x4d, - OP_PUSHDATA4 = 0x4e, - OP_1NEGATE = 0x4f, - OP_RESERVED = 0x50, - OP_1 = 0x51, - OP_TRUE=OP_1, - OP_2 = 0x52, - OP_3 = 0x53, - OP_4 = 0x54, - OP_5 = 0x55, - OP_6 = 0x56, - OP_7 = 0x57, - OP_8 = 0x58, - OP_9 = 0x59, - OP_10 = 0x5a, - OP_11 = 0x5b, - OP_12 = 0x5c, - OP_13 = 0x5d, - OP_14 = 0x5e, - OP_15 = 0x5f, - OP_16 = 0x60, - - // control - OP_NOP = 0x61, - OP_VER = 0x62, - OP_IF = 0x63, - OP_NOTIF = 0x64, - OP_VERIF = 0x65, - OP_VERNOTIF = 0x66, - OP_ELSE = 0x67, - OP_ENDIF = 0x68, - OP_VERIFY = 0x69, - OP_RETURN = 0x6a, - - // stack ops - OP_TOALTSTACK = 0x6b, - OP_FROMALTSTACK = 0x6c, - OP_2DROP = 0x6d, - OP_2DUP = 0x6e, - OP_3DUP = 0x6f, - OP_2OVER = 0x70, - OP_2ROT = 0x71, - OP_2SWAP = 0x72, - OP_IFDUP = 0x73, - OP_DEPTH = 0x74, - OP_DROP = 0x75, - OP_DUP = 0x76, - OP_NIP = 0x77, - OP_OVER = 0x78, - OP_PICK = 0x79, - OP_ROLL = 0x7a, - OP_ROT = 0x7b, - OP_SWAP = 0x7c, - OP_TUCK = 0x7d, - - // splice ops - OP_CAT = 0x7e, - OP_SUBSTR = 0x7f, - OP_LEFT = 0x80, - OP_RIGHT = 0x81, - OP_SIZE = 0x82, - - // bit logic - OP_INVERT = 0x83, - OP_AND = 0x84, - OP_OR = 0x85, - OP_XOR = 0x86, - OP_EQUAL = 0x87, - OP_EQUALVERIFY = 0x88, - OP_RESERVED1 = 0x89, - OP_RESERVED2 = 0x8a, - - // numeric - OP_1ADD = 0x8b, - OP_1SUB = 0x8c, - OP_2MUL = 0x8d, - OP_2DIV = 0x8e, - OP_NEGATE = 0x8f, - OP_ABS = 0x90, - OP_NOT = 0x91, - OP_0NOTEQUAL = 0x92, - - OP_ADD = 0x93, - OP_SUB = 0x94, - OP_MUL = 0x95, - OP_DIV = 0x96, - OP_MOD = 0x97, - OP_LSHIFT = 0x98, - OP_RSHIFT = 0x99, - - OP_BOOLAND = 0x9a, - OP_BOOLOR = 0x9b, - OP_NUMEQUAL = 0x9c, - OP_NUMEQUALVERIFY = 0x9d, - OP_NUMNOTEQUAL = 0x9e, - OP_LESSTHAN = 0x9f, - OP_GREATERTHAN = 0xa0, - OP_LESSTHANOREQUAL = 0xa1, - OP_GREATERTHANOREQUAL = 0xa2, - OP_MIN = 0xa3, - OP_MAX = 0xa4, - - OP_WITHIN = 0xa5, - - // crypto - OP_RIPEMD160 = 0xa6, - OP_SHA1 = 0xa7, - OP_SHA256 = 0xa8, - OP_HASH160 = 0xa9, - OP_HASH256 = 0xaa, - OP_CODESEPARATOR = 0xab, - OP_CHECKSIG = 0xac, - OP_CHECKSIGVERIFY = 0xad, - OP_CHECKMULTISIG = 0xae, - OP_CHECKMULTISIGVERIFY = 0xaf, - - // expansion - OP_NOP1 = 0xb0, - OP_CHECKLOCKTIMEVERIFY = 0xb1, - OP_CHECKSEQUENCEVERIFY = 0xb2, - OP_NOP4 = 0xb3, - OP_NOP5 = 0xb4, - OP_NOP6 = 0xb5, - OP_NOP7 = 0xb6, - OP_NOP8 = 0xb7, - OP_NOP9 = 0xb8, - OP_NOP10 = 0xb9, - - OP_COMBINEPUBKEYS = 0xc0, - OP_CHECKSCHNORR = 0xc1, - OP_CHECKSCHNORRVERIFY = 0xc2, - OP_CHECKPRIVATEKEY = 0xc3, - OP_CHECKPRIVATEKEYVERIFY = 0xc4, - - // template matching params - //OP_SMALLINTEGER = 0xfa, - //OP_PUBKEYS = 0xfb, - //OP_PUBKEYHASH = 0xfd, - //OP_PUBKEY = 0xfe, - - OP_INVALIDOPCODE = 0xff, -}; void basilisk_dontforget_update(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx); uint32_t basilisk_requestid(struct basilisk_request *rp); uint32_t basilisk_quoteid(struct basilisk_request *rp); struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp); char *bitcoind_passthru(char *coinstr,char *serverport,char *userpass,char *method,char *params); -struct iguana_info *LP_coinfind(char *symbol); -void *curl_post(void **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3); uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx,uint32_t nextbits,int32_t suppress_swapsend); #endif diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index ce8a3b97c..68915cd7a 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -23,549 +23,21 @@ #include "LP_include.h" #include "LP_network.c" -#define LP_PROPAGATION_SLACK 10 // txid ordering is not enforced, so getting extra recent txid +struct LP_utxoinfo *LP_utxoinfos; +struct LP_peerinfo *LP_peerinfos,*LP_mypeer; char *activecoins[] = { "BTC", "KMD", "REVS", "JUMBLR" };//"LTC", "USD", }; +char GLOBAL_DBDIR[] = "DB"; char *default_LPnodes[] = { "5.9.253.196", "5.9.253.197", "5.9.253.198", "5.9.253.199", "5.9.253.200", "5.9.253.201", "5.9.253.202", "5.9.253.203", "5.9.253.204" }; //"5.9.253.195", + portable_mutex_t LP_peermutex,LP_utxomutex,LP_commandmutex,LP_cachemutex; int32_t LP_mypubsock = -1; int32_t Client_connections; int32_t IAMCLIENT = 0; -struct LP_peerinfo -{ - UT_hash_handle hh; - uint64_t ip_port; - double profitmargin; - uint32_t ipbits,errortime,errors,numpeers,numutxos,lasttime,connected; - int32_t pushsock,subsock; - uint16_t port; - char ipaddr[64]; -} *LP_peerinfos,*LP_mypeer; - -struct LP_utxoinfo -{ - UT_hash_handle hh; - bits256 txid,txid2,feetxid,otherpubkey,mypub; - void *swap; - uint64_t satoshis,satoshis2; - uint8_t key[sizeof(bits256) + sizeof(int32_t)]; - int32_t vout,vout2,pair; uint32_t lasttime,errors,swappending; - double profitmargin; - char ipaddr[64],coinaddr[64],spendscript[256],coin[16]; - uint16_t port; -} *LP_utxoinfos; - -struct LP_cacheinfo -{ - UT_hash_handle hh; - struct LP_quoteinfo Q; - uint8_t key[sizeof(bits256)+sizeof(uint64_t)*2+sizeof(int32_t)]; - double price; - uint32_t timestamp; -} *LP_cacheinfos; - -int32_t LP_cachekey(uint8_t *key,char *base,char *rel,bits256 txid,int32_t vout) -{ - uint64_t basebits,relbits; int32_t offset = 0; - basebits = stringbits(base); - relbits = stringbits(rel); - memcpy(&key[offset],&basebits,sizeof(basebits)), offset += sizeof(basebits); - memcpy(&key[offset],&relbits,sizeof(relbits)), offset += sizeof(relbits); - memcpy(&key[offset],&txid,sizeof(txid)), offset += sizeof(txid); - memcpy(&key[offset],&vout,sizeof(vout)), offset += sizeof(vout); - return(offset); -} - -struct LP_cacheinfo *LP_cachefind(char *base,char *rel,bits256 txid,int32_t vout) -{ - struct LP_cacheinfo *ptr=0; uint8_t key[sizeof(bits256)+sizeof(uint64_t)*2+sizeof(vout)]; - if ( LP_cachekey(key,base,rel,txid,vout) == sizeof(key) ) - { - portable_mutex_lock(&LP_cachemutex); - HASH_FIND(hh,LP_cacheinfos,key,sizeof(key),ptr); - portable_mutex_unlock(&LP_cachemutex); - } else printf("LP_cachefind keysize mismatch?\n"); - if ( 0 && ptr != 0 && ptr->timestamp != 0 && ptr->timestamp < time(NULL)-LP_CACHEDURATION ) - { - printf("expire price %.8f\n",ptr->price); - ptr->price = 0.; - ptr->timestamp = 0; - memset(&ptr->Q,0,sizeof(ptr->Q)); - } - return(ptr); -} - -double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,int32_t vout) -{ - struct LP_cacheinfo *ptr; - if ( (ptr= LP_cachefind(base,rel,txid,vout)) != 0 ) - { - if ( qp != 0 ) - (*qp) = ptr->Q; - if ( ptr->price == 0. && ptr->Q.satoshis != 0 ) - { - printf("null ptr->price? "); - ptr->price = (double)ptr->Q.destsatoshis / ptr->Q.satoshis; - } - //printf("found %s/%s %.8f\n",base,rel,ptr->price); - return(ptr->price); - } - //char str[65]; printf("cachemiss %s/%s %s/v%d\n",base,rel,bits256_str(str,txid),vout); - return(0.); -} - -struct LP_cacheinfo *LP_cacheadd(char *base,char *rel,bits256 txid,int32_t vout,double price,struct LP_quoteinfo *qp) -{ - struct LP_cacheinfo *ptr=0; - if ( (ptr= LP_cachefind(base,rel,txid,vout)) == 0 ) - { - 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"); - } //else printf("CACHE hit!\n"); - char str[65]; if ( price != ptr->price ) - printf("updated %s/v%d %s/%s %llu price %.8f\n",bits256_str(str,txid),vout,base,rel,(long long)qp->satoshis,price); - ptr->price = price; - ptr->Q = *qp; - ptr->timestamp = (uint32_t)time(NULL); - printf("cacheadd %.8f\n",price); - return(ptr); -} - -struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port) -{ - struct LP_peerinfo *peer=0; uint64_t ip_port; - ip_port = ((uint64_t)port << 32) | ipbits; - portable_mutex_lock(&LP_peermutex); - HASH_FIND(hh,LP_peerinfos,&ip_port,sizeof(ip_port),peer); - portable_mutex_unlock(&LP_peermutex); - return(peer); -} - -struct LP_utxoinfo *LP_utxofind(bits256 txid,int32_t vout) -{ - struct LP_utxoinfo *utxo=0; uint8_t key[sizeof(txid) + sizeof(vout)]; - memcpy(key,txid.bytes,sizeof(txid)); - memcpy(&key[sizeof(txid)],&vout,sizeof(vout)); - portable_mutex_lock(&LP_utxomutex); - HASH_FIND(hh,LP_utxoinfos,key,sizeof(key),utxo); - portable_mutex_unlock(&LP_utxomutex); - return(utxo); -} - -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); - return(item); -} - -cJSON *LP_utxojson(struct LP_utxoinfo *utxo) -{ - cJSON *item = cJSON_CreateObject(); - jaddstr(item,"ipaddr",utxo->ipaddr); - jaddnum(item,"port",utxo->port); - jaddnum(item,"profit",utxo->profitmargin); - jaddstr(item,"base",utxo->coin); - jaddstr(item,"coin",utxo->coin); - jaddstr(item,"address",utxo->coinaddr); - jaddstr(item,"script",utxo->spendscript); - jaddbits256(item,"txid",utxo->txid); - jaddnum(item,"vout",utxo->vout); - jaddnum(item,"value",dstr(utxo->satoshis)); - jaddbits256(item,"txid2",utxo->txid2); - jaddnum(item,"vout2",utxo->vout2); - jaddnum(item,"value2",dstr(utxo->satoshis2)); - return(item); -} - -char *LP_peers() -{ - struct LP_peerinfo *peer,*tmp; cJSON *peersjson = cJSON_CreateArray(); - HASH_ITER(hh,LP_peerinfos,peer,tmp) - { - jaddi(peersjson,LP_peerjson(peer)); - } - return(jprint(peersjson,1)); -} - -char *LP_utxos(struct LP_peerinfo *mypeer,char *coin,int32_t lastn) -{ - int32_t i,firsti; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray(); - i = 0; - if ( lastn >= mypeer->numutxos ) - firsti = -1; - else firsti = (mypeer->numutxos - lastn); - HASH_ITER(hh,LP_utxoinfos,utxo,tmp) - { - if ( i++ < firsti ) - continue; - if ( coin == 0 || coin[0] == 0 || strcmp(coin,utxo->coin) == 0 ) - { - jaddi(utxosjson,LP_utxojson(utxo)); - } - } - return(jprint(utxosjson,1)); -} - -struct LP_peerinfo *LP_addpeer(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *ipaddr,uint16_t port,uint16_t pushport,uint16_t subport,double profitmargin,int32_t numpeers,int32_t numutxos) -{ - uint32_t ipbits; int32_t pushsock,subsock,timeout,enabled; char checkip[64],pushaddr[64],subaddr[64]; struct LP_peerinfo *peer = 0; - ipbits = (uint32_t)calc_ipbits(ipaddr); - expand_ipbits(checkip,ipbits); - if ( strcmp(checkip,ipaddr) == 0 ) - { - if ( (peer= LP_peerfind(ipbits,port)) != 0 ) - { - if ( peer->profitmargin == 0. ) - peer->profitmargin = profitmargin; - if ( numpeers > peer->numpeers ) - peer->numpeers = numpeers; - if ( numutxos > peer->numutxos ) - peer->numutxos = numutxos; - } - else - { - //printf("LPaddpeer %s\n",ipaddr); - peer = calloc(1,sizeof(*peer)); - peer->pushsock = peer->subsock = pushsock = subsock = -1; - strcpy(peer->ipaddr,ipaddr); - if ( amclient == 0 ) - enabled = 1; - else enabled = 1;//(rand() % (1 << Client_connections)) == 0; - if ( pushport != 0 && subport != 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 ) - { - timeout = 1000; - nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); - nanomsg_tcpname(pushaddr,peer->ipaddr,pushport); - if ( nn_connect(pushsock,pushaddr) >= 0 ) - { - printf("connected to push.(%s) %d\n",pushaddr,pushsock); - peer->connected = (uint32_t)time(NULL); - peer->pushsock = pushsock; - if ( enabled != 0 && (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 ) - { - timeout = 1; - nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); - nn_setsockopt(subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); - nanomsg_tcpname(subaddr,peer->ipaddr,subport); - if ( nn_connect(subsock,subaddr) >= 0 ) - { - peer->subsock = subsock; - printf("connected to sub.(%s) %d\n",subaddr,peer->subsock); - Client_connections += amclient; - } else nn_close(subsock); - } - } - else - { - nn_close(pushsock); - 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->ipbits = ipbits; - peer->port = port; - peer->ip_port = ((uint64_t)port << 32) | ipbits; - portable_mutex_lock(&LP_peermutex); - HASH_ADD(hh,LP_peerinfos,ip_port,sizeof(peer->ip_port),peer); - if ( mypeer != 0 ) - { - mypeer->numpeers++; - 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 ) - LP_send(mypubsock,jprint(LP_peerjson(peer),1),1); - } - } else printf("LP_addpeer: checkip.(%s) vs (%s)\n",checkip,ipaddr); - return(peer); -} - -struct LP_utxoinfo *LP_addutxo(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *coin,bits256 txid,int32_t vout,int64_t satoshis,bits256 deposittxid,int32_t depositvout,int64_t depositsatoshis,char *spendscript,char *coinaddr,char *ipaddr,uint16_t port,double profitmargin) -{ - struct LP_utxoinfo *utxo = 0; - if ( coin == 0 || coin[0] == 0 || spendscript == 0 || spendscript[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(deposittxid) == 0 || vout < 0 || depositvout < 0 || satoshis <= 0 || depositsatoshis <= 0 ) - { - printf("malformed addutxo %d %d %d %d %d %d %d %d %d\n", coin == 0,spendscript == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(deposittxid) == 0,vout < 0,depositvout < 0,satoshis <= 0,depositsatoshis <= 0); - return(0); - } - if ( amclient == 0 && strcmp(ipaddr,"127.0.0.1") == 0 ) - { - printf("LP node got localhost utxo\n"); - return(0); - } - if ( (utxo= LP_utxofind(txid,vout)) != 0 ) - { - if ( bits256_cmp(txid,utxo->txid) != 0 || bits256_cmp(deposittxid,utxo->txid2) != 0 || vout != utxo->vout || satoshis != utxo->satoshis || depositvout != utxo->vout2 || depositsatoshis != utxo->satoshis2 || strcmp(coin,utxo->coin) != 0 || strcmp(spendscript,utxo->spendscript) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || strcmp(ipaddr,utxo->ipaddr) != 0 || port != utxo->port ) - { - utxo->errors++; - char str[65],str2[65]; printf("error on subsequent utxo add.(%s v %s) %d %d %d %d %d %d %d %d %d %d %d\n",bits256_str(str,txid),bits256_str(str2,utxo->txid),bits256_cmp(txid,utxo->txid) != 0,bits256_cmp(deposittxid,utxo->txid2) != 0,vout != utxo->vout,satoshis != utxo->satoshis,depositvout != utxo->vout2,depositsatoshis != utxo->satoshis2,strcmp(coin,utxo->coin) != 0,strcmp(spendscript,utxo->spendscript) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,strcmp(ipaddr,utxo->ipaddr) != 0,port != utxo->port); - } - else if ( profitmargin != 0. ) - utxo->profitmargin = profitmargin; - } - else - { - utxo = calloc(1,sizeof(*utxo)); - utxo->pair = -1; - utxo->profitmargin = profitmargin; - strcpy(utxo->ipaddr,ipaddr); - utxo->port = port; - safecopy(utxo->coin,coin,sizeof(utxo->coin)); - safecopy(utxo->coinaddr,coinaddr,sizeof(utxo->coinaddr)); - safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript)); - utxo->txid = txid; - utxo->vout = vout; - utxo->satoshis = satoshis; - utxo->txid2 = deposittxid; - utxo->vout2 = depositvout; - utxo->satoshis2 = depositsatoshis; - memcpy(utxo->key,txid.bytes,sizeof(txid)); - memcpy(&utxo->key[sizeof(txid)],&vout,sizeof(vout)); - portable_mutex_lock(&LP_utxomutex); - HASH_ADD_KEYPTR(hh,LP_utxoinfos,utxo->key,sizeof(utxo->key),utxo); - if ( mypeer != 0 ) - mypeer->numutxos++; - portable_mutex_unlock(&LP_utxomutex); - if ( mypubsock >= 0 ) - LP_send(mypubsock,jprint(LP_utxojson(utxo),1),1); - //char str[65],str2[65]; printf("%s:%u %s LP_addutxo.(%.8f %.8f) numutxos.%d %s %s\n",ipaddr,port,utxo->coin,dstr(satoshis),dstr(depositsatoshis),mypeer!=0?mypeer->numutxos:0,bits256_str(str,utxo->txid),bits256_str(str2,txid)); - } - return(utxo); -} - -int32_t LP_peersparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now) -{ - struct LP_peerinfo *peer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - if ( (n= cJSON_GetArraySize(array)) > 0 ) - { - for (i=0; ilasttime = now; - if ( strcmp(argipaddr,destipaddr) == 0 && destport == argport && peer->numpeers != n ) - peer->numpeers = n; - } - } - } - } - free_json(array); - } - return(n); -} - -int32_t LP_utxosparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now) -{ - struct LP_peerinfo *peer,*destpeer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; bits256 txid; struct LP_utxoinfo *utxo; - if ( amclient != 0 ) - { - printf("LP_utxosparse not for clientside\n"); - return(-1); - } - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - if ( (n= cJSON_GetArraySize(array)) > 0 ) - { - for (i=0; ilasttime = now; - } - } - } - if ( (destpeer= LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport)) != 0 ) - { - if ( destpeer->numutxos < n ) - { - //destpeer->numutxos = n; - //printf("got.(%s) from %s numutxos.%d\n",retstr,destpeer->ipaddr,destpeer->numutxos); - } - } - } - free_json(array); - } - return(n); -} - -char *issue_LP_getpeers(char *destip,uint16_t destport,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos) -{ - char url[512],*retstr; - sprintf(url,"http://%s:%u/api/stats/getpeers?ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,profitmargin,numpeers,numutxos); - //printf("send.(%s)\n",url); - retstr = issue_curl(url); - //printf("GETPEERS.(%s)\n",retstr); - return(retstr); -} - -char *issue_LP_getutxos(char *destip,uint16_t destport,char *coin,int32_t lastn,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos) -{ - char url[512]; - sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,coin,lastn,ipaddr,port,profitmargin,numpeers,numutxos); - return(issue_curl(url)); -} - -char *issue_LP_clientgetutxos(char *destip,uint16_t destport,char *coin,int32_t lastn) -{ - char url[512]; - sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=127.0.0.1&port=0",destip,destport,coin,lastn); - //printf("getutxos.(%s)\n",url); - return(issue_curl(url)); -} - -char *issue_LP_notify(char *destip,uint16_t destport,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos) -{ - char url[512]; - sprintf(url,"http://%s:%u/api/stats/notify?ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,profitmargin,numpeers,numutxos); - return(issue_curl(url)); -} - -char *issue_LP_notifyutxo(char *destip,uint16_t destport,struct LP_utxoinfo *utxo) -{ - char url[4096],str[65],str2[65]; - sprintf(url,"http://%s:%u/api/stats/notifyutxo?ipaddr=%s&port=%u&profit=%.6f&coin=%s&txid=%s&vout=%d&value=%.8f&txid2=%s&vout2=%d&value2=%.8f&script=%s&address=%s",destip,destport,utxo->ipaddr,utxo->port,utxo->profitmargin,utxo->coin,bits256_str(str,utxo->txid),utxo->vout,dstr(utxo->satoshis),bits256_str(str2,utxo->txid2),utxo->vout2,dstr(utxo->satoshis2),utxo->spendscript,utxo->coinaddr); - if ( strlen(url) > 1024 ) - printf("WARNING long url.(%s)\n",url); - return(issue_curl(url)); -} - -void LP_peersquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *myipaddr,uint16_t myport,double myprofit) -{ - char *retstr; struct LP_peerinfo *peer,*tmp; uint32_t now,flag = 0; - peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); - if ( peer != 0 && peer->errors > 0 ) - return; - if ( (retstr= issue_LP_getpeers(destipaddr,destport,myipaddr,myport,myprofit,mypeer!=0?mypeer->numpeers:0,mypeer!=0?mypeer->numutxos:0)) != 0 ) - { - //printf("got.(%s)\n",retstr); - now = (uint32_t)time(NULL); - LP_peersparse(amclient,mypeer,mypubsock,destipaddr,destport,retstr,now); - free(retstr); - if ( amclient == 0 ) - { - HASH_ITER(hh,LP_peerinfos,peer,tmp) - { - if ( peer->lasttime != now ) - { - printf("{%s:%u %.6f}.%d ",peer->ipaddr,peer->port,peer->profitmargin,peer->lasttime - now); - flag++; - if ( (retstr= issue_LP_notify(destipaddr,destport,peer->ipaddr,peer->port,peer->profitmargin,peer->numpeers,0)) != 0 ) - free(retstr); - } - } - if ( flag != 0 ) - printf(" <- missing peers\n"); - } - } else if ( peer != 0 ) - peer->errors++; -} - -void LP_utxosquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *coin,int32_t lastn,char *myipaddr,uint16_t myport,double myprofit) -{ - char *retstr; struct LP_utxoinfo *utxo,*tmp; struct LP_peerinfo *peer; int32_t i,firsti; uint32_t now,flag = 0; - if ( amclient != 0 ) - { - printf("LP_utxosquery not for clientside\n"); - return; - } - peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); - if ( (peer != 0 && peer->errors > 0) || mypeer == 0 ) - return; - if ( coin == 0 ) - coin = ""; - if ( (retstr= issue_LP_getutxos(destipaddr,destport,coin,lastn,myipaddr,myport,myprofit,mypeer->numpeers,mypeer->numutxos)) != 0 ) - { - now = (uint32_t)time(NULL); - LP_utxosparse(amclient,mypeer,mypubsock,destipaddr,destport,retstr,now); - free(retstr); - i = 0; - if ( lastn >= mypeer->numutxos ) - firsti = -1; - else firsti = (mypeer->numutxos - lastn); - HASH_ITER(hh,LP_utxoinfos,utxo,tmp) - { - if ( i++ < firsti ) - continue; - if ( utxo->lasttime != now && strcmp(utxo->ipaddr,"127.0.0.1") != 0 ) - { - char str[65]; printf("{%s:%u %s} ",utxo->ipaddr,utxo->port,bits256_str(str,utxo->txid)); - flag++; - if ( (retstr= issue_LP_notifyutxo(destipaddr,destport,utxo)) != 0 ) - free(retstr); - } - } - if ( flag != 0 ) - printf(" <- missing utxos\n"); - } else if ( peer != 0 ) - peer->errors++; -} - -int32_t LP_maxvalue(uint64_t *values,int32_t n) -{ - int32_t i,maxi = -1; uint64_t maxval = 0; - for (i=0; i maxval ) - { - maxi = i; - maxval = values[i]; - } - return(maxi); -} - -int32_t LP_nearestvalue(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= 0 && dist < mindist ) - { - mini = i; - mindist = dist; - } - } - return(mini); -} +// stubs int32_t basilisk_istrustedbob(struct basilisk_swap *swap) { // for BTC and if trusted LP @@ -581,283 +53,32 @@ void tradebot_pendingadd(cJSON *tradejson,char *base,double basevolume,char *rel { // add to trades } +char *LP_getdatadir() +{ + return("/root"); +} -char GLOBAL_DBDIR[] = "DB"; +char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_t skip) +{ + return(0); +} #include "LP_secp.c" -#include "LP_rpc.c" #include "LP_bitcoin.c" +#include "LP_coins.c" +#include "LP_rpc.c" +#include "LP_prices.c" #include "LP_transaction.c" #include "LP_remember.c" -//#include "LP_statemachine.c" #include "LP_swap.c" +#include "LP_peers.c" +#include "LP_utxos.c" #include "LP_commands.c" -char *parse_conf_line(char *line,char *field) -{ - line += strlen(field); - for (; *line!='='&&*line!=0; line++) - break; - if ( *line == 0 ) - return(0); - if ( *line == '=' ) - line++; - while ( line[strlen(line)-1] == '\r' || line[strlen(line)-1] == '\n' || line[strlen(line)-1] == ' ' ) - line[strlen(line)-1] = 0; - //printf("LINE.(%s)\n",line); - _stripwhite(line,0); - return(clonestr(line)); -} - -void LP_userpassfp(char *username,char *password,FILE *fp) -{ - char *rpcuser,*rpcpassword,*str,line[8192]; - rpcuser = rpcpassword = 0; - username[0] = password[0] = 0; - while ( fgets(line,sizeof(line),fp) != 0 ) - { - if ( line[0] == '#' ) - continue; - //printf("line.(%s) %p %p\n",line,strstr(line,(char *)"rpcuser"),strstr(line,(char *)"rpcpassword")); - if ( (str= strstr(line,(char *)"rpcuser")) != 0 ) - rpcuser = parse_conf_line(str,(char *)"rpcuser"); - else if ( (str= strstr(line,(char *)"rpcpassword")) != 0 ) - rpcpassword = parse_conf_line(str,(char *)"rpcpassword"); - } - if ( rpcuser != 0 && rpcpassword != 0 ) - { - strcpy(username,rpcuser); - strcpy(password,rpcpassword); - } - //printf("rpcuser.(%s) rpcpassword.(%s) KMDUSERPASS.(%s) %u\n",rpcuser,rpcpassword,KMDUSERPASS,port); - if ( rpcuser != 0 ) - free(rpcuser); - if ( rpcpassword != 0 ) - free(rpcpassword); -} - -void LP_statefname(char *fname,char *symbol,char *assetname,char *str) -{ - sprintf(fname,"%s",LP_getdatadir()); -#ifdef WIN32 - strcat(fname,"\\"); -#else - strcat(fname,"/"); -#endif - if ( strcmp(symbol,"BTC") == 0 ) - strcat(fname,".bitcoin"); - else if ( strcmp(symbol,"LTC") == 0 ) - strcat(fname,".litecoin"); - else - { - strcat(fname,".komodo"); - if ( strcmp(symbol,"KMD") != 0 ) - { -#ifdef WIN32 - strcat(fname,"\\"); -#else - strcat(fname,"/"); -#endif - strcat(fname,assetname); - } - } -#ifdef WIN32 - strcat(fname,"\\"); -#else - strcat(fname,"/"); -#endif - strcat(fname,str); - printf("LP_statefname.(%s) <- %s %s %s\n",fname,symbol,assetname,str); -} - -int32_t LP_userpass(char *userpass,char *symbol,char *assetname,char *confroot) -{ - FILE *fp; char fname[512],username[512],password[512],confname[16]; - userpass[0] = 0; - sprintf(confname,"%s.conf",confroot); -#ifdef __APPLE__ - confname[0] = toupper(confname[0]); -#endif - LP_statefname(fname,symbol,assetname,confname); - if ( (fp= fopen(fname,"rb")) != 0 ) - { - LP_userpassfp(username,password,fp); - sprintf(userpass,"%s:%s",username,password); - fclose(fp); - return((int32_t)strlen(userpass)); - } - return(-1); -} - -uint32_t LP_assetmagic(char *symbol,uint64_t supply) -{ - uint8_t buf[512]; int32_t len = 0; - if ( strcmp(symbol,"KMD") == 0 ) - return(0x8de4eef9); - len = iguana_rwnum(1,&buf[len],sizeof(supply),(void *)&supply); - strcpy((char *)&buf[len],symbol); - len += strlen(symbol); - return(calc_crc32(0,buf,len)); -} - -uint16_t LP_assetport(uint32_t magic) -{ - if ( magic == 0x8de4eef9 ) - return(7771); - else return(8000 + (magic % 7777)); -} - -uint16_t LP_rpcport(char *symbol,uint64_t supply,uint32_t *magicp) -{ - if ( symbol == 0 || symbol[0] == 0 || strcmp("KMD",symbol) == 0 ) - { - *magicp = 0x8de4eef9; - return(7771); - } - else if ( strcmp("BTC",symbol) == 0 ) - return(8332); - else if ( strcmp("LTC",symbol) == 0 ) - return(9332); - *magicp = LP_assetmagic(symbol,supply); - return(LP_assetport(*magicp)+1); -} - -struct iguana_info *LP_coinfind(char *symbol) -{ - static struct iguana_info *LP_coins; static int32_t LP_numcoins; - struct iguana_info *coin,cdata; int32_t i; uint32_t magic; uint16_t port; - for (i=0; ipubtype); - { - char tmpstr[128]; - bitcoin_priv2wif(tmpstr,privkey,coin->wiftype); - printf("%s (%s) %d wif.(%s) (%s)\n",symbol,coinaddr,coin->pubtype,tmpstr,passphrase); - if ( (retjson= LP_importprivkey(coin->symbol,tmpstr,coinaddr,-1)) != 0 ) - printf("importprivkey -> (%s)\n",jprint(retjson,1)); - } - bitcoin_addr2rmd160(&tmptype,rmd160,coinaddr); - LP_privkeyadd(privkey,rmd160); - if ( (array= LP_listunspent(symbol,coinaddr)) != 0 ) - { - if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) - { - values = calloc(n,sizeof(*values)); - for (i=0; i= 0 ) - { - item = jitem(array,i); - deposittxid = jbits256(item,"txid"); - depositvout = juint(item,"vout"); - script = jstr(item,"scriptPubKey"); - depositval = values[i]; - values[i] = 0, used++; - if ( amclient != 0 ) - targetval = (depositval / 776) + 50000; - else targetval = (depositval / 9) * 8; - //printf("i.%d %.8f target %.8f\n",i,dstr(depositval),dstr(targetval)); - if ( (i= LP_nearestvalue(values,n,targetval)) >= 0 ) - { - item = jitem(array,i); - txid = jbits256(item,"txid"); - vout = juint(item,"vout"); - printf("j.%d %.8f target %.8f\n",i,dstr(values[i]),dstr(targetval)); - if ( jstr(item,"scriptPubKey") != 0 && strcmp(script,jstr(item,"scriptPubKey")) == 0 ) - { - value = values[i]; - values[i] = 0, used++; - if ( amclient == 0 ) - { - if ( (utxo= LP_addutxo(amclient,mypeer,mypubsock,symbol,txid,vout,value,deposittxid,depositvout,depositval,script,coinaddr,LP_peerinfos[0].ipaddr,LP_peerinfos[0].port,LP_peerinfos[0].profitmargin)) != 0 ) - utxo->mypub = curve25519(privkey,curve25519_basepoint9()); - } - else - { - if ( (utxo= LP_addutxo(amclient,mypeer,mypubsock,symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coinaddr,"127.0.0.1",0,0)) != 0 ) - utxo->mypub = curve25519(privkey,curve25519_basepoint9()); - } - total += value; - } - } - } else break; - } - free(values); - } - free_json(array); - } - return(total); -} - -void LP_privkey_updates(struct LP_peerinfo *mypeer,int32_t pubsock,char *passphrase,int32_t amclient) -{ - int32_t i; - for (i=0; icoin,"KMD") == 0 ) + LP_priceping(pubsock,utxo,"BTC",profitmargin); + else LP_priceping(pubsock,utxo,"KMD",profitmargin); + } + } HASH_ITER(hh,LP_peerinfos,peer,tmp) { n++; @@ -1052,16 +282,3 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,double profit } LP_mainloop(mypeer,mypubport,pubsock,pullsock,myport,amclient,passphrase,profitmargin); } - -/*#ifdef __APPLE__ -int32_t nn_bind() { return(-1); } -int32_t nn_close() { return(-1); } -int32_t nn_connect() { return(-1); } -int32_t nn_freemsg() { return(-1); } -int32_t nn_poll() { return(-1); } -int32_t nn_recv() { return(-1); } -int32_t nn_send() { return(-1); } -int32_t nn_setsockopt() { return(-1); } -int32_t nn_socket() { return(-1); } - -#endif*/ diff --git a/iguana/exchanges/LP_network.c b/iguana/exchanges/LP_network.c index faf6137f3..84a7cb512 100644 --- a/iguana/exchanges/LP_network.c +++ b/iguana/exchanges/LP_network.c @@ -18,94 +18,6 @@ // marketmaker // -void basilisk_psockinit(struct basilisk_swap *swap,int32_t amlp) -{ -/* char keystr[64],databuf[1024],pubkeystr[128],*retstr,*retstr2,*datastr,*pushaddr=0,*subaddr=0; cJSON *retjson,*addrjson; uint8_t data[512]; int32_t datalen,timeout,pushsock = -1,subsock = -1; - if ( swap->connected == 1 ) - return; - if ( swap->pushsock < 0 && swap->subsock < 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 && (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 ) - { - timeout = 1000; - nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); - timeout = 1; - nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); - nn_setsockopt(subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); - swap->pushsock = pushsock; - swap->subsock = subsock; - } - if ( (subsock= swap->subsock) < 0 || (pushsock= swap->pushsock) < 0 ) - { - printf("error getting nn_sockets\n"); - return; - } - sprintf(keystr,"%08x-%08x",swap->I.req.requestid,swap->I.req.quoteid); - if ( swap->connected == 0 && (retstr= _dex_kvsearch("KV",keystr)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( (datastr= jstr(retjson,"value")) != 0 ) - { - datalen = (int32_t)strlen(datastr) >> 1; - decode_hex((uint8_t *)databuf,datalen,datastr); - if ( (addrjson= cJSON_Parse(databuf)) != 0 ) - { - pushaddr = jstr(addrjson,"push"); - subaddr = jstr(addrjson,"sub"); - if ( pushaddr != 0 && subaddr != 0 ) - { - printf("KV decoded (%s and %s) %d %d\n",pushaddr,subaddr,swap->pushsock,swap->subsock); - if ( nn_connect(swap->pushsock,pushaddr) >= 0 && nn_connect(swap->subsock,subaddr) >= 0 ) - swap->connected = 1; - } - free_json(addrjson); - } - } - free_json(retjson); - } - printf("KVsearch.(%s) -> (%s) connected.%d socks.(%d %d) amlp.%d\n",keystr,retstr,swap->connected,swap->pushsock,swap->subsock,amlp); - free(retstr); - } - printf("connected.%d amlp.%d subsock.%d pushsock.%d\n",swap->connected,amlp,subsock,pushsock); - if ( swap->connected <= 0 && amlp != 0 && subsock >= 0 && pushsock >= 0 ) - { - if ( (retstr= _dex_psock("{}")) != 0 ) - { - printf("psock returns.(%s)\n",retstr); - // {"result":"success","pushaddr":"tcp://5.9.102.210:30002","subaddr":"tcp://5.9.102.210:30003","randipbits":3606291758,"coin":"KMD","tag":"6952562460568228137"} - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - pushaddr = jstr(retjson,"pushaddr"); - subaddr = jstr(retjson,"subaddr"); - if ( pushaddr != 0 && subaddr != 0 ) - { - if ( nn_connect(pushsock,pushaddr) >= 0 ) - { - printf("connected to %d pushaddr.(%s)\n",pushsock,pushaddr); - if ( nn_connect(subsock,subaddr) >= 0 ) - { - swap->connected = 1; - init_hexbytes_noT(pubkeystr,myinfo->persistent_pubkey33,33); - sprintf((char *)data,"{\"push\":\"%s\",\"sub\":\"%s\",\"trade\":[\"%s\", %.8f, \"%s\", %.8f],\"pub\":\"%s\"}",pushaddr,subaddr,swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount),pubkeystr); - datalen = (int32_t)strlen((char *)data) + 1; - printf("datalen.%d (%s)\n",datalen,(char *)data); - init_hexbytes_noT(databuf,data,datalen); - printf("%s -> %s\n",keystr,databuf); - if ( (retstr2= _dex_kvupdate("KV",keystr,databuf,1)) != 0 ) - { - printf("KVupdate.(%s)\n",retstr2); - free(retstr2); - } - } else printf("nn_connect error to %d subaddr.(%s)\n",subsock,subaddr); - } else printf("nn_connect error to %d pushaddr.(%s)\n",pushsock,pushaddr); - } - else printf("missing addr (%p) (%p) (%s)\n",pushaddr,subaddr,jprint(retjson,0)); - free_json(retjson); - } else printf("Error parsing psock.(%s)\n",retstr); - free(retstr); - } else printf("error issuing _dex_psock\n"); - }*/ -} - char *nanomsg_tcpname(char *str,char *ipaddr,uint16_t port) { sprintf(str,"tcp://%s:%u",ipaddr,port); @@ -168,144 +80,3 @@ uint32_t LP_swapsend(int32_t pairsock,struct basilisk_swap *swap,uint32_t msgbit free(buf); return(nextbits); } - -void basilisk_swap_sendabort(struct basilisk_swap *swap) -{ - uint32_t msgbits = 0; uint8_t buf[sizeof(msgbits) + sizeof(swap->I.req.quoteid) + sizeof(bits256)*2]; int32_t sentbytes,offset=0; - memset(buf,0,sizeof(buf)); - offset += iguana_rwnum(1,&buf[offset],sizeof(swap->I.req.quoteid),&swap->I.req.quoteid); - offset += iguana_rwnum(1,&buf[offset],sizeof(msgbits),&msgbits); - if ( (sentbytes= nn_send(swap->pushsock,buf,offset,0)) != offset ) - { - if ( sentbytes < 0 ) - { - if ( swap->pushsock >= 0 ) // - nn_close(swap->pushsock), swap->pushsock = -1; - if ( swap->subsock >= 0 ) // - nn_close(swap->subsock), swap->subsock = -1; - swap->connected = 0; - } - } else printf("basilisk_swap_sendabort\n"); -} - -void basilisk_psockinit(struct basilisk_swap *swap,int32_t amlp); - -void basilisk_swapgotdata(struct basilisk_swap *swap,uint32_t crc32,bits256 srchash,bits256 desthash,uint32_t quoteid,uint32_t msgbits,uint8_t *data,int32_t datalen,int32_t reinit) -{ - int32_t i; struct basilisk_swapmessage *mp; - for (i=0; inummessages; i++) - if ( crc32 == swap->messages[i].crc32 && msgbits == swap->messages[i].msgbits && bits256_cmp(srchash,swap->messages[i].srchash) == 0 && bits256_cmp(desthash,swap->messages[i].desthash) == 0 ) - return; - //printf(" new message.[%d] datalen.%d Q.%x msg.%x [%llx]\n",swap->nummessages,datalen,quoteid,msgbits,*(long long *)data); - swap->messages = realloc(swap->messages,sizeof(*swap->messages) * (swap->nummessages + 1)); - mp = &swap->messages[swap->nummessages++]; - mp->crc32 = crc32; - mp->srchash = srchash; - mp->desthash = desthash; - mp->msgbits = msgbits; - mp->quoteid = quoteid; - mp->data = malloc(datalen); - mp->datalen = datalen; - memcpy(mp->data,data,datalen); - if ( reinit == 0 && swap->fp != 0 ) - { - fwrite(mp,1,sizeof(*mp),swap->fp); - fwrite(data,1,datalen,swap->fp); - fflush(swap->fp); - } -} - -int32_t basilisk_swapget(struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,int32_t (*basilisk_verify_func)(void *ptr,uint8_t *data,int32_t datalen)) -{ - uint8_t *ptr; bits256 srchash,desthash; uint32_t crc32,_msgbits,quoteid; int32_t i,size,offset,retval = -1; struct basilisk_swapmessage *mp = 0; - while ( (size= nn_recv(swap->subsock,&ptr,NN_MSG,0)) >= 0 ) - { - swap->lasttime = (uint32_t)time(NULL); - memset(srchash.bytes,0,sizeof(srchash)); - memset(desthash.bytes,0,sizeof(desthash)); - //printf("gotmsg.[%d] crc.%x\n",size,crc32); - offset = 0; - for (i=0; i<32; i++) - srchash.bytes[i] = ptr[offset++]; - for (i=0; i<32; i++) - desthash.bytes[i] = ptr[offset++]; - offset += iguana_rwnum(0,&ptr[offset],sizeof(uint32_t),"eid); - offset += iguana_rwnum(0,&ptr[offset],sizeof(uint32_t),&_msgbits); - if ( size > offset ) - { - crc32 = calc_crc32(0,&ptr[offset],size-offset); - if ( size > offset ) - { - //printf("size.%d offset.%d datalen.%d\n",size,offset,size-offset); - basilisk_swapgotdata(swap,crc32,srchash,desthash,quoteid,_msgbits,&ptr[offset],size-offset,0); - } - } - else if ( bits256_nonz(srchash) == 0 && bits256_nonz(desthash) == 0 ) - { - if ( swap->aborted == 0 ) - { - swap->aborted = (uint32_t)time(NULL); - printf("got abort signal from other side\n"); - } - } else printf("basilisk_swapget: got strange packet\n"); - if ( ptr != 0 ) - nn_freemsg(ptr), ptr = 0; - } - //char str[65],str2[65]; - for (i=0; inummessages; i++) - { - //printf("%d: %s vs %s\n",i,bits256_str(str,swap->messages[i].srchash),bits256_str(str2,swap->messages[i].desthash)); - if ( bits256_cmp(swap->messages[i].desthash,swap->I.myhash) == 0 ) - { - if ( swap->messages[i].msgbits == msgbits ) - { - if ( swap->I.iambob == 0 && swap->lasttime != 0 && time(NULL) > swap->lasttime+360 ) - { - printf("nothing received for a while from Bob, try new sockets\n"); - if ( swap->pushsock >= 0 ) // - nn_close(swap->pushsock), swap->pushsock = -1; - if ( swap->subsock >= 0 ) // - nn_close(swap->subsock), swap->subsock = -1; - swap->connected = 0; - basilisk_psockinit(swap,swap->I.iambob != 0); - } - mp = &swap->messages[i]; - if ( msgbits != 0x80000000 ) - break; - } - } - } - if ( mp != 0 ) - retval = (*basilisk_verify_func)(swap,mp->data,mp->datalen); - //printf("mine/other %s vs %s\n",bits256_str(str,swap->I.myhash),bits256_str(str2,swap->I.otherhash)); - return(retval); -} - -int32_t basilisk_messagekeyread(uint8_t *key,uint32_t *channelp,uint32_t *msgidp,bits256 *srchashp,bits256 *desthashp) -{ - int32_t keylen = 0; - keylen += iguana_rwnum(0,&key[keylen],sizeof(uint32_t),channelp); - keylen += iguana_rwnum(0,&key[keylen],sizeof(uint32_t),msgidp); - keylen += iguana_rwbignum(0,&key[keylen],sizeof(*srchashp),srchashp->bytes); - keylen += iguana_rwbignum(0,&key[keylen],sizeof(*desthashp),desthashp->bytes); - return(keylen); -} - -int32_t basilisk_messagekey(uint8_t *key,uint32_t channel,uint32_t msgid,bits256 srchash,bits256 desthash) -{ - int32_t keylen = 0; - keylen += iguana_rwnum(1,&key[keylen],sizeof(uint32_t),&channel); - keylen += iguana_rwnum(1,&key[keylen],sizeof(uint32_t),&msgid); - keylen += iguana_rwbignum(1,&key[keylen],sizeof(srchash),srchash.bytes); - keylen += iguana_rwbignum(1,&key[keylen],sizeof(desthash),desthash.bytes); - return(keylen); -} - -void LP_channelsend(bits256 srchash,bits256 desthash,uint32_t channel,uint32_t msgid,uint8_t *data,int32_t datalen) -{ - int32_t keylen; uint8_t key[BASILISK_KEYSIZE]; //char *retstr; - keylen = basilisk_messagekey(key,channel,msgid,srchash,desthash); - //if ( (retstr= _dex_reqsend(myinfo,"DEX",key,keylen,data,datalen)) != 0 ) - // free(retstr); -} - diff --git a/iguana/exchanges/LP_peers.c b/iguana/exchanges/LP_peers.c new file mode 100644 index 000000000..e7d83a93e --- /dev/null +++ b/iguana/exchanges/LP_peers.c @@ -0,0 +1,188 @@ + +/****************************************************************************** + * 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_peers.c +// marketmaker +// + +struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port) +{ + struct LP_peerinfo *peer=0; uint64_t ip_port; + ip_port = ((uint64_t)port << 32) | ipbits; + portable_mutex_lock(&LP_peermutex); + HASH_FIND(hh,LP_peerinfos,&ip_port,sizeof(ip_port),peer); + portable_mutex_unlock(&LP_peermutex); + return(peer); +} + +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); + return(item); +} + +char *LP_peers() +{ + struct LP_peerinfo *peer,*tmp; cJSON *peersjson = cJSON_CreateArray(); + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + jaddi(peersjson,LP_peerjson(peer)); + } + return(jprint(peersjson,1)); +} + +struct LP_peerinfo *LP_addpeer(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *ipaddr,uint16_t port,uint16_t pushport,uint16_t subport,double profitmargin,int32_t numpeers,int32_t numutxos) +{ + uint32_t ipbits; int32_t pushsock,subsock,timeout,enabled; char checkip[64],pushaddr[64],subaddr[64]; struct LP_peerinfo *peer = 0; + ipbits = (uint32_t)calc_ipbits(ipaddr); + expand_ipbits(checkip,ipbits); + if ( strcmp(checkip,ipaddr) == 0 ) + { + if ( (peer= LP_peerfind(ipbits,port)) != 0 ) + { + if ( peer->profitmargin == 0. ) + peer->profitmargin = profitmargin; + if ( numpeers > peer->numpeers ) + peer->numpeers = numpeers; + if ( numutxos > peer->numutxos ) + peer->numutxos = numutxos; + } + else + { + //printf("LPaddpeer %s\n",ipaddr); + peer = calloc(1,sizeof(*peer)); + peer->pushsock = peer->subsock = pushsock = subsock = -1; + strcpy(peer->ipaddr,ipaddr); + if ( amclient == 0 ) + enabled = 1; + else enabled = 1;//(rand() % (1 << Client_connections)) == 0; + if ( pushport != 0 && subport != 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 ) + { + timeout = 1000; + nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); + nanomsg_tcpname(pushaddr,peer->ipaddr,pushport); + if ( nn_connect(pushsock,pushaddr) >= 0 ) + { + printf("connected to push.(%s) %d\n",pushaddr,pushsock); + peer->connected = (uint32_t)time(NULL); + peer->pushsock = pushsock; + if ( enabled != 0 && (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 ) + { + timeout = 1; + nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)); + nn_setsockopt(subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); + nanomsg_tcpname(subaddr,peer->ipaddr,subport); + if ( nn_connect(subsock,subaddr) >= 0 ) + { + peer->subsock = subsock; + printf("connected to sub.(%s) %d\n",subaddr,peer->subsock); + Client_connections += amclient; + } else nn_close(subsock); + } + } + else + { + nn_close(pushsock); + 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->ipbits = ipbits; + peer->port = port; + peer->ip_port = ((uint64_t)port << 32) | ipbits; + portable_mutex_lock(&LP_peermutex); + HASH_ADD(hh,LP_peerinfos,ip_port,sizeof(peer->ip_port),peer); + if ( mypeer != 0 ) + { + mypeer->numpeers++; + 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 ) + LP_send(mypubsock,jprint(LP_peerjson(peer),1),1); + } + } else printf("LP_addpeer: checkip.(%s) vs (%s)\n",checkip,ipaddr); + return(peer); +} + +int32_t LP_peersparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now) +{ + struct LP_peerinfo *peer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; + if ( (array= cJSON_Parse(retstr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; ilasttime = now; + if ( strcmp(argipaddr,destipaddr) == 0 && destport == argport && peer->numpeers != n ) + peer->numpeers = n; + } + } + } + } + free_json(array); + } + return(n); +} + +void LP_peersquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *myipaddr,uint16_t myport,double myprofit) +{ + char *retstr; struct LP_peerinfo *peer,*tmp; uint32_t now,flag = 0; + peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); + if ( peer != 0 && peer->errors > 0 ) + return; + if ( (retstr= issue_LP_getpeers(destipaddr,destport,myipaddr,myport,myprofit,mypeer!=0?mypeer->numpeers:0,mypeer!=0?mypeer->numutxos:0)) != 0 ) + { + //printf("got.(%s)\n",retstr); + now = (uint32_t)time(NULL); + LP_peersparse(amclient,mypeer,mypubsock,destipaddr,destport,retstr,now); + free(retstr); + if ( amclient == 0 ) + { + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + if ( peer->lasttime != now ) + { + printf("{%s:%u %.6f}.%d ",peer->ipaddr,peer->port,peer->profitmargin,peer->lasttime - now); + flag++; + if ( (retstr= issue_LP_notify(destipaddr,destport,peer->ipaddr,peer->port,peer->profitmargin,peer->numpeers,0)) != 0 ) + free(retstr); + } + } + if ( flag != 0 ) + printf(" <- missing peers\n"); + } + } else if ( peer != 0 ) + peer->errors++; +} diff --git a/iguana/exchanges/LP_prices.c b/iguana/exchanges/LP_prices.c index 4d1fff738..37cd3275c 100644 --- a/iguana/exchanges/LP_prices.c +++ b/iguana/exchanges/LP_prices.c @@ -20,8 +20,168 @@ double LP_kmdbtc; +struct LP_cacheinfo +{ + UT_hash_handle hh; + struct LP_quoteinfo Q; + uint8_t key[sizeof(bits256)+sizeof(uint64_t)*2+sizeof(int32_t)]; + double price; + uint32_t timestamp; +} *LP_cacheinfos; + +int32_t LP_cachekey(uint8_t *key,char *base,char *rel,bits256 txid,int32_t vout) +{ + uint64_t basebits,relbits; int32_t offset = 0; + basebits = stringbits(base); + relbits = stringbits(rel); + memcpy(&key[offset],&basebits,sizeof(basebits)), offset += sizeof(basebits); + memcpy(&key[offset],&relbits,sizeof(relbits)), offset += sizeof(relbits); + memcpy(&key[offset],&txid,sizeof(txid)), offset += sizeof(txid); + memcpy(&key[offset],&vout,sizeof(vout)), offset += sizeof(vout); + return(offset); +} + +struct LP_cacheinfo *LP_cachefind(char *base,char *rel,bits256 txid,int32_t vout) +{ + struct LP_cacheinfo *ptr=0; uint8_t key[sizeof(bits256)+sizeof(uint64_t)*2+sizeof(vout)]; + if ( LP_cachekey(key,base,rel,txid,vout) == sizeof(key) ) + { + portable_mutex_lock(&LP_cachemutex); + HASH_FIND(hh,LP_cacheinfos,key,sizeof(key),ptr); + portable_mutex_unlock(&LP_cachemutex); + } else printf("LP_cachefind keysize mismatch?\n"); + if ( 0 && ptr != 0 && ptr->timestamp != 0 && ptr->timestamp < time(NULL)-LP_CACHEDURATION ) + { + printf("expire price %.8f\n",ptr->price); + ptr->price = 0.; + ptr->timestamp = 0; + memset(&ptr->Q,0,sizeof(ptr->Q)); + } + return(ptr); +} + +double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,int32_t vout) +{ + struct LP_cacheinfo *ptr; + if ( (ptr= LP_cachefind(base,rel,txid,vout)) != 0 ) + { + if ( qp != 0 ) + (*qp) = ptr->Q; + if ( ptr->price == 0. && ptr->Q.satoshis != 0 ) + { + printf("null ptr->price? "); + ptr->price = (double)ptr->Q.destsatoshis / ptr->Q.satoshis; + } + //printf("found %s/%s %.8f\n",base,rel,ptr->price); + return(ptr->price); + } + //char str[65]; printf("cachemiss %s/%s %s/v%d\n",base,rel,bits256_str(str,txid),vout); + return(0.); +} + +struct LP_cacheinfo *LP_cacheadd(char *base,char *rel,bits256 txid,int32_t vout,double price,struct LP_quoteinfo *qp) +{ + char str[65]; struct LP_cacheinfo *ptr=0; + if ( (ptr= LP_cachefind(base,rel,txid,vout)) == 0 ) + { + 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"); + } + if ( price != ptr->price ) + { + printf("updated %s/v%d %s/%s %llu price %.8f\n",bits256_str(str,txid),vout,base,rel,(long long)qp->satoshis,price); + } + ptr->price = price; + ptr->Q = *qp; + ptr->timestamp = (uint32_t)time(NULL); + return(ptr); +} + +static int _cmp_orderbook(const void *a,const void *b) +{ +#define ptr_a ((struct LP_cacheinfo *)a)->price +#define ptr_b ((struct LP_cacheinfo *)b)->price + if ( ptr_b > ptr_a ) + return(1); + else if ( ptr_b < ptr_a ) + return(-1); + else + { +#undef ptr_a +#undef ptr_b +#define ptr_a ((struct LP_cacheinfo *)a)->Q.satoshis +#define ptr_b ((struct LP_cacheinfo *)b)->Q.satoshis + if ( ptr_b > ptr_a ) + return(1); + else if ( ptr_b < ptr_a ) + return(-1); + } + return(0); +#undef ptr_a +#undef ptr_b +} + +static int _cmp_orderbookrev(const void *a,const void *b) +{ + return(-_cmp_orderbook(a,b)); +} + +cJSON *LP_orderbookjson(struct LP_cacheinfo *ptr,int32_t polarity) +{ + double price,volume; cJSON *item = cJSON_CreateObject(); + if ( (price= ptr->price) != 0. && (volume= dstr(ptr->Q.satoshis)) != 0. ) + { + jaddnum(item,"price",polarity > 0 ? price : 1. / price); + jaddnum(item,"volume",polarity > 0 ? volume : volume / price); + jaddbits256(item,"txid",ptr->Q.txid); + jaddnum(item,"vout",ptr->Q.vout); + } + return(item); +} + +char *LP_orderbook(char *base,char *rel) +{ + uint32_t now,i; struct LP_cacheinfo *ptr,*tmp,**bids = 0,**asks = 0; cJSON *retjson,*array; int32_t numbids=0,numasks=0; + now = (uint32_t)time(NULL); + HASH_ITER(hh,LP_cacheinfos,ptr,tmp) + { + if ( ptr->timestamp < now-60 || ptr->price == 0. ) + continue; + if ( strcmp(ptr->Q.srccoin,base) == 0 && strcmp(ptr->Q.destcoin,rel) == 0 ) + { + asks = realloc(asks,sizeof(*asks) * (numasks+1)); + asks[numasks++] = ptr; + } + else if ( strcmp(ptr->Q.srccoin,rel) == 0 && strcmp(ptr->Q.destcoin,base) == 0 ) + { + bids = realloc(bids,sizeof(*bids) * (numbids+1)); + bids[numbids++] = ptr; + } + } + retjson = cJSON_CreateObject(); + array = cJSON_CreateArray(); + if ( numbids > 1 ) + qsort(bids,numbids,sizeof(*bids),_cmp_orderbook); + for (i=0; i 1 ) + qsort(asks,numasks,sizeof(*asks),_cmp_orderbookrev); + for (i=0; iswapsfp= fopen(fname,"rb+")) != 0 ) - { - while ( fread(&requestid,1,sizeof(requestid),myinfo->swapsfp) == sizeof(requestid) && fread("eid,1,sizeof(quoteid),myinfo->swapsfp) == sizeof(quoteid) ) - { - sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname); - printf("%s\n",fname); - if ( (fp= fopen(fname,"rb+")) != 0 ) // check to see if completed - { - memset(&M,0,sizeof(M)); - swapcompleted = 1; - for (iter=0; iter<2; iter++) - { - if ( fread(privkey.bytes,1,sizeof(privkey),fp) == sizeof(privkey) && - fread(&R,1,sizeof(R),fp) == sizeof(R) && - fread(&statebits,1,sizeof(statebits),fp) == sizeof(statebits) && - fread(&optionduration,1,sizeof(optionduration),fp) == sizeof(optionduration) ) - { - while ( 0 && fread(&M,1,sizeof(M),fp) == sizeof(M) ) - { - M.data = 0; - //printf("entry iter.%d crc32.%x datalen.%d\n",iter,M.crc32,M.datalen); - if ( M.datalen < 100000 ) - { - M.data = malloc(M.datalen); - if ( fread(M.data,1,M.datalen,fp) == M.datalen ) - { - if ( calc_crc32(0,M.data,M.datalen) == M.crc32 ) - { - if ( iter == 1 ) - { - if ( swap == 0 ) - { - swap = basilisk_thread_start(privkey,&R,statebits,optionduration,1); - swap->I.choosei = swap->I.otherchoosei = -1; - } - if ( swap != 0 ) - basilisk_swapgotdata(swap,M.crc32,M.srchash,M.desthash,M.quoteid,M.msgbits,M.data,M.datalen,1); - } - } else printf("crc mismatch %x vs %x\n",calc_crc32(0,M.data,M.datalen),M.crc32); - } else printf("error reading M.datalen %d\n",M.datalen); - free(M.data), M.data = 0; - } - } - } - if ( swapcompleted != 0 ) - break; - rewind(fp); - } - } - } - } else myinfo->swapsfp = fopen(fname,"wb+"); -}*/ - -FILE *basilisk_swap_save(struct basilisk_swap *swap,bits256 privkey,struct basilisk_request *rp,uint32_t statebits,int32_t optionduration,int32_t reinit) -{ - FILE *fp=0; /*char fname[512]; - sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,rp->requestid,rp->quoteid), OS_compatible_path(fname); - if ( (fp= fopen(fname,"rb+")) == 0 ) - { - if ( (fp= fopen(fname,"wb+")) != 0 ) - { - fwrite(privkey.bytes,1,sizeof(privkey),fp); - fwrite(rp,1,sizeof(*rp),fp); - fwrite(&statebits,1,sizeof(statebits),fp); - fwrite(&optionduration,1,sizeof(optionduration),fp); - fflush(fp); - } - } - else if ( reinit != 0 ) - { - }*/ - return(fp); -} - -int32_t basilisk_swap_load(uint32_t requestid,uint32_t quoteid,bits256 *privkeyp,struct basilisk_request *rp,uint32_t *statebitsp,int32_t *optiondurationp) -{ - FILE *fp=0; char fname[512]; int32_t retval = -1; - sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname); - if ( (fp= fopen(fname,"rb+")) != 0 ) - { - if ( fread(privkeyp,1,sizeof(*privkeyp),fp) == sizeof(*privkeyp) && - fread(rp,1,sizeof(*rp),fp) == sizeof(*rp) && - fread(statebitsp,1,sizeof(*statebitsp),fp) == sizeof(*statebitsp) && - fread(optiondurationp,1,sizeof(*optiondurationp),fp) == sizeof(*optiondurationp) ) - retval = 0; - fclose(fp); - } - return(retval); -} - -void basilisk_swap_saveupdate(struct basilisk_swap *swap) -{ - FILE *fp; char fname[512]; - sprintf(fname,"%s/SWAPS/%u-%u.swap",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid), OS_compatible_path(fname); - if ( (fp= fopen(fname,"wb")) != 0 ) - { - fwrite(&swap->I,1,sizeof(swap->I),fp); - /*fwrite(&swap->bobdeposit,1,sizeof(swap->bobdeposit),fp); - fwrite(&swap->bobpayment,1,sizeof(swap->bobpayment),fp); - fwrite(&swap->alicepayment,1,sizeof(swap->alicepayment),fp); - fwrite(&swap->myfee,1,sizeof(swap->myfee),fp); - fwrite(&swap->otherfee,1,sizeof(swap->otherfee),fp); - fwrite(&swap->aliceclaim,1,sizeof(swap->aliceclaim),fp); - fwrite(&swap->alicespend,1,sizeof(swap->alicespend),fp); - fwrite(&swap->bobreclaim,1,sizeof(swap->bobreclaim),fp); - fwrite(&swap->bobspend,1,sizeof(swap->bobspend),fp); - fwrite(&swap->bobrefund,1,sizeof(swap->bobrefund),fp); - fwrite(&swap->alicereclaim,1,sizeof(swap->alicereclaim),fp);*/ - fwrite(swap->privkeys,1,sizeof(swap->privkeys),fp); - fwrite(swap->otherdeck,1,sizeof(swap->otherdeck),fp); - fwrite(swap->deck,1,sizeof(swap->deck),fp); - fclose(fp); - } -} - -/*int32_t basilisk_swap_loadtx(struct basilisk_rawtx *rawtx,FILE *fp,char *bobcoinstr,char *alicecoinstr) -{ - if ( fread(rawtx,1,sizeof(*rawtx),fp) == sizeof(*rawtx) ) - { - rawtx->coin = 0; - rawtx->vins = 0; - if ( strcmp(rawtx->I.coinstr,bobcoinstr) == 0 || strcmp(rawtx->I.coinstr,alicecoinstr) == 0 ) - { - rawtx->coin = LP_coinfind(rawtx->I.coinstr); - if ( rawtx->vinstr[0] != 0 ) - rawtx->vins = cJSON_Parse(rawtx->vinstr); - printf("loaded.%s len.%d\n",rawtx->name,rawtx->I.datalen); - return(0); - } - } - return(-1); -}*/ - void basilisk_dontforget_userdata(char *userdataname,FILE *fp,uint8_t *script,int32_t scriptlen) { int32_t i; char scriptstr[513]; @@ -350,8 +213,6 @@ void basilisk_dontforget_update(struct basilisk_swap *swap,struct basilisk_rawtx basilisk_dontforget(swap,&swap->bobreclaim,swap->bobpayment.I.locktime,triggertxid); } - - bits256 basilisk_swap_privbob_extract(char *symbol,bits256 spendtxid,int32_t vini,int32_t revflag) { bits256 privkey; int32_t i,scriptlen,siglen; uint8_t script[1024]; // from Bob refund of Bob deposit diff --git a/iguana/exchanges/LP_rpc.c b/iguana/exchanges/LP_rpc.c index d3742e5e0..ed3784b55 100644 --- a/iguana/exchanges/LP_rpc.c +++ b/iguana/exchanges/LP_rpc.c @@ -17,31 +17,45 @@ // LP_rpc.c // marketmaker // +char *issue_LP_getpeers(char *destip,uint16_t destport,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos) +{ + char url[512],*retstr; + sprintf(url,"http://%s:%u/api/stats/getpeers?ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,profitmargin,numpeers,numutxos); + //printf("send.(%s)\n",url); + retstr = issue_curl(url); + //printf("GETPEERS.(%s)\n",retstr); + return(retstr); +} -char *LP_getdatadir() +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) { - return("/root"); + char url[512]; + sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,coin,lastn,ipaddr,port,profitmargin,numpeers,numutxos); + return(issue_curl(url)); } -cJSON *basilisk_nullretjson(cJSON *retjson) +char *issue_LP_clientgetutxos(char *destip,uint16_t destport,char *coin,int32_t lastn) { - /*char *outstr; - if ( retjson != 0 ) - { - outstr = jprint(retjson,0); - if ( strcmp(outstr,"{}") == 0 || strcmp(outstr,"[]") == 0 ) - { - free_json(retjson); - retjson = 0; - } - free(outstr); - }*/ - return(retjson); + char url[512]; + sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=127.0.0.1&port=0",destip,destport,coin,lastn); + //printf("getutxos.(%s)\n",url); + return(issue_curl(url)); } -char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_t skip) +char *issue_LP_notify(char *destip,uint16_t destport,char *ipaddr,uint16_t port,double profitmargin,int32_t numpeers,int32_t numutxos) { - return(0); + char url[512]; + sprintf(url,"http://%s:%u/api/stats/notify?ipaddr=%s&port=%u&profit=%.6f&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,profitmargin,numpeers,numutxos); + return(issue_curl(url)); +} + +char *issue_LP_notifyutxo(char *destip,uint16_t destport,struct LP_utxoinfo *utxo) +{ + char url[4096],str[65],str2[65]; + sprintf(url,"http://%s:%u/api/stats/notifyutxo?ipaddr=%s&port=%u&profit=%.6f&coin=%s&txid=%s&vout=%d&value=%.8f&txid2=%s&vout2=%d&value2=%.8f&script=%s&address=%s",destip,destport,utxo->ipaddr,utxo->port,utxo->profitmargin,utxo->coin,bits256_str(str,utxo->txid),utxo->vout,dstr(utxo->satoshis),bits256_str(str2,utxo->txid2),utxo->vout2,dstr(utxo->satoshis2),utxo->spendscript,utxo->coinaddr); + if ( strlen(url) > 1024 ) + printf("WARNING long url.(%s)\n",url); + return(issue_curl(url)); } cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params) @@ -59,7 +73,7 @@ cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params) } //printf("dpow_gettxout.(%s)\n",retstr); } - return(basilisk_nullretjson(retjson)); + return(retjson); } void LP_unspents_mark(char *symbol,cJSON *vins) diff --git a/iguana/exchanges/LP_statemachine.c b/iguana/exchanges/LP_statemachine.c index 9b4604c25..dc0240c1b 100644 --- a/iguana/exchanges/LP_statemachine.c +++ b/iguana/exchanges/LP_statemachine.c @@ -17,6 +17,317 @@ // LP_statemachine.c // marketmaker // + +/*void basilisk_swaps_init(struct supernet_info *myinfo) + { + char fname[512]; uint32_t iter,swapcompleted,requestid,quoteid,optionduration,statebits; FILE *fp; bits256 privkey;struct basilisk_request R; struct basilisk_swapmessage M; struct basilisk_swap *swap = 0; + sprintf(fname,"%s/SWAPS/list",GLOBAL_DBDIR), OS_compatible_path(fname); + if ( (myinfo->swapsfp= fopen(fname,"rb+")) != 0 ) + { + while ( fread(&requestid,1,sizeof(requestid),myinfo->swapsfp) == sizeof(requestid) && fread("eid,1,sizeof(quoteid),myinfo->swapsfp) == sizeof(quoteid) ) + { + sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname); + printf("%s\n",fname); + if ( (fp= fopen(fname,"rb+")) != 0 ) // check to see if completed + { + memset(&M,0,sizeof(M)); + swapcompleted = 1; + for (iter=0; iter<2; iter++) + { + if ( fread(privkey.bytes,1,sizeof(privkey),fp) == sizeof(privkey) && + fread(&R,1,sizeof(R),fp) == sizeof(R) && + fread(&statebits,1,sizeof(statebits),fp) == sizeof(statebits) && + fread(&optionduration,1,sizeof(optionduration),fp) == sizeof(optionduration) ) + { + while ( 0 && fread(&M,1,sizeof(M),fp) == sizeof(M) ) + { + M.data = 0; + //printf("entry iter.%d crc32.%x datalen.%d\n",iter,M.crc32,M.datalen); + if ( M.datalen < 100000 ) + { + M.data = malloc(M.datalen); + if ( fread(M.data,1,M.datalen,fp) == M.datalen ) + { + if ( calc_crc32(0,M.data,M.datalen) == M.crc32 ) + { + if ( iter == 1 ) + { + if ( swap == 0 ) + { + swap = basilisk_thread_start(privkey,&R,statebits,optionduration,1); + swap->I.choosei = swap->I.otherchoosei = -1; + } + if ( swap != 0 ) + basilisk_swapgotdata(swap,M.crc32,M.srchash,M.desthash,M.quoteid,M.msgbits,M.data,M.datalen,1); + } + } else printf("crc mismatch %x vs %x\n",calc_crc32(0,M.data,M.datalen),M.crc32); + } else printf("error reading M.datalen %d\n",M.datalen); + free(M.data), M.data = 0; + } + } + } + if ( swapcompleted != 0 ) + break; + rewind(fp); + } + } + } + } else myinfo->swapsfp = fopen(fname,"wb+"); + }*/ + +FILE *basilisk_swap_save(struct basilisk_swap *swap,bits256 privkey,struct basilisk_request *rp,uint32_t statebits,int32_t optionduration,int32_t reinit) +{ + FILE *fp=0; /*char fname[512]; + sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,rp->requestid,rp->quoteid), OS_compatible_path(fname); + if ( (fp= fopen(fname,"rb+")) == 0 ) + { + if ( (fp= fopen(fname,"wb+")) != 0 ) + { + fwrite(privkey.bytes,1,sizeof(privkey),fp); + fwrite(rp,1,sizeof(*rp),fp); + fwrite(&statebits,1,sizeof(statebits),fp); + fwrite(&optionduration,1,sizeof(optionduration),fp); + fflush(fp); + } + } + else if ( reinit != 0 ) + { + }*/ + return(fp); +} + +int32_t basilisk_swap_load(uint32_t requestid,uint32_t quoteid,bits256 *privkeyp,struct basilisk_request *rp,uint32_t *statebitsp,int32_t *optiondurationp) +{ + FILE *fp=0; char fname[512]; int32_t retval = -1; + sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname); + if ( (fp= fopen(fname,"rb+")) != 0 ) + { + if ( fread(privkeyp,1,sizeof(*privkeyp),fp) == sizeof(*privkeyp) && + fread(rp,1,sizeof(*rp),fp) == sizeof(*rp) && + fread(statebitsp,1,sizeof(*statebitsp),fp) == sizeof(*statebitsp) && + fread(optiondurationp,1,sizeof(*optiondurationp),fp) == sizeof(*optiondurationp) ) + retval = 0; + fclose(fp); + } + return(retval); +} + +void basilisk_swap_saveupdate(struct basilisk_swap *swap) +{ + FILE *fp; char fname[512]; + sprintf(fname,"%s/SWAPS/%u-%u.swap",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid), OS_compatible_path(fname); + if ( (fp= fopen(fname,"wb")) != 0 ) + { + fwrite(&swap->I,1,sizeof(swap->I),fp); + /*fwrite(&swap->bobdeposit,1,sizeof(swap->bobdeposit),fp); + fwrite(&swap->bobpayment,1,sizeof(swap->bobpayment),fp); + fwrite(&swap->alicepayment,1,sizeof(swap->alicepayment),fp); + fwrite(&swap->myfee,1,sizeof(swap->myfee),fp); + fwrite(&swap->otherfee,1,sizeof(swap->otherfee),fp); + fwrite(&swap->aliceclaim,1,sizeof(swap->aliceclaim),fp); + fwrite(&swap->alicespend,1,sizeof(swap->alicespend),fp); + fwrite(&swap->bobreclaim,1,sizeof(swap->bobreclaim),fp); + fwrite(&swap->bobspend,1,sizeof(swap->bobspend),fp); + fwrite(&swap->bobrefund,1,sizeof(swap->bobrefund),fp); + fwrite(&swap->alicereclaim,1,sizeof(swap->alicereclaim),fp);*/ + fwrite(swap->privkeys,1,sizeof(swap->privkeys),fp); + fwrite(swap->otherdeck,1,sizeof(swap->otherdeck),fp); + fwrite(swap->deck,1,sizeof(swap->deck),fp); + fclose(fp); + } +} + +/*int32_t basilisk_swap_loadtx(struct basilisk_rawtx *rawtx,FILE *fp,char *bobcoinstr,char *alicecoinstr) + { + if ( fread(rawtx,1,sizeof(*rawtx),fp) == sizeof(*rawtx) ) + { + rawtx->coin = 0; + rawtx->vins = 0; + if ( strcmp(rawtx->I.coinstr,bobcoinstr) == 0 || strcmp(rawtx->I.coinstr,alicecoinstr) == 0 ) + { + rawtx->coin = LP_coinfind(rawtx->I.coinstr); + if ( rawtx->vinstr[0] != 0 ) + rawtx->vins = cJSON_Parse(rawtx->vinstr); + printf("loaded.%s len.%d\n",rawtx->name,rawtx->I.datalen); + return(0); + } + } + return(-1); + }*/ + +void basilisk_swap_sendabort(struct basilisk_swap *swap) +{ + uint32_t msgbits = 0; uint8_t buf[sizeof(msgbits) + sizeof(swap->I.req.quoteid) + sizeof(bits256)*2]; int32_t sentbytes,offset=0; + memset(buf,0,sizeof(buf)); + offset += iguana_rwnum(1,&buf[offset],sizeof(swap->I.req.quoteid),&swap->I.req.quoteid); + offset += iguana_rwnum(1,&buf[offset],sizeof(msgbits),&msgbits); + if ( (sentbytes= nn_send(swap->pushsock,buf,offset,0)) != offset ) + { + if ( sentbytes < 0 ) + { + if ( swap->pushsock >= 0 ) // + nn_close(swap->pushsock), swap->pushsock = -1; + if ( swap->subsock >= 0 ) // + nn_close(swap->subsock), swap->subsock = -1; + swap->connected = 0; + } + } else printf("basilisk_swap_sendabort\n"); +} + +void basilisk_psockinit(struct basilisk_swap *swap,int32_t amlp); + +void basilisk_swapgotdata(struct basilisk_swap *swap,uint32_t crc32,bits256 srchash,bits256 desthash,uint32_t quoteid,uint32_t msgbits,uint8_t *data,int32_t datalen,int32_t reinit) +{ + int32_t i; struct basilisk_swapmessage *mp; + for (i=0; inummessages; i++) + if ( crc32 == swap->messages[i].crc32 && msgbits == swap->messages[i].msgbits && bits256_cmp(srchash,swap->messages[i].srchash) == 0 && bits256_cmp(desthash,swap->messages[i].desthash) == 0 ) + return; + //printf(" new message.[%d] datalen.%d Q.%x msg.%x [%llx]\n",swap->nummessages,datalen,quoteid,msgbits,*(long long *)data); + swap->messages = realloc(swap->messages,sizeof(*swap->messages) * (swap->nummessages + 1)); + mp = &swap->messages[swap->nummessages++]; + mp->crc32 = crc32; + mp->srchash = srchash; + mp->desthash = desthash; + mp->msgbits = msgbits; + mp->quoteid = quoteid; + mp->data = malloc(datalen); + mp->datalen = datalen; + memcpy(mp->data,data,datalen); + if ( reinit == 0 && swap->fp != 0 ) + { + fwrite(mp,1,sizeof(*mp),swap->fp); + fwrite(data,1,datalen,swap->fp); + fflush(swap->fp); + } +} + +int32_t basilisk_swapget(struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,int32_t (*basilisk_verify_func)(void *ptr,uint8_t *data,int32_t datalen)) +{ + uint8_t *ptr; bits256 srchash,desthash; uint32_t crc32,_msgbits,quoteid; int32_t i,size,offset,retval = -1; struct basilisk_swapmessage *mp = 0; + while ( (size= nn_recv(swap->subsock,&ptr,NN_MSG,0)) >= 0 ) + { + swap->lasttime = (uint32_t)time(NULL); + memset(srchash.bytes,0,sizeof(srchash)); + memset(desthash.bytes,0,sizeof(desthash)); + //printf("gotmsg.[%d] crc.%x\n",size,crc32); + offset = 0; + for (i=0; i<32; i++) + srchash.bytes[i] = ptr[offset++]; + for (i=0; i<32; i++) + desthash.bytes[i] = ptr[offset++]; + offset += iguana_rwnum(0,&ptr[offset],sizeof(uint32_t),"eid); + offset += iguana_rwnum(0,&ptr[offset],sizeof(uint32_t),&_msgbits); + if ( size > offset ) + { + crc32 = calc_crc32(0,&ptr[offset],size-offset); + if ( size > offset ) + { + //printf("size.%d offset.%d datalen.%d\n",size,offset,size-offset); + basilisk_swapgotdata(swap,crc32,srchash,desthash,quoteid,_msgbits,&ptr[offset],size-offset,0); + } + } + else if ( bits256_nonz(srchash) == 0 && bits256_nonz(desthash) == 0 ) + { + if ( swap->aborted == 0 ) + { + swap->aborted = (uint32_t)time(NULL); + printf("got abort signal from other side\n"); + } + } else printf("basilisk_swapget: got strange packet\n"); + if ( ptr != 0 ) + nn_freemsg(ptr), ptr = 0; + } + //char str[65],str2[65]; + for (i=0; inummessages; i++) + { + //printf("%d: %s vs %s\n",i,bits256_str(str,swap->messages[i].srchash),bits256_str(str2,swap->messages[i].desthash)); + if ( bits256_cmp(swap->messages[i].desthash,swap->I.myhash) == 0 ) + { + if ( swap->messages[i].msgbits == msgbits ) + { + if ( swap->I.iambob == 0 && swap->lasttime != 0 && time(NULL) > swap->lasttime+360 ) + { + printf("nothing received for a while from Bob, try new sockets\n"); + if ( swap->pushsock >= 0 ) // + nn_close(swap->pushsock), swap->pushsock = -1; + if ( swap->subsock >= 0 ) // + nn_close(swap->subsock), swap->subsock = -1; + swap->connected = 0; + basilisk_psockinit(swap,swap->I.iambob != 0); + } + mp = &swap->messages[i]; + if ( msgbits != 0x80000000 ) + break; + } + } + } + if ( mp != 0 ) + retval = (*basilisk_verify_func)(swap,mp->data,mp->datalen); + //printf("mine/other %s vs %s\n",bits256_str(str,swap->I.myhash),bits256_str(str2,swap->I.otherhash)); + return(retval); +} + +int32_t basilisk_messagekeyread(uint8_t *key,uint32_t *channelp,uint32_t *msgidp,bits256 *srchashp,bits256 *desthashp) +{ + int32_t keylen = 0; + keylen += iguana_rwnum(0,&key[keylen],sizeof(uint32_t),channelp); + keylen += iguana_rwnum(0,&key[keylen],sizeof(uint32_t),msgidp); + keylen += iguana_rwbignum(0,&key[keylen],sizeof(*srchashp),srchashp->bytes); + keylen += iguana_rwbignum(0,&key[keylen],sizeof(*desthashp),desthashp->bytes); + return(keylen); +} + +int32_t basilisk_messagekey(uint8_t *key,uint32_t channel,uint32_t msgid,bits256 srchash,bits256 desthash) +{ + int32_t keylen = 0; + keylen += iguana_rwnum(1,&key[keylen],sizeof(uint32_t),&channel); + keylen += iguana_rwnum(1,&key[keylen],sizeof(uint32_t),&msgid); + keylen += iguana_rwbignum(1,&key[keylen],sizeof(srchash),srchash.bytes); + keylen += iguana_rwbignum(1,&key[keylen],sizeof(desthash),desthash.bytes); + return(keylen); +} + +void LP_channelsend(bits256 srchash,bits256 desthash,uint32_t channel,uint32_t msgid,uint8_t *data,int32_t datalen) +{ + int32_t keylen; uint8_t key[BASILISK_KEYSIZE]; //char *retstr; + keylen = basilisk_messagekey(key,channel,msgid,srchash,desthash); + //if ( (retstr= _dex_reqsend(myinfo,"DEX",key,keylen,data,datalen)) != 0 ) + // free(retstr); +} + + +#ifdef adfafds +void iguana_ensure_privkey(struct iguana_info *coin,bits256 privkey) +{ + uint8_t pubkey33[33]; struct iguana_waccount *wacct; struct iguana_waddress *waddr,addr; char coinaddr[128]; + bitcoin_pubkey33(swap->ctx,pubkey33,privkey); + bitcoin_address(coinaddr,coin->pubtype,pubkey33,33); + //printf("privkey for (%s)\n",coinaddr); + if ( myinfo->expiration != 0 && ((waddr= iguana_waddresssearch(&wacct,coinaddr)) == 0 || bits256_nonz(waddr->privkey) == 0) ) + { + if ( waddr == 0 ) + { + memset(&addr,0,sizeof(addr)); + iguana_waddresscalc(coin->pubtype,coin->wiftype,&addr,privkey); + if ( (wacct= iguana_waccountfind("default")) != 0 ) + waddr = iguana_waddressadd(coin,wacct,&addr,0); + } + if ( waddr != 0 ) + { + waddr->privkey = privkey; + if ( bitcoin_priv2wif(waddr->wifstr,waddr->privkey,coin->wiftype) > 0 ) + { + if ( (0) && waddr->wiftype != coin->wiftype ) + printf("ensurepriv warning: mismatched wiftype %02x != %02x\n",waddr->wiftype,coin->wiftype); + if ( (0) && waddr->addrtype != coin->pubtype ) + printf("ensurepriv warning: mismatched addrtype %02x != %02x\n",waddr->addrtype,coin->pubtype); + } + } + } +} +#endif + + int32_t basilisk_rawtx_return(struct basilisk_rawtx *rawtx,cJSON *item,int32_t lockinputs,struct vin_info *V) { char *signedtx,*txbytes; cJSON *vins,*privkeyarray; int32_t i,n,retval = -1; diff --git a/iguana/exchanges/LP_transaction.c b/iguana/exchanges/LP_transaction.c index 6ee6499f7..63ca5beee 100644 --- a/iguana/exchanges/LP_transaction.c +++ b/iguana/exchanges/LP_transaction.c @@ -202,37 +202,6 @@ int32_t iguana_msgtx_Vset(uint8_t *serialized,int32_t maxlen,struct iguana_msgtx return(len); } -#ifdef adfafds -void iguana_ensure_privkey(struct iguana_info *coin,bits256 privkey) -{ - uint8_t pubkey33[33]; struct iguana_waccount *wacct; struct iguana_waddress *waddr,addr; char coinaddr[128]; - bitcoin_pubkey33(swap->ctx,pubkey33,privkey); - bitcoin_address(coinaddr,coin->pubtype,pubkey33,33); - //printf("privkey for (%s)\n",coinaddr); - if ( myinfo->expiration != 0 && ((waddr= iguana_waddresssearch(&wacct,coinaddr)) == 0 || bits256_nonz(waddr->privkey) == 0) ) - { - if ( waddr == 0 ) - { - memset(&addr,0,sizeof(addr)); - iguana_waddresscalc(coin->pubtype,coin->wiftype,&addr,privkey); - if ( (wacct= iguana_waccountfind("default")) != 0 ) - waddr = iguana_waddressadd(coin,wacct,&addr,0); - } - if ( waddr != 0 ) - { - waddr->privkey = privkey; - if ( bitcoin_priv2wif(waddr->wifstr,waddr->privkey,coin->wiftype) > 0 ) - { - if ( (0) && waddr->wiftype != coin->wiftype ) - printf("ensurepriv warning: mismatched wiftype %02x != %02x\n",waddr->wiftype,coin->wiftype); - if ( (0) && waddr->addrtype != coin->pubtype ) - printf("ensurepriv warning: mismatched addrtype %02x != %02x\n",waddr->addrtype,coin->pubtype); - } - } - } -} -#endif - int32_t iguana_interpreter(struct iguana_info *coin,cJSON *logarray,int64_t nLockTime,struct vin_info *V,int32_t numvins) { uint8_t script[IGUANA_MAXSCRIPTSIZE],*activescript,savescript[IGUANA_MAXSCRIPTSIZE]; char str[IGUANA_MAXSCRIPTSIZE*2+1]; int32_t vini,scriptlen,activescriptlen,savelen,errs = 0; cJSON *spendscript,*item=0; diff --git a/iguana/exchanges/LP_utxos.c b/iguana/exchanges/LP_utxos.c new file mode 100644 index 000000000..b620c65c5 --- /dev/null +++ b/iguana/exchanges/LP_utxos.c @@ -0,0 +1,327 @@ + +/****************************************************************************** + * 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_utxos.c +// marketmaker +// + +struct LP_utxoinfo *LP_utxofind(bits256 txid,int32_t vout) +{ + struct LP_utxoinfo *utxo=0; uint8_t key[sizeof(txid) + sizeof(vout)]; + memcpy(key,txid.bytes,sizeof(txid)); + memcpy(&key[sizeof(txid)],&vout,sizeof(vout)); + portable_mutex_lock(&LP_utxomutex); + HASH_FIND(hh,LP_utxoinfos,key,sizeof(key),utxo); + portable_mutex_unlock(&LP_utxomutex); + return(utxo); +} + +cJSON *LP_utxojson(struct LP_utxoinfo *utxo) +{ + cJSON *item = cJSON_CreateObject(); + jaddstr(item,"ipaddr",utxo->ipaddr); + jaddnum(item,"port",utxo->port); + jaddnum(item,"profit",utxo->profitmargin); + jaddstr(item,"base",utxo->coin); + jaddstr(item,"coin",utxo->coin); + jaddstr(item,"address",utxo->coinaddr); + jaddstr(item,"script",utxo->spendscript); + jaddbits256(item,"txid",utxo->txid); + jaddnum(item,"vout",utxo->vout); + jaddnum(item,"value",dstr(utxo->satoshis)); + jaddbits256(item,"txid2",utxo->txid2); + jaddnum(item,"vout2",utxo->vout2); + jaddnum(item,"value2",dstr(utxo->satoshis2)); + return(item); +} + +char *LP_utxos(struct LP_peerinfo *mypeer,char *coin,int32_t lastn) +{ + int32_t i,firsti; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray(); + i = 0; + if ( lastn >= mypeer->numutxos ) + firsti = -1; + else firsti = (mypeer->numutxos - lastn); + HASH_ITER(hh,LP_utxoinfos,utxo,tmp) + { + if ( i++ < firsti ) + continue; + if ( coin == 0 || coin[0] == 0 || strcmp(coin,utxo->coin) == 0 ) + { + jaddi(utxosjson,LP_utxojson(utxo)); + } + } + return(jprint(utxosjson,1)); +} + +struct LP_utxoinfo *LP_addutxo(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *coin,bits256 txid,int32_t vout,int64_t satoshis,bits256 deposittxid,int32_t depositvout,int64_t depositsatoshis,char *spendscript,char *coinaddr,char *ipaddr,uint16_t port,double profitmargin) +{ + struct LP_utxoinfo *utxo = 0; + if ( coin == 0 || coin[0] == 0 || spendscript == 0 || spendscript[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(deposittxid) == 0 || vout < 0 || depositvout < 0 || satoshis <= 0 || depositsatoshis <= 0 ) + { + printf("malformed addutxo %d %d %d %d %d %d %d %d %d\n", coin == 0,spendscript == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(deposittxid) == 0,vout < 0,depositvout < 0,satoshis <= 0,depositsatoshis <= 0); + return(0); + } + if ( amclient == 0 && strcmp(ipaddr,"127.0.0.1") == 0 ) + { + printf("LP node got localhost utxo\n"); + return(0); + } + if ( (utxo= LP_utxofind(txid,vout)) != 0 ) + { + if ( bits256_cmp(txid,utxo->txid) != 0 || bits256_cmp(deposittxid,utxo->txid2) != 0 || vout != utxo->vout || satoshis != utxo->satoshis || depositvout != utxo->vout2 || depositsatoshis != utxo->satoshis2 || strcmp(coin,utxo->coin) != 0 || strcmp(spendscript,utxo->spendscript) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || strcmp(ipaddr,utxo->ipaddr) != 0 || port != utxo->port ) + { + utxo->errors++; + char str[65],str2[65]; printf("error on subsequent utxo add.(%s v %s) %d %d %d %d %d %d %d %d %d %d %d\n",bits256_str(str,txid),bits256_str(str2,utxo->txid),bits256_cmp(txid,utxo->txid) != 0,bits256_cmp(deposittxid,utxo->txid2) != 0,vout != utxo->vout,satoshis != utxo->satoshis,depositvout != utxo->vout2,depositsatoshis != utxo->satoshis2,strcmp(coin,utxo->coin) != 0,strcmp(spendscript,utxo->spendscript) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,strcmp(ipaddr,utxo->ipaddr) != 0,port != utxo->port); + } + else if ( profitmargin != 0. ) + utxo->profitmargin = profitmargin; + } + else + { + utxo = calloc(1,sizeof(*utxo)); + utxo->pair = -1; + utxo->profitmargin = profitmargin; + strcpy(utxo->ipaddr,ipaddr); + utxo->port = port; + safecopy(utxo->coin,coin,sizeof(utxo->coin)); + safecopy(utxo->coinaddr,coinaddr,sizeof(utxo->coinaddr)); + safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript)); + utxo->txid = txid; + utxo->vout = vout; + utxo->satoshis = satoshis; + utxo->txid2 = deposittxid; + utxo->vout2 = depositvout; + utxo->satoshis2 = depositsatoshis; + memcpy(utxo->key,txid.bytes,sizeof(txid)); + memcpy(&utxo->key[sizeof(txid)],&vout,sizeof(vout)); + portable_mutex_lock(&LP_utxomutex); + HASH_ADD_KEYPTR(hh,LP_utxoinfos,utxo->key,sizeof(utxo->key),utxo); + if ( mypeer != 0 ) + mypeer->numutxos++; + portable_mutex_unlock(&LP_utxomutex); + if ( mypubsock >= 0 ) + LP_send(mypubsock,jprint(LP_utxojson(utxo),1),1); + //char str[65],str2[65]; printf("%s:%u %s LP_addutxo.(%.8f %.8f) numutxos.%d %s %s\n",ipaddr,port,utxo->coin,dstr(satoshis),dstr(depositsatoshis),mypeer!=0?mypeer->numutxos:0,bits256_str(str,utxo->txid),bits256_str(str2,txid)); + } + return(utxo); +} + +int32_t LP_utxosparse(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *retstr,uint32_t now) +{ + struct LP_peerinfo *peer,*destpeer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; bits256 txid; struct LP_utxoinfo *utxo; + if ( amclient != 0 ) + { + printf("LP_utxosparse not for clientside\n"); + return(-1); + } + if ( (array= cJSON_Parse(retstr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; ilasttime = now; + } + } + } + if ( (destpeer= LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport)) != 0 ) + { + if ( destpeer->numutxos < n ) + { + //destpeer->numutxos = n; + //printf("got.(%s) from %s numutxos.%d\n",retstr,destpeer->ipaddr,destpeer->numutxos); + } + } + } + free_json(array); + } + return(n); +} + +void LP_utxosquery(int32_t amclient,struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *coin,int32_t lastn,char *myipaddr,uint16_t myport,double myprofit) +{ + char *retstr; struct LP_utxoinfo *utxo,*tmp; struct LP_peerinfo *peer; int32_t i,firsti; uint32_t now,flag = 0; + if ( amclient != 0 ) + { + printf("LP_utxosquery not for clientside\n"); + return; + } + peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); + if ( (peer != 0 && peer->errors > 0) || mypeer == 0 ) + return; + if ( coin == 0 ) + coin = ""; + if ( (retstr= issue_LP_getutxos(destipaddr,destport,coin,lastn,myipaddr,myport,myprofit,mypeer->numpeers,mypeer->numutxos)) != 0 ) + { + now = (uint32_t)time(NULL); + LP_utxosparse(amclient,mypeer,mypubsock,destipaddr,destport,retstr,now); + free(retstr); + i = 0; + if ( lastn >= mypeer->numutxos ) + firsti = -1; + else firsti = (mypeer->numutxos - lastn); + HASH_ITER(hh,LP_utxoinfos,utxo,tmp) + { + if ( i++ < firsti ) + continue; + if ( utxo->lasttime != now && strcmp(utxo->ipaddr,"127.0.0.1") != 0 ) + { + char str[65]; printf("{%s:%u %s} ",utxo->ipaddr,utxo->port,bits256_str(str,utxo->txid)); + flag++; + if ( (retstr= issue_LP_notifyutxo(destipaddr,destport,utxo)) != 0 ) + free(retstr); + } + } + if ( flag != 0 ) + printf(" <- missing utxos\n"); + } else if ( peer != 0 ) + peer->errors++; +} + +int32_t LP_maxvalue(uint64_t *values,int32_t n) +{ + int32_t i,maxi = -1; uint64_t maxval = 0; + for (i=0; i maxval ) + { + maxi = i; + maxval = values[i]; + } + return(maxi); +} + +int32_t LP_nearestvalue(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= 0 && dist < mindist ) + { + mini = i; + mindist = dist; + } + } + return(mini); +} + +uint64_t LP_privkey_init(struct LP_peerinfo *mypeer,int32_t mypubsock,char *symbol,char *passphrase,char *wifstr,int32_t amclient) +{ + char coinaddr[64],*script; struct LP_utxoinfo *utxo; cJSON *array,*item,*retjson; bits256 txid,deposittxid; int32_t used,i,n,vout,depositvout; uint64_t *values,satoshis,depositval,targetval,value,total = 0; bits256 privkey,pubkey; uint8_t pubkey33[33],tmptype,rmd160[20]; struct iguana_info *coin = LP_coinfind(symbol); + if ( coin == 0 ) + { + printf("cant add privkey for %s, coin not active\n",symbol); + return(0); + } + if ( passphrase != 0 ) + conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); + else privkey = iguana_wif2privkey(wifstr); + iguana_priv2pub(pubkey33,coinaddr,privkey,coin->pubtype); + { + char tmpstr[128]; + bitcoin_priv2wif(tmpstr,privkey,coin->wiftype); + printf("%s (%s) %d wif.(%s) (%s)\n",symbol,coinaddr,coin->pubtype,tmpstr,passphrase); + if ( (retjson= LP_importprivkey(coin->symbol,tmpstr,coinaddr,-1)) != 0 ) + printf("importprivkey -> (%s)\n",jprint(retjson,1)); + } + bitcoin_addr2rmd160(&tmptype,rmd160,coinaddr); + LP_privkeyadd(privkey,rmd160); + if ( (array= LP_listunspent(symbol,coinaddr)) != 0 ) + { + if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) + { + values = calloc(n,sizeof(*values)); + for (i=0; i= 0 ) + { + item = jitem(array,i); + deposittxid = jbits256(item,"txid"); + depositvout = juint(item,"vout"); + script = jstr(item,"scriptPubKey"); + depositval = values[i]; + values[i] = 0, used++; + if ( amclient != 0 ) + targetval = (depositval / 776) + 50000; + else targetval = (depositval / 9) * 8; + //printf("i.%d %.8f target %.8f\n",i,dstr(depositval),dstr(targetval)); + if ( (i= LP_nearestvalue(values,n,targetval)) >= 0 ) + { + item = jitem(array,i); + txid = jbits256(item,"txid"); + vout = juint(item,"vout"); + printf("j.%d %.8f target %.8f\n",i,dstr(values[i]),dstr(targetval)); + if ( jstr(item,"scriptPubKey") != 0 && strcmp(script,jstr(item,"scriptPubKey")) == 0 ) + { + value = values[i]; + values[i] = 0, used++; + if ( amclient == 0 ) + { + if ( (utxo= LP_addutxo(amclient,mypeer,mypubsock,symbol,txid,vout,value,deposittxid,depositvout,depositval,script,coinaddr,LP_peerinfos[0].ipaddr,LP_peerinfos[0].port,LP_peerinfos[0].profitmargin)) != 0 ) + utxo->mypub = curve25519(privkey,curve25519_basepoint9()); + } + else + { + if ( (utxo= LP_addutxo(amclient,mypeer,mypubsock,symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coinaddr,"127.0.0.1",0,0)) != 0 ) + utxo->mypub = curve25519(privkey,curve25519_basepoint9()); + } + total += value; + } + } + } else break; + } + free(values); + } + free_json(array); + } + return(total); +} + +void LP_privkey_updates(struct LP_peerinfo *mypeer,int32_t pubsock,char *passphrase,int32_t amclient) +{ + int32_t i; + for (i=0; i (b) ? (a) : (b)) char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port); #include "stats.c" -#include "LP_prices.c" +void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32]); #if defined(__APPLE__) || defined(WIN32) || defined(USE_STATIC_NANOMSG) #include "../../crypto777/nanosrc/nn.h"