diff --git a/crypto777/iguana_OS.c b/crypto777/iguana_OS.c index 504905ee1..9b218f130 100755 --- a/crypto777/iguana_OS.c +++ b/crypto777/iguana_OS.c @@ -297,11 +297,11 @@ void *queue_dequeue(queue_t *queue)//,int32_t offsetflag) void *queue_delete(queue_t *queue,struct queueitem *copy,int32_t copysize,int32_t freeitem) { struct allocitem *ptr; - struct queueitem *item = 0; + struct queueitem *tmp,*item = 0; lock_queue(queue); if ( queue->list != 0 ) { - DL_FOREACH(queue->list,item) + DL_FOREACH_SAFE(queue->list,item,tmp) { ptr = (void *)((long)item - sizeof(struct allocitem)); if ( item == copy || (ptr->allocsize == copysize && memcmp((void *)((long)item + sizeof(struct queueitem)),(void *)((long)item + sizeof(struct queueitem)),copysize) == 0) ) @@ -321,11 +321,11 @@ void *queue_delete(queue_t *queue,struct queueitem *copy,int32_t copysize,int32_ void *queue_free(queue_t *queue) { - struct queueitem *item = 0; + struct queueitem *tmp,*item = 0; lock_queue(queue); if ( queue->list != 0 ) { - DL_FOREACH(queue->list,item) + DL_FOREACH_SAFE(queue->list,item,tmp) { DL_DELETE(queue->list,item); myfree(item,sizeof(struct queueitem)); @@ -338,11 +338,11 @@ void *queue_free(queue_t *queue) void *queue_clone(queue_t *clone,queue_t *queue,int32_t size) { - struct queueitem *ptr,*item = 0; + struct queueitem *ptr,*tmp,*item = 0; lock_queue(queue); if ( queue->list != 0 ) { - DL_FOREACH(queue->list,item) + DL_FOREACH_SAFE(queue->list,item,tmp) { ptr = mycalloc('c',1,sizeof(*ptr)); memcpy(ptr,item,size); diff --git a/iguana/coins/basilisk/mnz b/iguana/coins/basilisk/mnz new file mode 100755 index 000000000..d08d34075 --- /dev/null +++ b/iguana/coins/basilisk/mnz @@ -0,0 +1,2 @@ +curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"MNZ.conf\",\"path\":\"${HOME#"/"}/.komodo/MNZ\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":0,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"MNZ\",\"name\":\"MNZ\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"53d06fde\",\"p2p\":14336,\"rpc\":14337,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}" + diff --git a/iguana/coins/mnz_7776 b/iguana/coins/mnz_7776 new file mode 100755 index 000000000..cdbe97124 --- /dev/null +++ b/iguana/coins/mnz_7776 @@ -0,0 +1,2 @@ +curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"MNZ.conf\",\"path\":\"${HOME#"/"}/.komodo/MNZ\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"MNZ\",\"name\":\"MNZ\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"53d06fde\",\"p2p\":14336,\"rpc\":14337,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}" + diff --git a/iguana/exchanges/LP_bitcoin.c b/iguana/exchanges/LP_bitcoin.c index ba6a5b63f..20cc5858f 100644 --- a/iguana/exchanges/LP_bitcoin.c +++ b/iguana/exchanges/LP_bitcoin.c @@ -325,14 +325,12 @@ enum opcodetype OP_INVALIDOPCODE = 0xff, }; -struct { bits256 privkey; uint8_t rmd160[20]; } LP_privkeys[100]; int32_t LP_numprivkeys; - bits256 LP_privkeyfind(uint8_t rmd160[20]) { int32_t i; static bits256 zero; - for (i=0; i no privkey\n"); @@ -345,13 +343,13 @@ int32_t LP_privkeyadd(bits256 privkey,uint8_t rmd160[20]) tmpkey = LP_privkeyfind(rmd160); if ( bits256_nonz(tmpkey) != 0 ) return(-bits256_cmp(privkey,tmpkey)); - LP_privkeys[LP_numprivkeys].privkey = privkey; - memcpy(LP_privkeys[LP_numprivkeys].rmd160,rmd160,20); + G.LP_privkeys[G.LP_numprivkeys].privkey = privkey; + memcpy(G.LP_privkeys[G.LP_numprivkeys].rmd160,rmd160,20); //int32_t i; for (i=0; i<20; i++) // printf("%02x",rmd160[i]); //char str[65]; printf(" -> add privkey.(%s)\n",bits256_str(str,privkey)); - LP_numprivkeys++; - return(LP_numprivkeys); + G.LP_numprivkeys++; + return(G.LP_numprivkeys); } int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp) @@ -2619,7 +2617,8 @@ cJSON *bitcoin_txscript(char *asmstr,char **vardata,int32_t numvars) { int32_t i; cJSON *scriptjson,*array; scriptjson = cJSON_CreateObject(); - jaddstr(scriptjson,"asm",asmstr); + if ( asmstr != 0 ) + jaddstr(scriptjson,"asm",asmstr); jaddnum(scriptjson,"numvars",numvars); if ( numvars > 0 ) { @@ -3186,7 +3185,7 @@ int32_t iguana_parsevoutobj(uint8_t *serialized,int32_t maxsize,struct iguana_ms cJSON *iguana_voutjson(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,struct iguana_msgvout *vout,int32_t txi,bits256 txid) { // 035f1321ed17d387e4433b2fa229c53616057964af065f98bfcae2233c5108055e OP_CHECKSIG - char scriptstr[IGUANA_MAXSCRIPTSIZE+1],asmstr[2*IGUANA_MAXSCRIPTSIZE+1]; int32_t i,m,n,scriptlen,asmtype; struct vin_info *vp; + char scriptstr[IGUANA_MAXSCRIPTSIZE+1]; int32_t i,m,n,scriptlen,asmtype; struct vin_info *vp; uint8_t space[8192]; cJSON *addrs,*skey,*json = cJSON_CreateObject(); vp = calloc(1,sizeof(*vp)); jadd64bits(json,"satoshis",vout->value); @@ -3196,12 +3195,12 @@ cJSON *iguana_voutjson(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,struct igu if ( vout->pk_script != 0 && vout->pk_scriptlen*2+1 < sizeof(scriptstr) ) { memset(vp,0,sizeof(*vp)); - if ( (asmtype= iguana_calcrmd160(taddr,pubtype,p2shtype,asmstr,vp,vout->pk_script,vout->pk_scriptlen,txid,txi,0xffffffff)) >= 0 ) + if ( (asmtype= iguana_calcrmd160(taddr,pubtype,p2shtype,0,vp,vout->pk_script,vout->pk_scriptlen,txid,txi,0xffffffff)) >= 0 ) { skey = cJSON_CreateObject(); - scriptlen = iguana_scriptgen(taddr,pubtype,p2shtype,&m,&n,vp->coinaddr,space,asmstr,vp->rmd160,asmtype,vp,txi); - if ( asmstr[0] != 0 ) - jaddstr(skey,"asm",asmstr); + scriptlen = iguana_scriptgen(taddr,pubtype,p2shtype,&m,&n,vp->coinaddr,space,0,vp->rmd160,asmtype,vp,txi); + //if ( asmstr[0] != 0 ) + // jaddstr(skey,"asm",asmstr); addrs = cJSON_CreateArray(); if ( vp->N == 1 ) { diff --git a/iguana/exchanges/LP_coins.c b/iguana/exchanges/LP_coins.c index be84416ad..e1eca4ab0 100644 --- a/iguana/exchanges/LP_coins.c +++ b/iguana/exchanges/LP_coins.c @@ -172,13 +172,14 @@ int32_t LP_userpass(char *userpass,char *symbol,char *assetname,char *confroot,c cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif) { - char wifstr[128]; uint8_t tmptype; bits256 checkkey; cJSON *item = cJSON_CreateObject(); + struct electrum_info *ep; char wifstr[128],ipaddr[64]; uint8_t tmptype; bits256 checkkey; cJSON *item = cJSON_CreateObject(); jaddstr(item,"coin",coin->symbol); + jaddnum(item,"height",coin->height); if ( showwif != 0 ) { - bitcoin_priv2wif(coin->wiftaddr,wifstr,LP_mypriv25519,coin->wiftype); + bitcoin_priv2wif(coin->wiftaddr,wifstr,G.LP_mypriv25519,coin->wiftype); bitcoin_wif2priv(coin->wiftaddr,&tmptype,&checkkey,wifstr); - if ( bits256_cmp(LP_mypriv25519,checkkey) == 0 ) + if ( bits256_cmp(G.LP_mypriv25519,checkkey) == 0 ) jaddstr(item,"wif",wifstr); else jaddstr(item,"wif","error creating wif"); } @@ -187,6 +188,11 @@ cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif) else jaddstr(item,"status","active"); if ( coin->isPoS != 0 ) jaddstr(item,"type","PoS"); + if ( (ep= coin->electrum) != 0 ) + { + sprintf(ipaddr,"%s:%u",ep->ipaddr,ep->port); + jaddstr(item,"electrum",ipaddr); + } jaddstr(item,"smartaddress",coin->smartaddr); jaddstr(item,"rpc",coin->serverport); jaddnum(item,"pubtype",coin->pubtype); @@ -196,6 +202,19 @@ cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif) return(item); } +struct iguana_info *LP_conflicts_find(struct iguana_info *refcoin) +{ + struct iguana_info *coin=0,*tmp; + HASH_ITER(hh,LP_coins,coin,tmp) + { + if ( coin->inactive != 0 || coin->electrum != 0 || coin == refcoin ) + continue; + if ( strcmp(coin->serverport,refcoin->serverport) == 0 ) + break; + } + return(coin); +} + cJSON *LP_coinsjson(int32_t showwif) { struct iguana_info *coin,*tmp; cJSON *array = cJSON_CreateArray(); @@ -243,6 +262,7 @@ struct iguana_info *LP_coinadd(struct iguana_info *cdata) //printf("%s: (%s) (%s)\n",symbol,cdata.serverport,cdata.userpass); *coin = *cdata; portable_mutex_init(&coin->txmutex); + portable_mutex_init(&coin->addrmutex); portable_mutex_lock(&LP_coinmutex); HASH_ADD_KEYPTR(hh,LP_coins,coin->symbol,strlen(coin->symbol),coin); portable_mutex_unlock(&LP_coinmutex); @@ -255,6 +275,7 @@ int32_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *asset memset(coin,0,sizeof(*coin)); safecopy(coin->symbol,symbol,sizeof(coin->symbol)); sprintf(coin->serverport,"127.0.0.1:%u",port); + coin->updaterate = (uint32_t)time(NULL); coin->isPoS = isPoS; coin->taddr = taddr; coin->wiftaddr = wiftaddr; @@ -290,6 +311,8 @@ int32_t LP_isdisabled(char *base,char *rel) struct iguana_info *LP_coinfind(char *symbol) { struct iguana_info *coin,cdata; int32_t isinactive,isPoS,longestchain = 1; uint16_t port,busport; uint64_t txfee; double estimatedrate; uint8_t pubtype,p2shtype,wiftype; char *name,*assetname; + if ( symbol == 0 || symbol[0] == 0 ) + return(0); if ( (coin= LP_coinsearch(symbol)) != 0 ) return(coin); if ( (port= LP_rpcport(symbol)) == 0 ) diff --git a/iguana/exchanges/LP_commands.c b/iguana/exchanges/LP_commands.c index b76100e93..e76f2c691 100644 --- a/iguana/exchanges/LP_commands.c +++ b/iguana/exchanges/LP_commands.c @@ -25,18 +25,19 @@ char *LP_numutxos() { jaddstr(retjson,"ipaddr",LP_mypeer->ipaddr); jaddnum(retjson,"port",LP_mypeer->port); - jaddnum(retjson,"numutxos",LP_mypeer->numutxos); + //jaddnum(retjson,"numutxos",LP_mypeer->numutxos); jaddnum(retjson,"numpeers",LP_mypeer->numpeers); - jaddnum(retjson,"session",LP_sessionid); + jaddnum(retjson,"session",G.LP_sessionid); } else jaddstr(retjson,"error","client node"); return(jprint(retjson,1)); } char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port { - char *method,*ipaddr,*userpass,*base,*rel,*coin,*retstr = 0; uint16_t argport=0,pushport,subport; int32_t changed,otherpeers,othernumutxos,flag = 0; struct LP_peerinfo *peer; cJSON *retjson,*reqjson = 0; struct iguana_info *ptr; + char *method,*ipaddr,*userpass,*base,*rel,*coin,*retstr = 0; uint16_t argport=0,pushport,subport; int32_t changed,otherpeers,flag = 0; struct LP_peerinfo *peer; cJSON *retjson,*reqjson = 0; struct iguana_info *ptr; //printf("stats_JSON(%s)\n",jprint(argjson,0)); - if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 ) + method = jstr(argjson,"method"); + if ( (ipaddr= jstr(argjson,"ipaddr")) != 0 && (argport= juint(argjson,"port")) != 0 && (method == 0 || strcmp(method,"electrum") != 0) ) { if ( strcmp(ipaddr,"127.0.0.1") != 0 && argport >= 1000 ) { @@ -49,18 +50,18 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r { if ( 0 && (otherpeers= jint(argjson,"numpeers")) > peer->numpeers ) peer->numpeers = otherpeers; - if ( 0 && (othernumutxos= jint(argjson,"numutxos")) > peer->numutxos ) + /*if ( 0 && (othernumutxos= jint(argjson,"numutxos")) > peer->numutxos ) { printf("change.(%s) numutxos.%d -> %d mynumutxos.%d\n",peer->ipaddr,peer->numutxos,othernumutxos,LP_mypeer != 0 ? LP_mypeer->numutxos:0); peer->numutxos = othernumutxos; - } + }*/ if ( peer->sessionid == 0 ) peer->sessionid = juint(argjson,"session"); //printf("peer.(%s) found (%d %d) (%d %d) (%s)\n",peer->ipaddr,peer->numpeers,peer->numutxos,otherpeers,othernumutxos,jprint(argjson,0)); } else LP_addpeer(LP_mypeer,LP_mypubsock,ipaddr,argport,pushport,subport,jint(argjson,"numpeers"),jint(argjson,"numutxos"),juint(argjson,"session")); } } - if ( (method= jstr(argjson,"method")) == 0 ) + if ( method == 0 ) { if ( flag == 0 || jobj(argjson,"result") != 0 ) printf("stats_JSON no method: (%s) (%s:%u)\n",jprint(argjson,0),ipaddr,argport); @@ -75,7 +76,7 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *r { static char *laststr; char *newstr; bits256 pubkey = jbits256(argjson,"pubkey"); - if ( bits256_nonz(pubkey) == 0 || bits256_cmp(pubkey,LP_mypub25519) == 0 ) + if ( bits256_nonz(pubkey) == 0 || bits256_cmp(pubkey,G.LP_mypub25519) == 0 ) { newstr = jprint(argjson,0); if ( laststr == 0 || strcmp(laststr,newstr) != 0 ) @@ -103,9 +104,7 @@ enable(coin)\n\ disable(coin)\n\ inventory(coin)\n\ bestfit(rel, relvolume)\n\ -ordermatch(base, txfee=0, rel, desttxfee=0, price, relvolume=0, txid, vout, feetxid, feevout, duration=3600)\n\ -trade(price, timeout=10, duration=3600, )\n\ -autotrade(base, rel, price, relvolume, timeout=10, duration=3600)\n\ +buy(base, rel, price, relvolume, timeout=10, duration=3600)\n\ swapstatus()\n\ swapstatus(requestid, quoteid)\n\ public API:\n \ @@ -113,8 +112,9 @@ getcoins()\n\ getcoin(coin)\n\ portfolio()\n\ getpeers()\n\ -getutxos()\n\ -getutxos(coin, lastn)\n\ +passphrase(passphrase, gui)\n\ +listunspent(coin, address)\n\ +balance(coin, address)\n\ orderbook(base, rel, duration=3600)\n\ getprices(base, rel)\n\ sendmessage(base=coin, rel="", pubkey=zero, )\n\ @@ -126,22 +126,24 @@ snapshot(coin, height)\n\ snapshot_balance(coin, height, addresses[])\n\ dividends(coin, height, )\n\ \"}")); - + //sell(base, rel, price, basevolume, timeout=10, duration=3600)\n\ + base = jstr(argjson,"base"); rel = jstr(argjson,"rel"); - if ( USERPASS[0] != 0 && strcmp(remoteaddr,"127.0.0.1") == 0 && port != 0 ) + coin = jstr(argjson,"coin"); + if ( G.USERPASS[0] != 0 && strcmp(remoteaddr,"127.0.0.1") == 0 && port != 0 ) { - if ( USERPASS_COUNTER == 0 ) + if ( G.USERPASS_COUNTER == 0 ) { - USERPASS_COUNTER = 1; + G.USERPASS_COUNTER = 1; retjson = cJSON_CreateObject(); - jaddstr(retjson,"userpass",USERPASS); - jaddbits256(retjson,"mypubkey",LP_mypub25519); + jaddstr(retjson,"userpass",G.USERPASS); + jaddbits256(retjson,"mypubkey",G.LP_mypub25519); jadd(retjson,"coins",LP_coinsjson(LP_showwif)); return(jprint(retjson,1)); } - if ( (userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,USERPASS) != 0 ) - return(clonestr("{\"error\":\"authentication error\"}")); + if ( (userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,G.USERPASS) != 0 ) + return(clonestr("{\"error\":\"authentication error you need to make sure userpass is set\"}")); jdelete(argjson,"userpass"); if ( strcmp(method,"sendmessage") == 0 ) { @@ -163,6 +165,18 @@ dividends(coin, height, )\n\ LP_deletemessages(jint(argjson,"firsti"),jint(argjson,"num")); return(clonestr("{\"result\":\"success\"}")); } + else if ( strcmp(method,"passphrase") == 0 ) + { + if ( LP_passphrase_init(jstr(argjson,"passphrase"),jstr(argjson,"gui")) < 0 ) + return(clonestr("{\"error\":\"couldnt change passphrase\"}")); + { + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jaddstr(retjson,"userpass",G.USERPASS); + jaddbits256(retjson,"mypubkey",G.LP_mypub25519); + return(jprint(retjson,1)); + } + } else if ( strcmp(method,"portfolio") == 0 ) { return(LP_portfolio()); @@ -213,26 +227,18 @@ dividends(coin, height, )\n\ return(jprint(retjson,1)); } else return(clonestr("{\"error\":\"no price set\"}")); } - else if ( strcmp(method,"ordermatch") == 0 ) + else if ( strcmp(method,"buy") == 0 ) { if ( price > SMALLVAL ) - return(LP_ordermatch(base,j64bits(argjson,"txfee"),price,jdouble(argjson,"relvolume"),rel,jbits256(argjson,"txid"),jint(argjson,"vout"),jbits256(argjson,"feetxid"),jint(argjson,"feevout"),j64bits(argjson,"desttxfee"),jint(argjson,"duration"))); - else return(clonestr("{\"error\":\"no price set\"}")); - } - else if ( strcmp(method,"trade") == 0 ) - { - struct LP_quoteinfo Q; - if ( price > SMALLVAL || jobj(argjson,"quote") != 0 ) { - LP_quoteparse(&Q,jobj(argjson,"quote")); - return(LP_trade(ctx,myipaddr,pubsock,&Q,price,jint(argjson,"timeout"),jint(argjson,"duration"))); - } else return(clonestr("{\"error\":\"no price set or no quote object\"}")); + return(LP_autobuy(ctx,myipaddr,pubsock,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui"))); + } else return(clonestr("{\"error\":\"no price set\"}")); } - else if ( strcmp(method,"autotrade") == 0 ) + else if ( strcmp(method,"sell") == 0 ) { if ( price > SMALLVAL ) { - return(LP_autotrade(ctx,myipaddr,pubsock,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration"))); + return(LP_autobuy(ctx,myipaddr,pubsock,rel,base,1./price,jdouble(argjson,"basevolume"),jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui"))); } else return(clonestr("{\"error\":\"no price set\"}")); } } @@ -248,7 +254,11 @@ dividends(coin, height, )\n\ if ( strcmp(method,"enable") == 0 ) { if ( (ptr= LP_coinsearch(coin)) != 0 ) - ptr->inactive = 0; + { + if ( LP_conflicts_find(ptr) == 0 ) + ptr->inactive = 0; + else return(clonestr("{\"error\":\"coin port conflicts with existing coin\"}")); + } return(jprint(LP_coinsjson(0),1)); } else if ( strcmp(method,"disable") == 0 ) @@ -292,14 +302,15 @@ dividends(coin, height, )\n\ { //privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,ptr,"",USERPASS_WIFSTR); //LP_utxopurge(0); - if ( bits256_nonz(LP_mypriv25519) != 0 ) - LP_privkey_init(-1,ptr,LP_mypriv25519,LP_mypub25519); + if ( bits256_nonz(G.LP_mypriv25519) != 0 ) + LP_privkey_init(-1,ptr,G.LP_mypriv25519,G.LP_mypub25519); + else printf("no LP_mypriv25519\n"); retjson = cJSON_CreateObject(); jaddstr(retjson,"result","success"); jaddstr(retjson,"coin",coin); jaddnum(retjson,"timestamp",time(NULL)); - jadd(retjson,"alice",LP_inventory(coin,0)); - jadd(retjson,"bob",LP_inventory(coin,1)); + jadd(retjson,"alice",LP_inventory(coin)); + //jadd(retjson,"bob",LP_inventory(coin,1)); return(jprint(retjson,1)); } } @@ -335,28 +346,67 @@ dividends(coin, height, )\n\ argjson = reqjson; } } - if ( IAMLP == 0 && LP_isdisabled(base,rel) != 0 ) + if ( strcmp(method,"postprice") == 0 ) + retstr = LP_postedprice(argjson); + else if ( strcmp(method,"postutxos") == 0 ) + retstr = LP_postedutxos(argjson); + else if ( strcmp(method,"getprices") == 0 ) + return(LP_prices()); + else if ( strcmp(method,"uitem") == 0 ) + { + bits256 txid; int32_t vout,height; uint64_t value; char *coinaddr; + txid = jbits256(argjson,"txid"); + vout = jint(argjson,"vout"); + height = jint(argjson,"ht"); + value = j64bits(argjson,"value"); + coinaddr = jstr(argjson,"coinaddr"); + if ( coin != 0 && coinaddr != 0 ) + { + //char str[65]; printf("uitem %s %s %s/v%d %.8f ht.%d\n",coin,coinaddr,bits256_str(str,txid),vout,dstr(value),height); + LP_address_utxoadd(LP_coinfind(coin),coinaddr,txid,vout,value,height,-1); + } + return(clonestr("{\"result\":\"success\"}")); + } + else if ( strcmp(method,"orderbook") == 0 ) + return(LP_orderbook(base,rel,jint(argjson,"duration"))); + else if ( strcmp(method,"listunspent") == 0 ) + { + if ( (ptr= LP_coinsearch(jstr(argjson,"coin"))) != 0 ) + return(jprint(LP_address_utxos(ptr,jstr(argjson,"address"),1),1)); + else return(clonestr("{\"error\":\"cant find coind\"}")); + } + else if ( strcmp(method,"balance") == 0 ) + { + if ( (ptr= LP_coinsearch(jstr(argjson,"coin"))) != 0 ) + return(jprint(LP_address_balance(ptr,jstr(argjson,"address"),1),1)); + else return(clonestr("{\"error\":\"cant find coind\"}")); + } + else if ( IAMLP == 0 && LP_isdisabled(base,rel) != 0 ) return(clonestr("{\"result\":\"at least one of coins disabled\"}")); else if ( IAMLP == 0 && LP_isdisabled(jstr(argjson,"coin"),0) != 0 ) retstr = clonestr("{\"result\":\"coin is disabled\"}"); else if ( strcmp(method,"reserved") == 0 ) + { + //printf("RESERVED.(%s)\n",jprint(argjson,0)); retstr = LP_quotereceived(argjson); + } else if ( strcmp(method,"connected") == 0 ) + { + //printf("CONNECTED.(%s)\n",jprint(argjson,0)); retstr = LP_connectedalice(argjson); + } else if ( strcmp(method,"checktxid") == 0 ) retstr = LP_spentcheck(argjson); else if ( strcmp(method,"getcoins") == 0 ) return(jprint(LP_coinsjson(0),1)); else if ( strcmp(method,"numutxos") == 0 ) - return(LP_numutxos()); - else if ( strcmp(method,"postprice") == 0 ) - retstr = LP_postedprice(argjson); + { + printf("deprecated numutxos received\n"); + retstr = clonestr("{\"result\":\"couldnt add utxo\"}"); + //return(LP_numutxos()); + } else if ( strcmp(method,"encrypted") == 0 ) retstr = clonestr("{\"result\":\"success\"}"); - else if ( strcmp(method,"getprices") == 0 ) - return(LP_prices()); - else if ( strcmp(method,"orderbook") == 0 ) - return(LP_orderbook(base,rel,jint(argjson,"duration"))); else if ( strcmp(method,"registerall") == 0 ) return(clonestr("{\"error\":\"you are running an obsolete version, update\"}")); else if ( strcmp(method,"forward") == 0 ) @@ -366,12 +416,20 @@ dividends(coin, height, )\n\ else if ( strcmp(method,"getpeers") == 0 ) return(LP_peers()); else if ( strcmp(method,"getutxos") == 0 ) - return(LP_utxos(1,LP_mypeer,jstr(argjson,"coin"),jint(argjson,"lastn"))); + { + printf("deprecated getutxos received\n"); + retstr = clonestr("{\"result\":\"couldnt add utxo\"}"); + //return(LP_utxos(1,LP_mypeer,jstr(argjson,"coin"),jint(argjson,"lastn"))); + } else if ( strcmp(method,"utxo") == 0 ) { - if ( LP_utxoaddjson(1,LP_mypubsock,argjson) != 0 ) - retstr = clonestr("{\"result\":\"success\",\"utxo\":\"received\"}"); - else retstr = clonestr("{\"result\":\"couldnt add utxo\"}"); + static uint32_t counter; + if ( counter++ < 3 ) + printf("deprecated utxo received\n"); + //if ( LP_utxoaddjson(1,LP_mypubsock,argjson) != 0 ) + // retstr = clonestr("{\"result\":\"success\",\"utxo\":\"received\"}"); + //else + retstr = clonestr("{\"result\":\"couldnt add utxo\"}"); } else { @@ -382,6 +440,25 @@ dividends(coin, height, )\n\ firsttime = (uint32_t)(time(NULL)-30*24*3600); return(jprint(LP_pricearray(base,rel,firsttime,juint(argjson,"lasttime"),jint(argjson,"timescale")),1)); } + else if ( strcmp(method,"notify") == 0 ) + { + char *rmd160str,*secpstr; bits256 pub; struct LP_pubkeyinfo *pubp; + pub = jbits256(argjson,"pub"); + if ( bits256_nonz(pub) != 0 && (rmd160str= jstr(argjson,"rmd160")) != 0 && strlen(rmd160str) == 40 ) + { + if ( (pubp= LP_pubkeyadd(pub)) != 0 ) + { + decode_hex(pubp->rmd160,20,rmd160str); + if ( (secpstr= jstr(argjson,"pubsecp")) != 0 ) + { + decode_hex(pubp->pubsecp,sizeof(pubp->pubsecp),secpstr); + //printf("got pubkey.(%s)\n",secpstr); + } + } + //printf("NOTIFIED pub %s rmd160 %s\n",bits256_str(str,pub),rmd160str); + } + retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}"); + } if ( IAMLP != 0 ) { if ( strcmp(method,"register") == 0 ) @@ -393,6 +470,7 @@ dividends(coin, height, )\n\ bits256 zero; char *cipherstr; int32_t cipherlen; uint8_t cipher[LP_ENCRYPTED_MAXSIZE]; if ( (reqjson= LP_dereference(argjson,"broadcast")) != 0 ) { + Broadcaststr = jprint(reqjson,0); if ( (cipherstr= jstr(reqjson,"cipher")) != 0 ) { cipherlen = (int32_t)strlen(cipherstr) >> 1; @@ -404,8 +482,11 @@ dividends(coin, height, )\n\ } else { + char *msg; memset(zero.bytes,0,sizeof(zero)); - LP_broadcast_message(LP_mypubsock,base!=0?base:jstr(argjson,"coin"),rel,zero,jprint(reqjson,0)); + msg = jprint(reqjson,0); + //printf("broadcast.(%s)\n",msg); + LP_broadcast_message(LP_mypubsock,base!=0?base:jstr(argjson,"coin"),rel,zero,msg); } retstr = clonestr("{\"result\":\"success\"}"); } else retstr = clonestr("{\"error\":\"couldnt dereference sendmessage\"}"); @@ -422,8 +503,6 @@ dividends(coin, height, )\n\ return(LP_psock(myipaddr,jint(argjson,"ispaired"))); else return(clonestr("{\"error\":\"you are running an obsolete version, update\"}")); } - else if ( strcmp(method,"notify") == 0 ) - retstr = clonestr("{\"result\":\"success\",\"notify\":\"received\"}"); } else { diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index 2a113134d..d1a85727e 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -45,10 +45,10 @@ #define LP_SWAPSTEP_TIMEOUT 30 #define LP_AUTOTRADE_TIMEOUT 60 #define LP_MIN_TXFEE 10000 -#define LP_MINVOL 10 -#define LP_MINCLIENTVOL 20 +#define LP_MINVOL 20 +#define LP_MINCLIENTVOL 50 #define LP_MINSIZE_TXFEEMULT 10 -#define LP_REQUIRED_TXFEE 0.95 +#define LP_REQUIRED_TXFEE 0.8 #define LP_DEXFEE(destsatoshis) ((destsatoshis) / INSTANTDEX_INSURANCEDIV) #define LP_DEPOSITSATOSHIS(satoshis) ((satoshis) + (satoshis >> 3)) @@ -75,8 +75,8 @@ #define DEX_SLEEP 3 #define BASILISK_KEYSIZE ((int32_t)(2*sizeof(bits256)+sizeof(uint32_t)*2)) -extern char GLOBAL_DBDIR[],USERPASS[],USERPASS_WIFSTR[]; -extern int32_t IAMLP,USERPASS_COUNTER; +extern char GLOBAL_DBDIR[]; +extern int32_t IAMLP; struct iguana_msgvin { bits256 prev_hash; uint8_t *vinscript,*userdata,*spendscript,*redeemscript; uint32_t prev_vout,sequence; uint16_t scriptlen,p2shlen,userdatalen,spendlen; }; @@ -167,22 +167,23 @@ struct basilisk_swapinfo uint8_t userdata_bobrefund[256],userdata_bobrefundlen; }; -struct LP_outpoint { bits256 spendtxid; uint64_t value,interest; int32_t spendvini,spendheight; char coinaddr[40]; }; +struct LP_outpoint { bits256 spendtxid; uint64_t value,interest; int32_t spendvini,spendheight; char coinaddr[64]; }; struct LP_transaction { UT_hash_handle hh; - bits256 txid; int32_t height,numvouts,numvins; //uint32_t timestamp; + bits256 txid; int32_t height,numvouts,numvins,len; //uint32_t timestamp; + uint8_t *serialized; struct LP_outpoint outpoints[]; }; struct iguana_info { UT_hash_handle hh; - portable_mutex_t txmutex; struct LP_transaction *transactions; struct LP_address *addresses; + portable_mutex_t txmutex,addrmutex; struct LP_transaction *transactions; struct LP_address *addresses; uint64_t txfee; int32_t longestchain,firstrefht,firstscanht,lastscanht,bussock,height; uint16_t busport; - uint32_t counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,unspenttime; + uint32_t lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,unspenttime,obooktime; uint8_t pubtype,p2shtype,isPoS,wiftype,wiftaddr,taddr,noimportprivkey_flag; char symbol[16],smartaddr[64],userpass[1024],serverport[128],lastunspent[64]; // portfolio @@ -192,7 +193,7 @@ struct iguana_info uint8_t pubkey33[33]; }; -struct _LP_utxoinfo { bits256 txid; uint64_t value; int32_t vout; }; +struct _LP_utxoinfo { bits256 txid; uint64_t value; int32_t vout,height; }; struct LP_utxostats { uint32_t sessionid,lasttime,errors,swappending,spentflag,lastspentcheck,bestflag; }; @@ -209,34 +210,35 @@ struct LP_utxoinfo struct _LP_utxoinfo payment,deposit,fee; struct LP_utxostats T; struct LP_utxoswap S; - //struct LP_utxonetwork N; int32_t iambob,iamlp; uint8_t key[sizeof(bits256) + sizeof(int32_t)]; uint8_t key2[sizeof(bits256) + sizeof(int32_t)]; - char coin[16],coinaddr[64],spendscript[256],gui[16]; + char coin[16],coinaddr[64],gui[16];//spendscript[256]; }; struct LP_address_utxo { struct LP_address_utxo *next,*prev; struct _LP_utxoinfo U; - uint32_t height,SPV,spentflag; + int32_t SPV,spendheight; }; struct LP_address { UT_hash_handle hh; struct LP_address_utxo *utxos; - int64_t balance; - uint32_t monitor; + bits256 pubkey; + int64_t balance,total; + uint32_t timestamp,n; char coinaddr[40]; + uint8_t pubsecp[33],pad; }; struct LP_peerinfo { UT_hash_handle hh; uint64_t ip_port; - uint32_t ipbits,errortime,errors,numpeers,numutxos,lasttime,connected,lastutxos,lastpeers,diduquery,good,sessionid; + uint32_t ipbits,errortime,errors,numpeers,needping,lasttime,connected,lastutxos,lastpeers,diduquery,good,sessionid; int32_t pushsock,subsock; uint16_t port; char ipaddr[64]; @@ -267,7 +269,7 @@ struct basilisk_swap struct basilisk_swapmessage *messages; int32_t nummessages,sentflag; char Bdeposit[64],Bpayment[64]; uint64_t otherdeck[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2]; - uint8_t persistent_pubkey33[33],changermd160[20],pad[15],verifybuf[65536]; + uint8_t persistent_pubkey33[33],changermd160[20],pad[15],verifybuf[100000]; }; @@ -285,24 +287,43 @@ int32_t LP_forward(void *ctx,char *myipaddr,int32_t pubsock,bits256 pubkey,char int32_t LP_ismine(struct LP_utxoinfo *utxo); int32_t LP_isavailable(struct LP_utxoinfo *utxo); struct LP_peerinfo *LP_peerfind(uint32_t ipbits,uint16_t port); +uint64_t LP_value_extract(cJSON *obj,int32_t addinterest); char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen); void LP_availableset(struct LP_utxoinfo *utxo); int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2); int32_t LP_pullsock_check(void *ctx,char **retstrp,char *myipaddr,int32_t pubsock,int32_t pullsock); uint16_t LP_psock_get(char *connectaddr,char *publicaddr,int32_t ispaired); -void LP_utxo_clientpublish(struct LP_utxoinfo *utxo); +//void LP_utxo_clientpublish(struct LP_utxoinfo *utxo); int32_t LP_coinbus(uint16_t coin_busport); struct iguana_info *LP_coinfind(char *symbol); int32_t LP_crc32find(int32_t *duplicatep,int32_t ind,uint32_t crc32); char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *rel,double price); uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee); struct LP_address *_LP_address(struct iguana_info *coin,char *coinaddr); +struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr); +struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr); int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,struct iguana_msgtx *msgtx,char **signedtxp,bits256 *signedtxidp,struct vin_info *V,int32_t numinputs,char *rawtx,cJSON *vins,cJSON *privkeysjson); -int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t duration); +//void LP_butxo_swapfields_set(struct LP_utxoinfo *butxo); +struct LP_address_utxo *LP_address_utxofind(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout); +int32_t LP_destaddr(char *destaddr,cJSON *item); +int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t duration); struct LP_transaction *LP_transactionfind(struct iguana_info *coin,bits256 txid); -int32_t LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter); +cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJSON *txobj); int32_t LP_mempoolscan(char *symbol,bits256 searchtxid); int32_t LP_txheight(struct iguana_info *coin,bits256 txid); +int32_t LP_address_utxoadd(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight); +cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrumret); +cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout); +void LP_postutxos(char *symbol,char *coinaddr); +int32_t LP_listunspent_both(char *symbol,char *coinaddr); +uint16_t LP_randpeer(char *destip); +cJSON *bitcoin_data2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys); +//int32_t LP_butxo_findeither(bits256 txid,int32_t vout); +cJSON *LP_listunspent(char *symbol,char *coinaddr); +int32_t LP_gettx_presence(char *symbol,bits256 expectedtxid); +double LP_getestimatedrate(struct iguana_info *coin); +struct LP_utxoinfo *_LP_utxofind(int32_t iambob,bits256 txid,int32_t vout); +struct LP_utxoinfo *_LP_utxo2find(int32_t iambob,bits256 txid,int32_t vout); #endif diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index 15296bcd6..769670543 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -20,20 +20,22 @@ // marketmaker // // new features: +// better error message in ordermatch +// withdraw +// sign packets +// spv check +// dPoW security +// stats, fix pricearray +// verify portfolio // bittrex balancing -// detect port conflicts on enable -// stats -// dynamic txid2 allocation -// unduplicated bugs: -// swap cancel should cleanly cancel +// -check for completed one being spent #include #include "LP_include.h" -portable_mutex_t LP_peermutex,LP_UTXOmutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex,LP_forwardmutex,LP_pubkeymutex,LP_networkmutex,LP_psockmutex,LP_coinmutex,LP_messagemutex,LP_portfoliomutex,LP_electrummutex; +portable_mutex_t LP_peermutex,LP_UTXOmutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex,LP_forwardmutex,LP_pubkeymutex,LP_networkmutex,LP_psockmutex,LP_coinmutex,LP_messagemutex,LP_portfoliomutex,LP_electrummutex,LP_butxomutex; int32_t LP_canbind; - -struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2]; +char *Broadcaststr; struct LP_peerinfo *LP_peerinfos,*LP_mypeer; struct LP_forwardinfo *LP_forwardinfos; struct iguana_info *LP_coins; @@ -41,7 +43,7 @@ struct iguana_info *LP_coins; char *activecoins[] = { "BTC", "KMD" }; char GLOBAL_DBDIR[] = { "DB" }; -char USERPASS[65],USERPASS_WIFSTR[64],LP_myipaddr[64],LP_publicaddr[64],USERHOME[512] = { "/root" }; +char LP_myipaddr[64],LP_publicaddr[64],USERHOME[512] = { "/root" }; char LP_gui[16] = { "cli" }; char *default_LPnodes[] = { "5.9.253.195", "5.9.253.196", "5.9.253.197", "5.9.253.198", "5.9.253.199", "5.9.253.200", "5.9.253.201", "5.9.253.202", "5.9.253.203", };//"5.9.253.204" }; // @@ -51,11 +53,22 @@ uint16_t LP_fixed_pairport,LP_publicport; int32_t LP_mybussock = -1; int32_t LP_mypubsock = -1; int32_t LP_mypullsock = -1; -int32_t LP_pendingswaps,LP_showwif,USERPASS_COUNTER,IAMLP = 0; -uint32_t LP_sessionid; +int32_t LP_showwif,IAMLP = 0; double LP_profitratio = 1.; -bits256 LP_mypub25519,LP_mypriv25519; -uint8_t LP_myrmd160[20]; + +struct LP_privkey { bits256 privkey; uint8_t rmd160[20]; }; + +struct LP_globals +{ + struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2]; + bits256 LP_mypub25519,LP_mypriv25519; + uint64_t LP_skipstatus[10000]; + uint8_t LP_myrmd160[20],LP_pubsecp[33]; + uint32_t LP_sessionid,counter; + int32_t LP_pendingswaps,USERPASS_COUNTER,LP_numprivkeys,initializing,waiting,LP_numskips; + char USERPASS[65],USERPASS_WIFSTR[64],LP_myrmd160str[41],gui[16]; + struct LP_privkey LP_privkeys[100]; +} G; // stubs @@ -84,8 +97,8 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_ #include "LP_bitcoin.c" #include "LP_coins.c" #include "LP_rpc.c" -#include "LP_prices.c" #include "LP_utxo.c" +#include "LP_prices.c" #include "LP_scan.c" #include "LP_transaction.c" #include "LP_remember.c" @@ -111,7 +124,7 @@ char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson //if ( pubsock >= 0 ) //strncmp("{\"error\":",retstr,strlen("{\"error\":")) != 0 && //LP_send(pubsock,retstr,(int32_t)strlen(retstr)+1,0); } - } + } //else printf("finished tradecommand (%s)\n",jprint(argjson,0)); return(retstr); } @@ -124,7 +137,7 @@ char *LP_decrypt(uint8_t *ptr,int32_t *recvlenp) cipherlen = recvlen - (2 + crypto_box_NONCEBYTES); if ( cipherlen > 0 && cipherlen <= sizeof(decoded) ) { - if ( (jsonstr= (char *)_SuperNET_decipher(nonce,cipher,decoded,cipherlen,GENESIS_PUBKEY,LP_mypriv25519)) != 0 ) + if ( (jsonstr= (char *)_SuperNET_decipher(nonce,cipher,decoded,cipherlen,GENESIS_PUBKEY,G.LP_mypriv25519)) != 0 ) { recvlen = (cipherlen - crypto_box_ZEROBYTES); if ( strlen(jsonstr)+1 != recvlen ) @@ -151,7 +164,7 @@ char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock, dup++; else uniq++; if ( (rand() % 1000) == 0 ) - printf("%s dup.%d (%u / %u) %.1f%% encrypted.%d recv.%u [%02x %02x] vs %02x %02x U.%d\n",typestr,duplicate,dup,dup+uniq,(double)100*dup/(dup+uniq),encrypted,crc32,ptr[0],ptr[1],crc32&0xff,(crc32>>8)&0xff,LP_mypeer != 0 ? LP_mypeer->numutxos : -1); + printf("%s dup.%d (%u / %u) %.1f%% encrypted.%d recv.%u [%02x %02x] vs %02x %02x\n",typestr,duplicate,dup,dup+uniq,(double)100*dup/(dup+uniq),encrypted,crc32,ptr[0],ptr[1],crc32&0xff,(crc32>>8)&0xff); if ( duplicate == 0 ) { if ( i >= 0 ) @@ -217,59 +230,12 @@ char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock, return(retstr); } -void LP_utxo_spentcheck(int32_t pubsock,struct LP_utxoinfo *utxo) -{ - struct _LP_utxoinfo u; struct iguana_info *coin; char str[65]; uint32_t now = (uint32_t)time(NULL); - if ( IAMLP != 0 && (coin= LP_coinfind(utxo->coin)) != 0 && coin->inactive != 0 ) - return; - //printf("%s lag.%d\n",bits256_str(str,utxo->txid),now-utxo->lastspentcheck); - if ( utxo->T.spentflag == 0 && now > utxo->T.lastspentcheck+60 ) - { - u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; - utxo->T.lastspentcheck = now; - if ( LP_txvalue(0,utxo->coin,utxo->payment.txid,utxo->payment.vout) == 0 ) - { - printf("txid.%s %s/v%d %.8f has been spent\n",utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout,dstr(utxo->payment.value)); - LP_spentnotify(utxo,0); - } - else if ( LP_txvalue(0,utxo->coin,u.txid,u.vout) == 0 ) - { - printf("txid2.%s %s/v%d %.8f has been spent\n",utxo->coin,bits256_str(str,u.txid),u.vout,dstr(u.value)); - LP_spentnotify(utxo,1); - } - } -} - -void LP_myutxo_updates(void *ctx,int32_t pubsock,char *passphrase) +int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int32_t sock,char *remoteaddr) { - //LP_utxopurge(0); not good to disrupt existing pointers - LP_privkey_updates(ctx,pubsock,passphrase,0); -} - -int32_t LP_peer_utxosquery(struct LP_peerinfo *mypeer,uint16_t myport,int32_t pubsock,struct LP_peerinfo *peer,uint32_t now,int32_t interval,int32_t maxentries) -{ - int32_t lastn,n = -1; - if ( peer->lastutxos < now-interval ) - { - //lastn = peer->numutxos - mypeer->numutxos + LP_PROPAGATION_SLACK; - //if ( lastn < LP_PROPAGATION_SLACK * 2 ) - lastn = LP_PROPAGATION_SLACK * 2; - if ( mypeer == 0 || strcmp(peer->ipaddr,mypeer->ipaddr) != 0 ) - { - peer->lastutxos = now; - //printf("query utxos from %s\n",peer->ipaddr); - n = LP_utxosquery(mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,maxentries); - } - } //else printf("LP_peer_utxosquery skip.(%s) %u\n",peer->ipaddr,peer->lastutxos); - return(n); -} - -int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int32_t sock) -{ - int32_t recvlen=1,nonz = 0; void *ptr; char *retstr; struct nn_pollfd pfd; + int32_t recvlen=1,nonz = 0; cJSON *argjson; void *ptr; char *retstr,*str; struct nn_pollfd pfd; if ( sock >= 0 ) { - while ( nonz < 1000 && recvlen > 0 ) + while ( nonz < 100 && recvlen > 0 ) { memset(&pfd,0,sizeof(pfd)); pfd.fd = sock; @@ -278,9 +244,28 @@ int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int break; if ( (recvlen= nn_recv(sock,&ptr,NN_MSG,0)) > 0 ) { +//printf("RECV.(%s)\n",(char *)ptr); nonz++; if ( (retstr= LP_process_message(ctx,typestr,myipaddr,pubsock,ptr,recvlen,sock)) != 0 ) free(retstr); + if ( Broadcaststr != 0 ) + { + //printf("self broadcast.(%s)\n",Broadcaststr); + str = Broadcaststr; + Broadcaststr = 0; + if ( (argjson= cJSON_Parse(str)) != 0 ) + { + if ( jobj(argjson,"method") != 0 && strcmp("connect",jstr(argjson,"method")) == 0 ) + printf("self.(%s)\n",str); + if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,0,0) <= 0 ) + { + if ( (retstr= stats_JSON(ctx,myipaddr,pubsock,argjson,remoteaddr,0)) != 0 ) + free(retstr); + } + free_json(argjson); + } + free(str); + } } } } @@ -289,7 +274,7 @@ int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int void command_rpcloop(void *myipaddr) { - int32_t nonz = 0; char *origipaddr; struct LP_peerinfo *peer,*tmp; void *ctx; //struct iguana_info *coin,*ctmp; + int32_t nonz = 0; char *origipaddr; struct LP_peerinfo *peer,*tmp; void *ctx; ctx = bitcoin_ctx(); if ( (origipaddr= myipaddr) == 0 ) origipaddr = "127.0.0.1"; @@ -302,10 +287,14 @@ void command_rpcloop(void *myipaddr) { if ( (rand() % 10000) == 0 ) peer->errors--; - else continue; + else + { + //printf("skip %s\n",peer->ipaddr); + continue; + } } //printf("check %s pubsock.%d\n",peer->ipaddr,peer->subsock); - nonz += LP_sock_check("PULL",ctx,origipaddr,LP_mypubsock,peer->subsock); + nonz += LP_sock_check("PULL",ctx,origipaddr,LP_mypubsock,peer->subsock,peer->ipaddr); } /*HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht { @@ -315,7 +304,7 @@ void command_rpcloop(void *myipaddr) nonz += LP_sock_check(coin->symbol,ctx,origipaddr,-1,coin->bussock,LP_profitratio - 1.); }*/ if ( LP_mypullsock >= 0 ) - nonz += LP_sock_check("SUB",ctx,origipaddr,-1,LP_mypullsock); + nonz += LP_sock_check("SUB",ctx,origipaddr,-1,LP_mypullsock,"127.0.0.1"); //if ( LP_mybussock >= 0 ) // nonz += LP_sock_check("BUS",ctx,origipaddr,-1,LP_mybussock); if ( nonz == 0 ) @@ -323,19 +312,118 @@ void command_rpcloop(void *myipaddr) } } -int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int32_t pubsock,char *pushaddr,uint16_t myport,char *passphrase) +int32_t LP_utxos_sync(struct LP_peerinfo *peer) { - static uint32_t counter,numpeers,lastresync; //lastforward - struct LP_utxoinfo *utxo,*utmp; cJSON *retjson; struct iguana_info *coin,*ctmp; char *retstr,*origipaddr; struct LP_peerinfo *peer,*tmp,*mostpeer; uint32_t id,now; int32_t mostutxos,nonz = 0,n=0,num,lastn=-1; + int32_t i,j,n=0,m,v,posted=0; bits256 txid; cJSON *array,*item,*item2,*array2,*array3; uint64_t total,total2,metric; struct iguana_info *coin,*ctmp; struct LP_address *ap; char *retstr,*retstr2,*coinaddr; + HASH_ITER(hh,LP_coins,coin,ctmp) + { + if ( coin->inactive != 0 )//|| (coin->electrum != 0 && coin->obooktime == 0) ) + continue; + total = 0; + LP_listunspent_both(coin->symbol,coin->smartaddr); + if ( (array= LP_address_utxos(coin,coin->smartaddr,1)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; i 0 && total > 0 && (retstr= issue_LP_listunspent(peer->ipaddr,peer->port,coin->symbol,coin->smartaddr)) != 0 ) + { + total2 = 0; + if ( (array2= cJSON_Parse(retstr)) != 0 ) + { + if ( (m= cJSON_GetArraySize(array2)) > 0 ) + { + for (i=0; iipaddr,jprint(item,0)); + if ( (retstr2= issue_LP_uitem(peer->ipaddr,peer->port,coin->symbol,coin->smartaddr,txid,v,jint(item,"height"),j64bits(item,"value"))) != 0 ) + free(retstr2); + posted++; + } + } + if ( 0 && posted != 0 ) + printf(">>>>>>>> %s compare %s %s (%.8f n%d) (%.8f m%d)\n",peer->ipaddr,coin->symbol,coin->smartaddr,dstr(total),n,dstr(total2),m); + } //else printf("%s matches\n",peer->ipaddr); + free_json(array2); + } + free(retstr); + } + } + if ( (retstr= issue_LP_listunspent(peer->ipaddr,peer->port,coin->symbol,"")) != 0 ) + { + if ( (array2= cJSON_Parse(retstr)) != 0 ) + { + if ( (m= cJSON_GetArraySize(array2)) > 0 ) + { + for (j=0; j %.8f n.%d\n",coinaddr,dstr(metric>>16),(uint16_t)metric); + if ( (ap= LP_addressfind(coin,coinaddr)) == 0 || _LP_unspents_metric(ap->total,ap->n) != metric ) + { + if ( ap == 0 || ap->n < (metric & 0xffff) ) + { + if ( (retstr2= issue_LP_listunspent(peer->ipaddr,peer->port,coin->symbol,coinaddr)) != 0 ) + { + if ( (array3= cJSON_Parse(retstr2)) != 0 ) + { + LP_unspents_array(coin,coinaddr,array3); + //printf("pulled.(%s)\n",retstr2); + free_json(array3); + } + free(retstr2); + } + } //else printf("wait for %s to pull %d vs %d\n",peer->ipaddr,ap!=0?ap->n:-1,(uint16_t)metric); + } + } + } + } + free_json(array2); + } + //printf("processed.(%s)\n",retstr); + free(retstr); + } + } + return(posted); +} + +int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int32_t pubsock,char *pushaddr,uint16_t myport) +{ + static uint32_t counter,numpeers; + struct iguana_info *coin,*ctmp; char *retstr,*origipaddr; struct LP_peerinfo *peer,*tmp; uint32_t now; bits256 zero; int32_t needpings,height,nonz = 0; now = (uint32_t)time(NULL); if ( (origipaddr= myipaddr) == 0 ) origipaddr = "127.0.0.1"; if ( mypeer == 0 ) myipaddr = "127.0.0.1"; - //if ( LP_canbind == 0 ) printf("counter.%d canbind.%d peers\n",counter,LP_canbind); numpeers = LP_numpeers(); - mostutxos = 0; - mostpeer = 0; + needpings = 0; HASH_ITER(hh,LP_peerinfos,peer,tmp) { if ( peer->errors >= LP_MAXPEER_ERRORS ) @@ -343,108 +431,53 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int if ( (rand() % 10000) == 0 ) { peer->errors--; - peer->diduquery = 0; + if ( peer->errors < LP_MAXPEER_ERRORS ) + peer->diduquery = 0; } if ( IAMLP == 0 ) continue; } - if ( now > peer->lastpeers+60 && peer->numpeers > 0 && (peer->numpeers != numpeers || (rand() % 10000) == 0) ) + if ( now > peer->lastpeers+60 && peer->numpeers > 0 && (peer->numpeers != numpeers || (rand() % 1000) == 0) ) { - //if ( IAMLP != 0 ) - // printf("numpeers.%d updatepeer.%s lag.%d\n",numpeers,peer->ipaddr,now-peer->lastpeers); peer->lastpeers = now; - //if ( IAMLP != 0 && peer->numpeers != numpeers ) - // printf("%s num.%d vs %d\n",peer->ipaddr,peer->numpeers,numpeers); if ( strcmp(peer->ipaddr,myipaddr) != 0 ) - LP_peersquery(mypeer,pubsock,peer->ipaddr,peer->port,myipaddr,myport); - if ( IAMLP != 0 && LP_mypeer != 0 && strcmp(peer->ipaddr,myipaddr) != 0 ) { - if ( (retstr= issue_LP_numutxos(peer->ipaddr,peer->port,LP_mypeer->ipaddr,LP_mypeer->port,LP_mypeer->numpeers,LP_mypeer->numutxos)) != 0 ) - { - //printf("%d <- (%s)\n",peer->numutxos,retstr); - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( (num= jint(retjson,"numutxos")) > peer->numutxos ) - peer->numutxos = num; - if ( (num= jint(retjson,"numpeers")) > peer->numpeers ) - peer->numpeers = num; - if ( (id= juint(retjson,"session")) != 0 ) - peer->sessionid = id; - free_json(retjson); - } - free(retstr); - retstr = 0; - } + LP_peersquery(mypeer,pubsock,peer->ipaddr,peer->port,myipaddr,myport); + peer->diduquery = 0; + LP_utxos_sync(peer); } } if ( peer->diduquery == 0 ) { - if ( lastn != n || n < 20 ) - { - lastn = n; - n = LP_peer_utxosquery(mypeer,myport,pubsock,peer,now,60,100); - } - LP_peer_pricesquery(peer->ipaddr,peer->port); + LP_peer_pricesquery(peer); peer->diduquery = now; } - if ( peer->numutxos > mostutxos ) + if ( peer->needping != 0 ) { - mostutxos = peer->numutxos; - mostpeer = peer; + needpings++; + if ( (retstr= issue_LP_notify(peer->ipaddr,peer->port,"127.0.0.1",0,numpeers,G.LP_sessionid,G.LP_myrmd160str,G.LP_mypub25519)) != 0 ) + free(retstr); + peer->needping = 0; } } - //printf("numutxos vs mine.%d\n",LP_mypeer != 0 ? LP_mypeer->numutxos : -1); - if ( LP_mypeer != 0 && mostpeer != 0 && ((LP_mypeer->numutxos < mostutxos && time(NULL) > lastresync+10) || time(NULL) > lastresync+60) ) + if ( needpings != 0 || (counter % 6000) == 5 ) { - //printf("myutxos.%d most.%d %s\n",LP_mypeer->numutxos,mostutxos,mostpeer->ipaddr); - LP_peer_utxosquery(LP_mypeer,myport,pubsock,mostpeer,now,60,(mostutxos-LP_mypeer->numutxos) * 2); - lastresync = (uint32_t)time(NULL); - //LP_peer_pricesquery(mostpeer->ipaddr,mostpeer->port); + //printf("needpings.%d send notify\n",needpings); + LP_notify_pubkeys(ctx,pubsock); } if ( (counter % 6000) == 10 ) { - LP_myutxo_updates(ctx,pubsock,passphrase); - HASH_ITER(hh,LP_utxoinfos[0],utxo,utmp) - { - LP_utxo_spentcheck(pubsock,utxo); - } - HASH_ITER(hh,LP_utxoinfos[1],utxo,utmp) - { - LP_utxo_spentcheck(pubsock,utxo); - if ( LP_isunspent(utxo) > 0 && utxo->T.lasttime == 0 && LP_ismine(utxo) > 0 ) - { - char str[65]; printf("publish mybob %s\n",bits256_str(str,utxo->payment.txid)); - LP_utxo_clientpublish(utxo); - } - } + LP_privkey_updates(ctx,pubsock,0); } HASH_ITER(hh,LP_coins,coin,ctmp) // firstrefht,firstscanht,lastscanht { - int32_t height; bits256 zero; //struct LP_address *ap,*atmp; struct LP_address_utxo *up; - //printf("%s ref.%d scan.%d to %d, longest.%d\n",coin->symbol,coin->firstrefht,coin->firstscanht,coin->lastscanht,coin->longestchain); - if ( coin->inactive != 0 || coin->electrum != 0 ) + memset(&zero,0,sizeof(zero)); + if ( coin->inactive != 0 ) continue; - /*if ( time(NULL) > coin->lastmonitor+60 ) - { - portable_mutex_lock(&coin->txmutex); - HASH_ITER(hh,coin->addresses,ap,atmp) - { - if ( ap->monitor != 0 ) - { - DL_FOREACH(ap->utxos,up) - { - if ( up->spentflag == 0 ) - { - if ( LP_txvalue(0,coin->symbol,up->U.txid,up->U.vout) == 0 ) - up->spentflag = (uint32_t)time(NULL); - } - } - } - } - portable_mutex_unlock(&coin->txmutex); - coin->lastmonitor = (uint32_t)time(NULL); - }*/ - memset(zero.bytes,0,sizeof(zero)); + if ( coin->electrum != 0 ) + continue; + //if ( coin->obooktime == 0 ) + // continue; if ( time(NULL) > coin->lastgetinfo+LP_GETINFO_INCR ) { if ( (height= LP_getheight(coin)) > coin->longestchain ) @@ -453,16 +486,6 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int if ( coin->firstrefht != 0 ) printf(">>>>>>>>>> set %s longestchain %d (ref.%d [%d, %d])\n",coin->symbol,height,coin->firstrefht,coin->firstscanht,coin->lastscanht); } else LP_mempoolscan(coin->symbol,zero); - /*if ( (obj= LP_getinfo(coin->symbol)) != 0 ) - { - if ( (height= jint(obj,"blocks")) > coin->longestchain ) - { - coin->longestchain = height; - if ( coin->firstrefht != 0 ) - printf(">>>>>>>>>> set %s longestchain %d (ref.%d [%d, %d])\n",coin->symbol,height,coin->firstrefht,coin->firstscanht,coin->lastscanht); - } else LP_mempoolscan(coin->symbol,zero); - free_json(obj); - } else printf("error getting info.%s\n",coin->symbol);*/ coin->lastgetinfo = (uint32_t)time(NULL); } if ( coin->firstrefht == 0 ) @@ -493,6 +516,7 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int continue; } coin->lastscanht++; + //LP_getestimatedrate(coin); break; } if ( (counter % 6000) == 60 ) @@ -507,7 +531,7 @@ int32_t LP_mainloop_iter(void *ctx,char *myipaddr,struct LP_peerinfo *mypeer,int return(nonz); } -void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins,char *passphrase) +void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins) { int32_t i,n; cJSON *item; for (i=0; i /tmp/myipaddr") == 0 ) + portable_mutex_init(&LP_butxomutex); + if ( system("curl -s4 checkip.amazonaws.com > DB/myipaddr") == 0 ) { - if ( (myipaddr= OS_filestr(&filesize,"/tmp/myipaddr")) != 0 && myipaddr[0] != 0 ) + if ( (myipaddr= OS_filestr(&filesize,"DB/myipaddr")) != 0 && myipaddr[0] != 0 ) { n = strlen(myipaddr); if ( myipaddr[n-1] == '\n' ) @@ -650,7 +672,7 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu { if ( nn_bind(pubsock,bindaddr) >= 0 ) { - timeout = 10; + timeout = 1; nn_setsockopt(pubsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)); } else @@ -673,7 +695,9 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu //LP_deadman_switch = (uint32_t)time(NULL); printf("canbind.%d my command address is (%s) pullsock.%d pullport.%u\n",LP_canbind,pushaddr,LP_mypullsock,mypullport); printf("initcoins\n"); - LP_initcoins(ctx,pubsock,jobj(argjson,"coins"),passphrase); + LP_initcoins(ctx,pubsock,jobj(argjson,"coins")); + G.waiting = 1; + LP_passphrase_init(passphrase,jstr(argjson,"gui")); if ( IAMLP != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_psockloop,(void *)&myipaddr) != 0 ) { printf("error launching LP_psockloop for (%s)\n",myipaddr); @@ -701,11 +725,22 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu } //if ( (retstr= basilisk_swapentry(0,0)) != 0 ) // free(retstr); + int32_t nonz; + printf("start mainloop\n"); while ( 1 ) { - //fprintf(stderr,"."); - if ( LP_mainloop_iter(ctx,myipaddr,mypeer,pubsock,pushaddr,myport,passphrase) == 0 ) - usleep(1000000 / MAINLOOP_PERSEC); + nonz = 0; + G.waiting = 1; + while ( G.initializing != 0 ) + { + fprintf(stderr,"."); + sleep(3); + } + if ( LP_mainloop_iter(ctx,myipaddr,mypeer,pubsock,pushaddr,myport) != 0 ) + nonz++; + if ( nonz == 0 ) + usleep(50000); + else usleep(5000); } } diff --git a/iguana/exchanges/LP_network.c b/iguana/exchanges/LP_network.c index aadc2f485..582c1f37a 100644 --- a/iguana/exchanges/LP_network.c +++ b/iguana/exchanges/LP_network.c @@ -46,7 +46,7 @@ int32_t _LP_send(int32_t sock,void *msg,int32_t sendlen,int32_t freeflag) } if ( (sentbytes= nn_send(sock,msg,sendlen,0)) != sendlen ) printf("LP_send sent %d instead of %d\n",sentbytes,sendlen); - //else printf("SENT.(%s)\n",msg); + else printf("SENT.(%s)\n",(char *)msg); if ( freeflag != 0 ) free(msg); return(sentbytes); @@ -157,12 +157,12 @@ void queue_loop(void *ignore) { if ( (sentbytes= nn_send(ptr->sock,ptr->msg,ptr->msglen,0)) != ptr->msglen ) printf("%d LP_send sent %d instead of %d\n",n,sentbytes,ptr->msglen); - // else printf("%d %p qsent %u msglen.%d peerind.%d\n",n,ptr,ptr->crc32,ptr->msglen,ptr->peerind); + //else printf("%d %p qsent %u msglen.%d peerind.%d (%s)\n",n,ptr,ptr->crc32,ptr->msglen,ptr->peerind,ptr->msg); ptr->sock = -1; if ( ptr->peerind > 0 ) ptr->starttime = (uint32_t)time(NULL); else flag = 1; - } + } //else printf("sock not ready to send.%d\n",ptr->msglen); } else if ( time(NULL) > ptr->starttime+13 ) { @@ -199,7 +199,7 @@ void queue_loop(void *ignore) //if ( n != 0 ) // printf("LP_Q.[%d]\n",n); if ( nonz == 0 ) - usleep(500000); + usleep(50000); } } @@ -214,7 +214,7 @@ void _LP_queuesend(uint32_t crc32,int32_t sock0,int32_t sock1,uint8_t *msg,int32 printf("_LP_queuesend0 sent %d instead of %d\n",sentbytes,msglen); else { - //printf("Q sent %u\n",crc32); + //printf("Q sent %u msglen.%d (%s)\n",crc32,msglen,msg); sock0 = -1; } } @@ -232,17 +232,16 @@ void _LP_queuesend(uint32_t crc32,int32_t sock0,int32_t sock1,uint8_t *msg,int32 peerind = 1; sock0 = LP_peerindsock(&peerind); } - portable_mutex_lock(&LP_networkmutex); if ( sock0 >= 0 ) _LP_sendqueueadd(crc32,sock0,msg,msglen,needack * peerind); if ( sock1 >= 0 ) _LP_sendqueueadd(crc32,sock1,msg,msglen,needack); - portable_mutex_unlock(&LP_networkmutex); } void LP_queuesend(uint32_t crc32,int32_t pubsock,char *base,char *rel,uint8_t *msg,int32_t msglen) { //struct iguana_info *coin; int32_t flag=0,socks[2]; + portable_mutex_lock(&LP_networkmutex); if ( pubsock >= 0 ) { //socks[0] = socks[1] = -1; @@ -254,6 +253,7 @@ void LP_queuesend(uint32_t crc32,int32_t pubsock,char *base,char *rel,uint8_t *m _LP_queuesend(crc32,pubsock,-1,msg,msglen,0); //else _LP_queuesend(socks[0],socks[1],msg,msglen,0); } else _LP_queuesend(crc32,-1,-1,msg,msglen,1); + portable_mutex_unlock(&LP_networkmutex); } // first 2 bytes == (crc32 & 0xffff) if encrypted, then nonce is next crypto_box_NONCEBYTES @@ -311,8 +311,11 @@ void LP_broadcast_message(int32_t pubsock,char *base,char *rel,bits256 destpub25 jdelete(argjson,"method2"); jaddstr(argjson,"method2",method); jaddstr(argjson,"method",method); - //printf("CRC32.%u (%s)\n",crc32,(char *)msg); + //if ( strncmp(method,"connect",7) == 0 || strcmp(method,"reserved") == 0 ) + // printf("CRC32.%u (%s)\n",crc32,msgstr); LP_broadcast_finish(pubsock,base,rel,msg,argjson,0); + //if ( strncmp(method,"connect",7) == 0 || strcmp(method,"reserved") == 0 ) + // printf("finished %u\n",crc32); } // else printf("no valid method in (%s)\n",msgstr); free_json(argjson); } else printf("couldnt parse (%s)\n",msgstr); diff --git a/iguana/exchanges/LP_ordermatch.c b/iguana/exchanges/LP_ordermatch.c index 52d4f418d..a3570d889 100644 --- a/iguana/exchanges/LP_ordermatch.c +++ b/iguana/exchanges/LP_ordermatch.c @@ -25,10 +25,15 @@ uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee) { if ( strcmp(coin->symbol,"BTC") == 0 ) { - if ( txfee == 0 && (txfee= LP_getestimatedrate(coin) * LP_AVETXSIZE) < LP_MIN_TXFEE ) - txfee = LP_MIN_TXFEE; - } - else txfee = coin->txfee; + coin->rate = LP_getestimatedrate(coin); + if ( (txfee= SATOSHIDEN * coin->rate * LP_AVETXSIZE) <= LP_MIN_TXFEE ) + { + coin->rate = -1.; + coin->rate = _LP_getestimatedrate(coin); + if ( (txfee= SATOSHIDEN * coin->rate * LP_AVETXSIZE) <= LP_MIN_TXFEE ) + txfee = LP_MIN_TXFEE; + } + } else txfee = coin->txfee; if ( txfee < LP_MIN_TXFEE ) txfee = LP_MIN_TXFEE; } @@ -39,6 +44,7 @@ void LP_txfees(uint64_t *txfeep,uint64_t *desttxfeep,char *base,char *rel) { *txfeep = LP_txfeecalc(LP_coinfind(base),0); *desttxfeep = LP_txfeecalc(LP_coinfind(rel),0); + printf("LP_txfees(%.8f %.8f)\n",dstr(*txfeep),dstr(*desttxfeep)); } double LP_qprice_calc(int64_t *destsatoshisp,int64_t *satoshisp,double price,uint64_t b_satoshis,uint64_t txfee,uint64_t a_value,uint64_t maxdestsatoshis,uint64_t desttxfee) @@ -126,7 +132,7 @@ cJSON *LP_quotejson(struct LP_quoteinfo *qp) jadd64bits(retjson,"destsatoshis",qp->destsatoshis); if ( qp->satoshis != 0 ) { - price = (double)qp->destsatoshis / qp->satoshis; + price = (double)qp->destsatoshis / (qp->satoshis - qp->txfee); jaddnum(retjson,"price",price); } } @@ -167,11 +173,11 @@ int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char * LP_txfees(&qp->txfee,&qp->desttxfee,utxo->coin,qp->destcoin); qp->satoshis = satoshis;//(destsatoshis / price) + 0.49; qp->destsatoshis = destsatoshis; - if ( utxo->iambob == 0 || qp->txfee >= qp->satoshis || qp->txfee >= utxo->deposit.value || utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis) ) + /*if ( qp->txfee >= qp->satoshis || qp->txfee >= utxo->deposit.value || utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis) ) //utxo->iambob == 0 || { printf("quoteinit error.(%d %d %d %d) %.8f vs %.8f\n",utxo->iambob == 0,qp->txfee >= qp->satoshis,qp->txfee >= utxo->deposit.value,utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis),dstr(utxo->deposit.value),dstr(LP_DEPOSITSATOSHIS(qp->satoshis))); return(-1); - } + }*/ qp->txid = utxo->payment.txid; qp->vout = utxo->payment.vout; qp->txid2 = utxo->deposit.txid; @@ -202,7 +208,7 @@ char *LP_quotereceived(cJSON *argjson) { struct LP_cacheinfo *ptr; double price; struct LP_quoteinfo Q; LP_quoteparse(&Q,argjson); - price = (double)Q.destsatoshis / Q.satoshis; + price = (double)Q.destsatoshis / (Q.satoshis - Q.txfee); if ( (ptr= LP_cacheadd(Q.srccoin,Q.destcoin,Q.txid,Q.vout,price,&Q)) != 0 ) { ptr->Q = Q; @@ -215,7 +221,7 @@ char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *re { bits256 zero; char *msg; cJSON *reqjson = cJSON_CreateObject(); memset(zero.bytes,0,sizeof(zero)); - jaddbits256(reqjson,"pubkey",LP_mypub25519); + jaddbits256(reqjson,"pubkey",G.LP_mypub25519); jaddstr(reqjson,"base",base); jaddstr(reqjson,"rel",rel); jaddnum(reqjson,"price",price); @@ -225,6 +231,19 @@ char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *re return(clonestr("{\"result\":\"success\"}")); } +void LP_notify_pubkeys(void *ctx,int32_t pubsock) +{ + bits256 zero; char *msg,secpstr[67]; cJSON *reqjson = cJSON_CreateObject(); + memset(zero.bytes,0,sizeof(zero)); + jaddstr(reqjson,"method","notify"); + jaddstr(reqjson,"rmd160",G.LP_myrmd160str); + jaddbits256(reqjson,"pub",G.LP_mypub25519); + init_hexbytes_noT(secpstr,G.LP_pubsecp,33); + jaddstr(reqjson,"pubsecp",secpstr); + msg = jprint(reqjson,1); + LP_broadcast_message(pubsock,"","",zero,msg); +} + char *LP_postedprice(cJSON *argjson) { bits256 pubkey; double price; char *base,*rel; @@ -241,15 +260,15 @@ char *LP_postedprice(cJSON *argjson) return(clonestr("{\"error\":\"missing fields in posted price\"}")); } -int32_t LP_quote_checkmempool(struct LP_quoteinfo *qp) +int32_t LP_quote_checkmempool(struct LP_quoteinfo *qp,struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo) { int32_t selector,spendvini; bits256 spendtxid; - if ( (selector= LP_mempool_vinscan(&spendtxid,&spendvini,qp->srccoin,qp->coinaddr,qp->txid,qp->vout,qp->txid2,qp->vout2)) >= 0 ) + if ( butxo != 0 && (selector= LP_mempool_vinscan(&spendtxid,&spendvini,qp->srccoin,qp->coinaddr,qp->txid,qp->vout,qp->txid2,qp->vout2)) >= 0 ) { char str[65]; printf("LP_tradecommand selector.%d in mempool %s vini.%d",selector,bits256_str(str,spendtxid),spendvini); return(-1); } - if ( (selector= LP_mempool_vinscan(&spendtxid,&spendvini,qp->destcoin,qp->destaddr,qp->desttxid,qp->destvout,qp->feetxid,qp->feevout)) >= 0 ) + if ( autxo != 0 && (selector= LP_mempool_vinscan(&spendtxid,&spendvini,qp->destcoin,qp->destaddr,qp->desttxid,qp->destvout,qp->feetxid,qp->feevout)) >= 0 ) { char str[65]; printf("LP_tradecommand dest selector.%d in mempool %s vini.%d",selector,bits256_str(str,spendtxid),spendvini); return(-1); @@ -257,57 +276,83 @@ int32_t LP_quote_checkmempool(struct LP_quoteinfo *qp) return(0); } -double LP_quote_validate(struct LP_utxoinfo **autxop,struct LP_utxoinfo **butxop,struct LP_quoteinfo *qp,int32_t iambob) +double LP_quote_validate(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,struct LP_quoteinfo *qp,int32_t iambob) { - double qprice; uint64_t txfee,desttxfee,srcvalue,srcvalue2,destvalue,destvalue2; - *autxop = *butxop = 0; - if ( LP_iseligible(&srcvalue,&srcvalue2,1,qp->srccoin,qp->txid,qp->vout,qp->satoshis,qp->txid2,qp->vout2) == 0 ) + double qprice=0.; uint64_t txfee,desttxfee,srcvalue=0,srcvalue2=0,destvalue=0,destvalue2=0; + printf("quote %s %.8f -> %s %.8f\n",qp->srccoin,dstr(qp->satoshis),qp->destcoin,dstr(qp->destsatoshis)); + if ( butxo != 0 ) { - printf("bob not eligible\n"); - return(-2); + if (LP_iseligible(&srcvalue,&srcvalue2,1,qp->srccoin,qp->txid,qp->vout,qp->satoshis,qp->txid2,qp->vout2) == 0 ) + { + printf("bob not eligible %s\n",jprint(LP_quotejson(qp),1)); + return(-2); + } + if ( bits256_cmp(butxo->deposit.txid,qp->txid2) != 0 || butxo->deposit.vout != qp->vout2 ) + { + char str[65],str2[65]; printf("%s != %s v%d != %d\n",bits256_str(str,butxo->deposit.txid),bits256_str(str2,qp->txid2),butxo->deposit.vout,qp->vout2); + return(-6); + } + if ( strcmp(butxo->coinaddr,qp->coinaddr) != 0 ) + { + printf("(%s) != (%s)\n",butxo->coinaddr,qp->coinaddr); + return(-7); + } } - if ( LP_iseligible(&destvalue,&destvalue2,0,qp->destcoin,qp->desttxid,qp->destvout,qp->destsatoshis,qp->feetxid,qp->feevout) == 0 ) + if ( autxo != 0 && LP_iseligible(&destvalue,&destvalue2,0,qp->destcoin,qp->desttxid,qp->destvout,qp->destsatoshis,qp->feetxid,qp->feevout) == 0 ) { char str[65]; printf("alice not eligible (%.8f %.8f) %s/v%d\n",dstr(destvalue),dstr(destvalue2),bits256_str(str,qp->feetxid),qp->feevout); return(-3); } - if ( LP_quote_checkmempool(qp) < 0 ) + if ( LP_quote_checkmempool(qp,autxo,butxo) < 0 ) return(-4); - if ( (*butxop= LP_utxofind(1,qp->txid,qp->vout)) == 0 ) - return(-5); - if ( bits256_cmp((*butxop)->deposit.txid,qp->txid2) != 0 || (*butxop)->deposit.vout != qp->vout2 ) - return(-6); - if ( strcmp((*butxop)->coinaddr,qp->coinaddr) != 0 ) - return(-7); - if ( iambob == 0 ) - { - if ( (*autxop= LP_utxofind(0,qp->desttxid,qp->destvout)) == 0 ) - return(-8); - if ( bits256_cmp((*autxop)->fee.txid,qp->feetxid) != 0 || (*autxop)->fee.vout != qp->feevout ) + //if ( iambob != 0 && (*butxop= LP_utxofind(1,qp->txid,qp->vout)) == 0 ) + // return(-5); + if ( iambob == 0 && autxo != 0 ) + { + //if ( (*autxop= LP_utxofind(0,qp->desttxid,qp->destvout)) == 0 ) + // return(-8); + if ( bits256_cmp(autxo->fee.txid,qp->feetxid) != 0 || autxo->fee.vout != qp->feevout ) return(-9); - if ( strcmp((*autxop)->coinaddr,qp->destaddr) != 0 ) + if ( strcmp(autxo->coinaddr,qp->destaddr) != 0 ) return(-10); } - if ( destvalue < qp->desttxfee+qp->destsatoshis || srcvalue < qp->txfee+qp->satoshis ) + if ( autxo != 0 && destvalue < qp->desttxfee+qp->destsatoshis ) { - printf("destvalue %.8f srcvalue %.8f, destsatoshis %.8f or satoshis %.8f is too small txfees %.8f %.8f?\n",dstr(destvalue),dstr(srcvalue),dstr(qp->destsatoshis),dstr(qp->satoshis),dstr(qp->desttxfee),dstr(qp->txfee)); + printf("destvalue %.8f destsatoshis %.8f is too small txfee %.8f?\n",dstr(destvalue),dstr(qp->destsatoshis),dstr(qp->desttxfee)); return(-11); } - qprice = ((double)qp->destsatoshis / qp->satoshis); - if ( qp->satoshis < (srcvalue / LP_MINVOL) || srcvalue < qp->txfee*LP_MINSIZE_TXFEEMULT ) + if ( butxo != 0 && srcvalue < qp->txfee+qp->satoshis ) { - printf("utxo payment %.8f is less than %f covered by Q %.8f or <10x txfee %.8f\n",dstr(srcvalue),1./LP_MINVOL,dstr(qp->satoshis),dstr(qp->txfee)); - return(-12); - } - if ( qp->destsatoshis < (destvalue / LP_MINCLIENTVOL) || destvalue < qp->desttxfee*LP_MINSIZE_TXFEEMULT ) - { - printf("destsatoshis %.8f is less than %f of value %.8f or < 10x txfee %.8f\n",dstr(qp->destsatoshis),1./LP_MINCLIENTVOL,dstr(destvalue),dstr(qp->desttxfee)); - return(-13); + printf("srcvalue %.8f [%.8f] satoshis %.8f is too small txfee %.8f?\n",dstr(srcvalue),dstr(srcvalue) - dstr(qp->txfee+qp->satoshis),dstr(qp->satoshis),dstr(qp->txfee)); + return(-33); } + if ( qp->satoshis != 0 ) + qprice = ((double)qp->destsatoshis / (qp->satoshis-qp->txfee)); LP_txfees(&txfee,&desttxfee,qp->srccoin,qp->destcoin); + if ( txfee < qp->txfee ) + txfee = qp->txfee; + if ( desttxfee < qp->desttxfee ) + desttxfee = qp->desttxfee; printf("qprice %.8f <- %.8f/%.8f txfees.(%.8f %.8f) vs (%.8f %.8f)\n",qprice,dstr(qp->destsatoshis),dstr(qp->satoshis),dstr(qp->txfee),dstr(qp->desttxfee),dstr(txfee),dstr(desttxfee)); if ( qp->txfee < LP_REQUIRED_TXFEE*txfee || qp->desttxfee < LP_REQUIRED_TXFEE*desttxfee ) return(-14); + if ( butxo != 0 ) + { + //qprice 2259.01692494 <- 10.34279604/0.00457845 txfees.(0.00042631 0.00010000) vs (0.00042791 0.00010000) + if ( qp->satoshis < (srcvalue / LP_MINVOL) || srcvalue < qp->txfee*LP_MINSIZE_TXFEEMULT ) + { + printf("utxo payment %.8f is less than %f covered by Q %.8f or <10x txfee %.8f\n",dstr(srcvalue),1./LP_MINVOL,dstr(qp->satoshis),dstr(qp->txfee)); + return(-12); + } + } + if ( autxo != 0 ) + { + if ( qp->destsatoshis < (destvalue / LP_MINCLIENTVOL) || destvalue < qp->desttxfee*LP_MINSIZE_TXFEEMULT ) + { + printf("destsatoshis %.8f is less than %f of value %.8f or < 10x txfee %.8f\n",dstr(qp->destsatoshis),1./LP_MINCLIENTVOL,dstr(destvalue),dstr(qp->desttxfee)); + return(-13); + } + } return(qprice); } @@ -325,7 +370,7 @@ int32_t LP_arrayfind(cJSON *array,bits256 txid,int32_t vout) double LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct LP_quoteinfo *qp) { - cJSON *reqjson; char *msg; int32_t i,flag = 0; double price = 0.; struct LP_utxoinfo *utxo; + cJSON *reqjson; bits256 zero; char *msg; int32_t i,flag = 0; double price = 0.; struct LP_utxoinfo *utxo; if ( strcmp(method,"request") == 0 ) { if ( (utxo= LP_utxofind(0,qp->desttxid,qp->destvout)) != 0 && LP_ismine(utxo) > 0 && LP_isavailable(utxo) > 0 ) @@ -343,7 +388,12 @@ double LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct L jaddstr(reqjson,"method",method); msg = jprint(reqjson,1); printf("QUERY.(%s)\n",msg); - LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,qp->srchash,msg); + memset(&zero,0,sizeof(zero)); + if ( 1 && strcmp(method,"request") == 0 ) + { + sleep(3); + LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,zero,msg); + } else LP_broadcast_message(LP_mypubsock,qp->srccoin,qp->destcoin,qp->srchash,msg); for (i=0; i<30; i++) { if ( (price= LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout)) > SMALLVAL ) @@ -354,7 +404,7 @@ double LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct L break; } } - usleep(100000); + usleep(250000); } return(price); } @@ -391,6 +441,107 @@ int32_t LP_nanobind(void *ctx,char *pairstr) return(pairsock); } +int32_t LP_nearest_utxovalue(struct LP_address_utxo **utxos,int32_t n,uint64_t targetval) +{ + int32_t i,mini = -1; int64_t dist; uint64_t mindist = (1LL << 60); + for (i=0; iU.value - targetval); + if ( dist >= 0 && dist < mindist ) + { + printf("(%.8f %.8f %.8f).%d ",dstr(utxos[i]->U.value),dstr(dist),dstr(mindist),mini); + mini = i; + mindist = dist; + } + } + } + return(mini); +} + +uint64_t LP_basesatoshis(double relvolume,double price,uint64_t txfee,uint64_t desttxfee) +{ + printf("basesatoshis %.8f (rel %.8f / price %.8f)\n",dstr(SATOSHIDEN * ((relvolume) / price) + 2*txfee),relvolume,price); + if ( relvolume > dstr(desttxfee) && price > SMALLVAL ) + return(SATOSHIDEN * (relvolume / price) + 2*txfee); + else return(0); +} + +struct LP_utxoinfo *LP_address_utxopair(int32_t iambob,struct LP_address_utxo **utxos,int32_t max,struct iguana_info *coin,char *coinaddr,uint64_t txfee,double relvolume,double price,uint64_t desttxfee) +{ + struct LP_address *ap; uint64_t targetval,targetval2; int32_t m,mini; struct LP_address_utxo *up,*up2; struct LP_utxoinfo *utxo = 0; + if ( coin != 0 && (ap= LP_addressfind(coin,coinaddr)) != 0 ) + { + if ( (m= LP_address_utxo_ptrs(iambob,utxos,max,ap)) > 1 ) + { + targetval = LP_basesatoshis(relvolume,price,txfee,desttxfee); + if ( 1 ) + { + int32_t i; + for (i=0; iU.value)); + printf("targetval %.8f vol %.8f price %.8f txfee %.8f %s\n",dstr(targetval),relvolume,price,dstr(txfee),coinaddr); + } + mini = -1; + if ( targetval != 0 && (mini= LP_nearest_utxovalue(utxos,m,targetval)) >= 0 && (double)utxos[mini]->U.value/targetval < LP_MINVOL-1 ) + { + up = utxos[mini]; + utxos[mini] = 0; + targetval2 = (up->U.value / 8) * 9 + 2*txfee; + if ( (mini= LP_nearest_utxovalue(utxos,m,targetval2)) >= 0 ) + { + if ( up != 0 && (up2= utxos[mini]) != 0 ) + { + if ( (utxo= LP_utxoadd(1,coin->symbol,up->U.txid,up->U.vout,up->U.value,up2->U.txid,up2->U.vout,up2->U.value,coinaddr,ap->pubkey,G.gui,0)) != 0 ) + { + utxo->S.satoshis = targetval; + char str[65],str2[65]; printf("butxo.%p targetval %.8f, found val %.8f %s | targetval2 %.8f val2 %.8f %s\n",utxo,dstr(targetval),dstr(up->U.value),bits256_str(str,utxo->payment.txid),dstr(targetval2),dstr(up2->U.value),bits256_str(str2,utxo->deposit.txid)); + return(utxo); + } + } + } else printf("cant find targetval2 %.8f\n",dstr(targetval2)); + } else if ( targetval != 0 && mini >= 0 ) + printf("targetval %.8f mini.%d ratio %.8f\n",dstr(targetval),mini,(double)utxos[mini]->U.value/targetval); + } else printf("no utxos pass LP_address_utxo_ptrs filter\n"); + } else printf("couldnt find %s %s\n",coin->symbol,coinaddr); + return(0); +} + +void LP_abutxo_set(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,struct LP_quoteinfo *qp) +{ + if ( butxo != 0 ) + { + memset(butxo,0,sizeof(*butxo)); + butxo->pubkey = qp->srchash; + safecopy(butxo->coin,qp->srccoin,sizeof(butxo->coin)); + safecopy(butxo->coinaddr,qp->coinaddr,sizeof(butxo->coinaddr)); + butxo->payment.txid = qp->txid; + butxo->payment.vout = qp->vout; + //butxo->payment.value = qp->value; + butxo->iambob = 1; + butxo->deposit.txid = qp->txid2; + butxo->deposit.vout = qp->vout2; + //butxo->deposit.value = up2->U.value; + butxo->S.satoshis = qp->satoshis; + } + if ( autxo != 0 ) + { + memset(autxo,0,sizeof(*autxo)); + autxo->pubkey = qp->desthash; + safecopy(autxo->coin,qp->destcoin,sizeof(autxo->coin)); + safecopy(autxo->coinaddr,qp->destaddr,sizeof(autxo->coinaddr)); + autxo->payment.txid = qp->desttxid; + autxo->payment.vout = qp->destvout; + //autxo->payment.value = qp->value; + autxo->iambob = 0; + autxo->fee.txid = qp->feetxid; + autxo->fee.vout = qp->feevout; + //autxo->deposit.value = up2->U.value; + autxo->S.satoshis = qp->destsatoshis; + } +} + int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJSON *argjson,char *base,char *rel,double price,struct LP_quoteinfo *qp) { char pairstr[512],*msg; cJSON *retjson; bits256 privkey; int32_t pair=-1,retval = -1,DEXselector = 0; struct basilisk_swap *swap; struct iguana_info *coin; @@ -402,12 +553,14 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ return(-1); } privkey = LP_privkey(utxo->coinaddr,coin->taddr); - if ( bits256_nonz(privkey) != 0 && qp->quotetime >= qp->timestamp-3 && qp->quotetime <= utxo->T.swappending && bits256_cmp(LP_mypub25519,qp->srchash) == 0 ) + if ( bits256_nonz(privkey) != 0 && bits256_cmp(G.LP_mypub25519,qp->srchash) == 0 ) //qp->quotetime >= qp->timestamp-3 && qp->quotetime <= utxo->T.swappending && { if ( (pair= LP_nanobind(ctx,pairstr)) >= 0 ) { LP_requestinit(&qp->R,qp->srchash,qp->desthash,base,qp->satoshis-qp->txfee,rel,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector); + printf("call swapinit\n"); swap = LP_swapinit(1,0,privkey,&qp->R,qp); + printf("swapinit.%p\n",swap); swap->N.pair = pair; utxo->S.swap = swap; swap->utxo = utxo; @@ -427,7 +580,7 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ } else { - printf("dest %.8f vs required %.8f (%d %d %d %d %d)\n",dstr(qp->destsatoshis),dstr(price*(utxo->S.satoshis-qp->txfee)),bits256_nonz(privkey) != 0 ,qp->timestamp == utxo->T.swappending-LP_RESERVETIME,qp->quotetime >= qp->timestamp-3,qp->quotetime < utxo->T.swappending,bits256_cmp(LP_mypub25519,qp->srchash) == 0); + printf("dest %.8f vs required %.8f (%d %d %d %d %d)\n",dstr(qp->destsatoshis),dstr(price*(utxo->S.satoshis-qp->txfee)),bits256_nonz(privkey) != 0 ,qp->timestamp == utxo->T.swappending-LP_RESERVETIME,qp->quotetime >= qp->timestamp-3,qp->quotetime < utxo->T.swappending,bits256_cmp(G.LP_mypub25519,qp->srchash) == 0); } if ( retval < 0 ) { @@ -435,21 +588,57 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ nn_close(pair); LP_availableset(utxo); } else LP_unavailableset(utxo,utxo->S.otherpubkey); + //LP_butxo_swapfields(utxo); return(retval); } char *LP_connectedalice(cJSON *argjson) // alice { - cJSON *retjson; double bid,ask,price,qprice; int32_t pairsock = -1; char *pairstr; int32_t DEXselector = 0; struct LP_utxoinfo *autxo,*butxo; struct LP_quoteinfo Q; struct basilisk_swap *swap; struct iguana_info *coin; + cJSON *retjson; double bid,ask,price,qprice; int32_t pairsock = -1; char *pairstr; int32_t DEXselector = 0; struct LP_utxoinfo *autxo,B,*butxo; struct LP_quoteinfo Q; struct basilisk_swap *swap; struct iguana_info *coin; //uint64_t value,value2; if ( LP_quoteparse(&Q,argjson) < 0 ) clonestr("{\"error\":\"cant parse quote\"}"); - if ( bits256_cmp(Q.desthash,LP_mypub25519) != 0 ) + if ( bits256_cmp(Q.desthash,G.LP_mypub25519) != 0 ) return(clonestr("{\"result\",\"update stats\"}")); - printf("CONNECTED.(%s)\n",jprint(argjson,0)); - if ( (qprice= LP_quote_validate(&autxo,&butxo,&Q,0)) <= SMALLVAL ) + printf("CONNECTED.(%s) numpending.%d\n",jprint(argjson,0),G.LP_pendingswaps); + /*if ( G.LP_pendingswaps > 0 ) + { + printf("swap already pending\n"); + return(clonestr("{\"error\":\"swap already pending\"}")); + }*/ + if ( (autxo= LP_utxopairfind(0,Q.desttxid,Q.destvout,Q.feetxid,Q.feevout)) == 0 ) + { + printf("cant find autxo\n"); + return(clonestr("{\"error\":\"cant find autxo\"}")); + } + if ( autxo->S.swap != 0 ) + return(clonestr("{\"error\":\"ignore duplicate swap\"}")); + butxo = &B; + memset(butxo,0,sizeof(*butxo)); + LP_abutxo_set(0,butxo,&Q); + /*if ( (butxo= LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2)) == 0 ) + { + value = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid,Q.vout); + value2 = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid2,Q.vout2); + if ( value == 0 || value2 == 0 ) + { + printf("zero value %.8f or value2 %.8f\n",dstr(value),dstr(value2)); + return(clonestr("{\"error\":\"spent txid or txid2 for bob?\"}")); + } + if ( (butxo= LP_utxoadd(1,Q.srccoin,Q.txid,Q.vout,value,Q.txid2,Q.vout2,value2,Q.coinaddr,Q.srchash,LP_gui,0)) == 0 ) + { + printf("cant find or create butxo\n"); + return(clonestr("{\"error\":\"cant find or create butxo\"}")); + } + if ( value < Q.satoshis ) + { + printf("butxo value %.8f less satoshis %.8f\n",dstr(value),dstr(Q.satoshis)); + return(clonestr("{\"error\":\"butxo value less than satoshis\"}")); + } + }*/ + if ( (qprice= LP_quote_validate(autxo,butxo,&Q,0)) <= SMALLVAL ) { LP_availableset(autxo); - LP_pendingswaps--; + //G.LP_pendingswaps--; printf("quote validate error %.0f\n",qprice); return(clonestr("{\"error\":\"quote validation error\"}")); } @@ -457,22 +646,14 @@ char *LP_connectedalice(cJSON *argjson) // alice { printf("this node has no price for %s/%s (%.8f %.8f)\n",Q.destcoin,Q.srccoin,bid,ask); LP_availableset(autxo); - LP_pendingswaps--; + //G.LP_pendingswaps--; return(clonestr("{\"error\":\"no price set\"}")); } - printf("%s/%s bid %.8f ask %.8f\n",Q.srccoin,Q.destcoin,bid,ask); - //if ( (price= ask) == 0. ) - price = bid; - /*if ( SATOSHIDEN*qprice > (SATOSHIDEN * price) * 1.001 + 10 ) - { - printf("qprice %.8f too big vs %.8f\n",qprice,price); - LP_availableset(autxo); - LP_pendingswaps--; - return(clonestr("{\"error\":\"quote price too expensive\"}")); - }*/ + printf("%s/%s bid %.8f ask %.8f values %.8f %.8f\n",Q.srccoin,Q.destcoin,bid,ask,dstr(butxo->payment.value),dstr(butxo->deposit.value)); + price = bid; if ( (coin= LP_coinfind(Q.destcoin)) == 0 ) { - LP_pendingswaps--; + //G.LP_pendingswaps--; return(clonestr("{\"error\":\"cant get alicecoin\"}")); } Q.privkey = LP_privkey(Q.destaddr,coin->taddr); @@ -503,7 +684,7 @@ char *LP_connectedalice(cJSON *argjson) // alice printf("connected result.(%s)\n",jprint(retjson,0)); if ( jobj(retjson,"error") != 0 ) LP_availableset(autxo); - else LP_pendingswaps++; + else G.LP_pendingswaps++; return(jprint(retjson,1)); } else @@ -514,22 +695,104 @@ char *LP_connectedalice(cJSON *argjson) // alice } } +int32_t LP_listunspent_both(char *symbol,char *coinaddr) +{ + int32_t i,v,height,n=0; uint64_t value; bits256 txid; char buf[512]; cJSON *array,*item; struct iguana_info *coin = LP_coinfind(symbol); + if ( coin != 0 && coin->inactive == 0 ) + { + if ( coin->electrum != 0 || LP_address_ismine(symbol,coinaddr) <= 0 ) + { + //printf("issue path electrum.%p\n",coin->electrum); + //if ( coin->electrum != 0 && (array= electrum_address_gethistory(symbol,coin->electrum,&array,coinaddr)) != 0 ) + // free_json(array); + n = LP_listunspent_issue(symbol,coinaddr); + } + else + { + //printf("my coin electrum.%p\n",coin->electrum); + sprintf(buf,"[1, 99999999, [\"%s\"]]",coinaddr); + if ( (array= bitcoin_json(coin,"listunspent",buf)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; iinactive:-1); + return(n); +} + int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen) { - char *method,*msg; cJSON *retjson; double qprice,price,bid,ask; struct LP_utxoinfo *autxo,*butxo; int32_t retval = -1; struct LP_quoteinfo Q; + char *method,*msg; uint64_t value,value2; cJSON *retjson; double qprice,price,bid,ask; struct LP_utxoinfo A,B,*autxo,*butxo; struct iguana_info *coin; struct LP_address_utxo *utxos[1000]; struct LP_quoteinfo Q; int32_t retval = -1,max=(int32_t)(sizeof(utxos)/sizeof(*utxos)); if ( (method= jstr(argjson,"method")) != 0 && (strcmp(method,"request") == 0 ||strcmp(method,"connect") == 0) ) { - printf("TRADECOMMAND.(%s)\n",jprint(argjson,0)); + printf("LP_tradecommand: check received %s\n",method); retval = 1; - if ( LP_quoteparse(&Q,argjson) == 0 && bits256_cmp(LP_mypub25519,Q.srchash) == 0 ) + if ( LP_quoteparse(&Q,argjson) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) == 0 && bits256_cmp(G.LP_mypub25519,Q.desthash) != 0 ) { - if ( (price= LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin)) <= SMALLVAL || ask <= SMALLVAL ) + if ( (coin= LP_coinfind(Q.srccoin)) == 0 || (price= LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin)) <= SMALLVAL || ask <= SMALLVAL ) { printf("this node has no price for %s/%s\n",Q.srccoin,Q.destcoin); return(-3); } price = ask; - if ( (qprice= LP_quote_validate(&autxo,&butxo,&Q,1)) <= SMALLVAL ) + autxo = &A; + butxo = &B; + memset(autxo,0,sizeof(*autxo)); + memset(butxo,0,sizeof(*butxo)); + LP_abutxo_set(autxo,butxo,&Q); + if ( (butxo= LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2)) == 0 ) + butxo = &B; + //LP_butxo_swapfields(butxo); + if ( strcmp(method,"request") == 0 ) + { + char str[65],str2[65]; + if ( LP_allocated(butxo->payment.txid,butxo->payment.vout) != 0 || LP_allocated(butxo->deposit.txid,butxo->deposit.vout) != 0 || (qprice= LP_quote_validate(autxo,butxo,&Q,1)) <= SMALLVAL ) + { + printf("butxo.%p replace path %p %s, %p %s, %.8f\n",butxo,LP_allocated(butxo->payment.txid,butxo->payment.vout),bits256_str(str,butxo->payment.txid),LP_allocated(butxo->deposit.txid,butxo->deposit.vout),bits256_str(str2,butxo->deposit.txid),LP_quote_validate(autxo,butxo,&Q,1)); + LP_listunspent_both(Q.srccoin,Q.coinaddr); + if ( (butxo= LP_address_utxopair(1,utxos,max,LP_coinfind(Q.srccoin),Q.coinaddr,Q.txfee,dstr(Q.destsatoshis),price,Q.desttxfee)) != 0 ) + { + Q.txid = butxo->payment.txid; + Q.vout = butxo->payment.vout; + Q.txid2 = butxo->deposit.txid; + Q.vout2 = butxo->deposit.vout; + printf("set butxo.%p %s/v%d %s/v%d %.8f %.8f -> bsat %.8f asat %.8f\n",butxo,bits256_str(str,butxo->payment.txid),butxo->payment.vout,bits256_str(str2,butxo->deposit.txid),butxo->deposit.vout,dstr(butxo->payment.value),dstr(butxo->deposit.value),dstr(butxo->S.satoshis),dstr(autxo->S.satoshis)); + } else printf("cant find utxopair\n"); + //LP_abutxo_set(0,butxo,&Q); + //LP_butxo_swapfields(butxo); + } + else + { + printf("other path %p %p %.8f\n",LP_allocated(butxo->payment.txid,butxo->payment.vout),LP_allocated(butxo->deposit.txid,butxo->deposit.vout), LP_quote_validate(autxo,butxo,&Q,1)); + } + } + if ( butxo == 0 || butxo == &B ) + butxo = LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2); + if ( butxo == 0 ) + { + value = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid,Q.vout); + value2 = LP_txvalue(Q.coinaddr,Q.srccoin,Q.txid2,Q.vout2); + butxo = LP_utxoadd(1,Q.srccoin,Q.txid,Q.vout,value,Q.txid2,Q.vout2,value2,Q.coinaddr,Q.srchash,LP_gui,0); + } + char str[65],str2[65]; printf("butxo.%p (%s %s) TRADECOMMAND.(%s)\n",butxo,butxo!=0?bits256_str(str,butxo->payment.txid):"",butxo!=0?bits256_str(str2,butxo->deposit.txid):"",jprint(argjson,0)); + if ( butxo == 0 || bits256_nonz(butxo->payment.txid) == 0 || bits256_nonz(butxo->deposit.txid) == 0 || butxo->payment.vout < 0 || butxo->deposit.vout < 0 ) + { + char str[65],str2[65]; printf("couldnt find bob utxos for autxo %s/v%d %s/v%d %.8f -> %.8f\n",bits256_str(str,Q.txid),Q.vout,bits256_str(str2,Q.txid2),Q.vout2,dstr(Q.satoshis),dstr(Q.destsatoshis)); + return(1); + } + if ( (qprice= LP_quote_validate(autxo,butxo,&Q,1)) <= SMALLVAL ) { printf("quote validate error %.0f\n",qprice); return(-4); @@ -555,148 +818,38 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, jaddbits256(retjson,"pubkey",butxo->S.otherpubkey); jaddstr(retjson,"method","reserved"); msg = jprint(retjson,1); - printf("set swappending.%u accept qprice %.8f, min %.8f\n(%s)",butxo->T.swappending,qprice,price,msg); - LP_broadcast_message(pubsock,Q.srccoin,Q.destcoin,butxo->S.otherpubkey,msg); butxo->T.lasttime = (uint32_t)time(NULL); + printf("set swappending.%u accept qprice %.8f, min %.8f\n(%s)\n",butxo->T.swappending,qprice,price,msg); + { + bits256 zero; char *msg2; + memset(&zero,0,sizeof(zero)); + msg2 = clonestr(msg); + LP_broadcast_message(pubsock,Q.srccoin,Q.destcoin,zero,msg); + LP_broadcast_message(pubsock,Q.srccoin,Q.destcoin,butxo->S.otherpubkey,msg2); + //LP_butxo_swapfields_set(butxo); + printf("return after RESERVED\n"); + return(2); + } } else printf("warning swappending.%u swap.%p\n",butxo->T.swappending,butxo->S.swap); } else if ( strcmp(method,"connect") == 0 ) // bob { retval = 4; - if ( butxo->T.swappending != 0 && butxo->S.swap == 0 ) + if ( butxo->S.swap == 0 && butxo->T.swappending != 0 ) + { + // validate SPV alice LP_connectstartbob(ctx,pubsock,butxo,argjson,Q.srccoin,Q.destcoin,qprice,&Q); + //LP_butxo_swapfields_set(butxo); + return(3); + } else printf("pend.%u swap %p when connect came in (%s)\n",butxo->T.swappending,butxo->S.swap,jprint(argjson,0)); } + //LP_butxo_swapfields_set(butxo); } } return(retval); } -struct LP_utxoinfo *LP_bestutxo(double *ordermatchpricep,int64_t *bestsatoshisp,int64_t *bestdestsatoshisp,struct LP_utxoinfo *autxo,char *base,double maxprice,int32_t duration,uint64_t txfee,uint64_t desttxfee,uint64_t maxdestsatoshis) -{ - int64_t satoshis,destsatoshis; uint64_t val,val2; bits256 txid,pubkey; char *obookstr; cJSON *orderbook,*asks,*item; struct LP_utxoinfo *butxo,*bestutxo = 0; int32_t i,n,j,vout,numasks; double bestmetric=0.,metric,vol,price,qprice,bestprice = 0.; struct LP_pubkeyinfo *pubp; - *ordermatchpricep = 0.; - *bestsatoshisp = *bestdestsatoshisp = 0; - if ( duration <= 0 ) - duration = LP_ORDERBOOK_DURATION; - if ( maxprice <= 0. || LP_priceinfofind(base) == 0 ) - return(0); - LP_txfees(&txfee,&desttxfee,base,autxo->coin); - if ( (obookstr= LP_orderbook(base,autxo->coin,duration)) != 0 ) - { - if ( (orderbook= cJSON_Parse(obookstr)) != 0 ) - { - if ( (asks= jarray(&numasks,orderbook,"asks")) != 0 ) - { - for (i=0; i 0 && price <= maxprice ) - { - //price *= 1.0001; - //if ( price > maxprice ) - // price = maxprice; - pubkey = jbits256(item,"pubkey"); - if ( bits256_cmp(pubkey,LP_mypub25519) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 && pubp->numerrors < LP_MAXPUBKEY_ERRORS ) - { - if ( bestprice == 0. ) // assumes price ordered asks - bestprice = price; - //printf("item.[%d] %s\n",i,jprint(item,0)); - txid = jbits256(item,"txid"); - vout = jint(item,"vout"); - vol = jdouble(item,"volume"); - metric = price / bestprice; - if ( (butxo= LP_utxofind(1,txid,vout)) != 0 && (long long)(vol*SATOSHIDEN) == butxo->S.satoshis && LP_isavailable(butxo) > 0 && LP_ismine(butxo) == 0 && butxo->T.bestflag == 0 ) - { - if ( LP_iseligible(&val,&val2,butxo->iambob,butxo->coin,butxo->payment.txid,butxo->payment.vout,butxo->S.satoshis,butxo->deposit.txid,butxo->deposit.vout) > 0 ) - { - destsatoshis = ((butxo->S.satoshis - txfee) * price); - satoshis = (destsatoshis / price + 0.49) - txfee; - if ( satoshis <= 0 ) - continue; - qprice = (double)destsatoshis / satoshis; - n = (int32_t)((double)destsatoshis / desttxfee); - if ( n < 10 ) - n = 10; - else n = 3; - for (j=0; jS.satoshis,txfee,autxo->payment.value,maxdestsatoshis,desttxfee)) > price+SMALLVAL ) - break; - } - //printf("j.%d/%d qprice %.8f vs price %.8f best.(%.8f %.8f)\n",j,n,qprice,price,dstr(satoshis),dstr(destsatoshis)); - if ( metric < 1.2 && destsatoshis > desttxfee && destsatoshis-desttxfee > (autxo->payment.value / LP_MINCLIENTVOL) && satoshis-txfee > (butxo->S.satoshis / LP_MINVOL) && satoshis <= butxo->payment.value-txfee ) - { - printf("value %.8f price %.8f/%.8f best %.8f destsatoshis %.8f * metric %.8f -> (%f)\n",dstr(autxo->payment.value),price,bestprice,bestmetric,dstr(destsatoshis),metric,dstr(destsatoshis) * metric * metric * metric); - metric = dstr(destsatoshis) * metric * metric * metric; - if ( bestmetric == 0. || metric < bestmetric ) - { - bestutxo = butxo; - *ordermatchpricep = price; - *bestdestsatoshisp = destsatoshis; - *bestsatoshisp = satoshis; - bestmetric = metric; - printf("set best!\n"); - } - } // else printf("skip.(%d %d %d %d %d) metric %f destsatoshis %.8f value %.8f destvalue %.8f txfees %.8f %.8f sats %.8f\n",metric < 1.2,destsatoshis > desttxfee,destsatoshis-desttxfee > (autxo->payment.value / LP_MINCLIENTVOL),satoshis-txfee > (butxo->S.satoshis / LP_MINVOL),satoshis < butxo->payment.value-txfee,metric,dstr(destsatoshis),dstr(butxo->S.satoshis),dstr(autxo->payment.value),dstr(txfee),dstr(desttxfee),dstr(satoshis)); - } - else - { - printf("ineligible.(%.8f %.8f)\n",price,dstr(butxo->S.satoshis)); - //if ( butxo->T.spentflag == 0 ) - // butxo->T.spentflag = (uint32_t)time(NULL); - } - } - else - { - if ( butxo != 0 ) - printf("%llu %llu %d %d %d: ",(long long)(vol*SATOSHIDEN),(long long)butxo->S.satoshis,vol*SATOSHIDEN == butxo->S.satoshis,LP_isavailable(butxo) > 0,LP_ismine(butxo) == 0); - printf("cant find butxo.%p or value mismatch %.8f != %.8f or bestflag.%d\n",butxo,vol,butxo!=0?dstr(butxo->S.satoshis):0,butxo->T.bestflag); - } - } else printf("self trading or blacklisted peer\n"); - } - else - { - if ( i == 0 ) - printf("maxprice %.8f vs %.8f\n",maxprice,price); - break; - } - } - if ( bestutxo == 0 ) - { - int32_t numrestraints; - for (i=numrestraints=0; iT.bestflag = 0; - pubp->numerrors = 0; - } - } - } - printf("no bob utxo found -> cleared %d restraints\n",numrestraints); - } - } - free_json(orderbook); - } - free(obookstr); - } - if ( bestutxo == 0 || *ordermatchpricep == 0. || *bestdestsatoshisp == 0 ) - return(0); - bestutxo->T.bestflag = 1; - int32_t changed; - LP_mypriceset(&changed,autxo->coin,base,1. / *ordermatchpricep); - return(bestutxo); -} - char *LP_bestfit(char *rel,double relvolume) { struct LP_utxoinfo *autxo; @@ -707,35 +860,14 @@ char *LP_bestfit(char *rel,double relvolume) return(jprint(LP_utxojson(autxo),1)); } -char *LP_ordermatch(char *base,int64_t txfee,double maxprice,double maxvolume,char *rel,bits256 txid,int32_t vout,bits256 feetxid,int32_t feevout,int64_t desttxfee,int32_t duration) -{ - struct LP_quoteinfo Q; int64_t bestsatoshis=0,bestdestsatoshis = 0; double ordermatchprice = 0.; struct LP_utxoinfo *autxo,*bestutxo; - txfee = LP_txfeecalc(LP_coinfind(base),txfee); - desttxfee = LP_txfeecalc(LP_coinfind(rel),desttxfee); - if ( (autxo= LP_utxopairfind(0,txid,vout,feetxid,feevout)) == 0 ) - return(clonestr("{\"error\":\"cant find alice utxopair\"}")); - if ( (bestutxo= LP_bestutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,SATOSHIDEN*maxvolume)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) - return(clonestr("{\"error\":\"cant find ordermatch utxo\"}")); - if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestsatoshis,bestdestsatoshis) < 0 ) - return(clonestr("{\"error\":\"cant set ordermatch quote\"}")); - if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,LP_mypub25519,autxo->coinaddr) < 0 ) - return(clonestr("{\"error\":\"cant set ordermatch quote info\"}")); - return(jprint(LP_quotejson(&Q),1)); -} - char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp,double maxprice,int32_t timeout,int32_t duration) { - struct LP_utxoinfo *bobutxo,*aliceutxo; cJSON *bestitem=0; int32_t DEXselector=0; uint32_t expiration; double price; struct LP_pubkeyinfo *pubp; + struct LP_utxoinfo *aliceutxo; cJSON *bestitem=0; int32_t DEXselector=0; uint32_t expiration; double price; struct LP_pubkeyinfo *pubp; struct basilisk_swap *swap; if ( (aliceutxo= LP_utxopairfind(0,qp->desttxid,qp->destvout,qp->feetxid,qp->feevout)) == 0 ) { char str[65],str2[65]; printf("dest.(%s)/v%d fee.(%s)/v%d\n",bits256_str(str,qp->desttxid),qp->destvout,bits256_str(str2,qp->feetxid),qp->feevout); return(clonestr("{\"error\":\"cant find alice utxopair\"}")); } - if ( (bobutxo= LP_utxopairfind(1,qp->txid,qp->vout,qp->txid2,qp->vout2)) == 0 ) - return(clonestr("{\"error\":\"cant find bob utxopair\"}")); - bobutxo->T.bestflag = (uint32_t)time(NULL); - //if ( (retstr= LP_registerall(0)) != 0 ) - // free(retstr); price = LP_query(ctx,myipaddr,mypubsock,"request",qp); bestitem = LP_quotejson(qp); if ( LP_pricevalid(price) > 0 ) @@ -743,25 +875,29 @@ char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *q if ( price <= maxprice ) { price = LP_query(ctx,myipaddr,mypubsock,"connect",qp); - LP_requestinit(&qp->R,qp->srchash,qp->desthash,bobutxo->coin,qp->satoshis-qp->txfee,qp->destcoin,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector); + LP_requestinit(&qp->R,qp->srchash,qp->desthash,qp->srccoin,qp->satoshis-qp->txfee,qp->destcoin,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector); expiration = (uint32_t)time(NULL) + timeout; while ( time(NULL) < expiration ) { if ( aliceutxo->S.swap != 0 ) break; - sleep(1); + sleep(3); } - if ( aliceutxo->S.swap == 0 ) + jaddnum(bestitem,"quotedprice",price); + jaddnum(bestitem,"maxprice",maxprice); + if ( (swap= aliceutxo->S.swap) == 0 ) { - if ( (pubp= LP_pubkeyadd(bobutxo->pubkey)) != 0 ) + if ( (pubp= LP_pubkeyadd(qp->srchash)) != 0 ) pubp->numerrors++; jaddstr(bestitem,"status","couldnt establish connection"); - } else jaddstr(bestitem,"status","connected"); - jaddnum(bestitem,"quotedprice",price); - jaddnum(bestitem,"maxprice",maxprice); - jaddnum(bestitem,"requestid",qp->R.requestid); - jaddnum(bestitem,"quoteid",qp->R.quoteid); - printf("Alice r.%u qp->%u\n",qp->R.requestid,qp->R.quoteid); + } + else + { + jaddstr(bestitem,"status","connected"); + jaddnum(bestitem,"requestid",swap->I.req.requestid); + jaddnum(bestitem,"quoteid",swap->I.req.quoteid); + printf("Alice r.%u qp->%u\n",swap->I.req.requestid,swap->I.req.quoteid); + } } else { @@ -772,6 +908,7 @@ char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *q } else { + printf("invalid price %.8f\n",price); jaddnum(bestitem,"maxprice",maxprice); jaddstr(bestitem,"status","no response to request"); } @@ -780,36 +917,120 @@ char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *q return(jprint(bestitem,0)); } -char *LP_autotrade(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel,double maxprice,double relvolume,int32_t timeout,int32_t duration) +struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,int64_t *bestdestsatoshisp,struct LP_utxoinfo *autxo,char *base,double maxprice,int32_t duration,uint64_t txfee,uint64_t desttxfee,char *gui,bits256 *avoids,int32_t numavoids) +{ + bits256 pubkey; char *obookstr,coinaddr[64],str[65]; cJSON *orderbook,*asks,*item; int32_t i,j,n,numasks,max = 10000; struct LP_address_utxo **utxos; double price; struct LP_pubkeyinfo *pubp; struct iguana_info *basecoin; uint64_t basesatoshis; struct LP_utxoinfo *bestutxo = 0; + *ordermatchpricep = 0.; + *bestsatoshisp = *bestdestsatoshisp = 0; + basecoin = LP_coinfind(base); + if ( duration <= 0 ) + duration = LP_ORDERBOOK_DURATION; + if ( maxprice <= 0. || LP_priceinfofind(base) == 0 || basecoin == 0 ) + return(0); + utxos = calloc(max,sizeof(*utxos)); + LP_txfees(&txfee,&desttxfee,base,autxo->coin); + printf("LP_buyutxo maxprice %.8f relvol %.8f %s/%s %.8f %.8f\n",maxprice,dstr(autxo->S.satoshis),base,autxo->coin,dstr(txfee),dstr(desttxfee)); + if ( (obookstr= LP_orderbook(base,autxo->coin,duration)) != 0 ) + { + if ( (orderbook= cJSON_Parse(obookstr)) != 0 ) + { + if ( (asks= jarray(&numasks,orderbook,"asks")) != 0 ) + { + for (i=0; i 0 && price <= maxprice ) + { + for (j=0; jtaddr,basecoin->pubtype,pubp->rmd160,sizeof(pubp->rmd160)); + n = LP_listunspent_both(base,coinaddr); + //printf("unspent.(%s) n.%d\n",coinaddr,n); + if ( n > 1 ) + { + basesatoshis = LP_basesatoshis(dstr(autxo->S.satoshis),price,txfee,desttxfee); + if ( basesatoshis != 0 && (bestutxo= LP_address_utxopair(0,utxos,max,basecoin,coinaddr,txfee,dstr(basesatoshis)*price,price,desttxfee)) != 0 ) + { + bestutxo->pubkey = pubp->pubkey; + safecopy(bestutxo->gui,gui,sizeof(bestutxo->gui)); + *bestsatoshisp = basesatoshis; + *ordermatchpricep = price; + *bestdestsatoshisp = autxo->S.satoshis; + printf("ordermatch %.8f %.8f %.8f txfees (%.8f %.8f)\n",price,dstr(*bestsatoshisp),dstr(*bestdestsatoshisp),dstr(txfee),dstr(desttxfee)); + break; + } + } else printf("no unspents %s %s %s\n",base,coinaddr,bits256_str(str,pubkey)); + } else printf("self trading or blacklisted peer\n"); + } + else + { + if ( i == 0 ) + printf("too expensive maxprice %.8f vs %.8f\n",maxprice,price); + break; + } + } + } + free_json(orderbook); + } + free(obookstr); + } + free(utxos); + if ( *ordermatchpricep == 0. || *bestdestsatoshisp == 0 ) + return(0); + int32_t changed; + LP_mypriceset(&changed,autxo->coin,base,1. / *ordermatchpricep); + return(bestutxo); +} + +char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel,double maxprice,double relvolume,int32_t timeout,int32_t duration,char *gui) { - uint64_t desttxfee,txfee; int64_t bestsatoshis=0,bestdestsatoshis=0; struct LP_utxoinfo *autxo,*butxo,*bestutxo = 0; double qprice,ordermatchprice=0.; struct LP_quoteinfo Q; + uint64_t desttxfee,txfee; int32_t numpubs = 0; int64_t bestsatoshis=0,destsatoshis,bestdestsatoshis=0; struct LP_utxoinfo *autxo,*bestutxo = 0; double qprice,ordermatchprice=0.; struct LP_quoteinfo Q; bits256 pubkeys[100]; + printf("LP_autobuy %s/%s price %.8f vol %.8f\n",base,rel,maxprice,relvolume); if ( duration <= 0 ) duration = LP_ORDERBOOK_DURATION; if ( timeout <= 0 ) timeout = LP_AUTOTRADE_TIMEOUT; if ( maxprice <= 0. || relvolume <= 0. || LP_priceinfofind(base) == 0 || LP_priceinfofind(rel) == 0 ) return(clonestr("{\"error\":\"invalid parameter\"}")); - if ( (autxo= LP_utxo_bestfit(rel,SATOSHIDEN * relvolume)) == 0 ) - return(clonestr("{\"error\":\"cant find utxo that is big enough\"}")); + if ( strcmp("BTC",rel) == 0 ) + maxprice *= 1.01; + else maxprice *= 1.001; + memset(pubkeys,0,sizeof(pubkeys)); LP_txfees(&txfee,&desttxfee,base,rel); - if ( (bestutxo= LP_bestutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,SATOSHIDEN*relvolume)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) - { - printf("bestutxo.%p ordermatchprice %.8f bestdestsatoshis %.8f\n",bestutxo,ordermatchprice,dstr(bestdestsatoshis)); - return(clonestr("{\"error\":\"cant find ordermatch utxo\"}")); - } - if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestsatoshis,bestdestsatoshis) < 0 ) - return(clonestr("{\"error\":\"cant set ordermatch quote\"}")); - if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,LP_mypub25519,autxo->coinaddr) < 0 ) - return(clonestr("{\"error\":\"cant set ordermatch quote info\"}")); - if ( (qprice= LP_quote_validate(&autxo,&butxo,&Q,0)) <= SMALLVAL ) + destsatoshis = SATOSHIDEN * relvolume + 2*desttxfee; + if ( (autxo= LP_utxo_bestfit(rel,destsatoshis)) == 0 ) + return(clonestr("{\"error\":\"cant find utxo that is big enough\"}")); + if ( destsatoshis < autxo->S.satoshis ) + autxo->S.satoshis = destsatoshis; + while ( 1 ) { - printf("quote validate error %.0f\n",qprice); - return(clonestr("{\"error\":\"quote validation error\"}")); + if ( (bestutxo= LP_buyutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,gui,pubkeys,numpubs)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) + { + printf("bestutxo.%p ordermatchprice %.8f bestdestsatoshis %.8f\n",bestutxo,ordermatchprice,dstr(bestdestsatoshis)); + return(clonestr("{\"error\":\"cant find ordermatch utxo\"}")); + } + pubkeys[numpubs++] = bestutxo->pubkey; + if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestsatoshis,bestdestsatoshis) < 0 ) + return(clonestr("{\"error\":\"cant set ordermatch quote\"}")); + if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,G.LP_mypub25519,autxo->coinaddr) < 0 ) + return(clonestr("{\"error\":\"cant set ordermatch quote info\"}")); + if ( (qprice= LP_quote_validate(autxo,0,&Q,0)) <= SMALLVAL ) + { + printf("continue searching, quote validate error %.0f\n",qprice); + continue; + } + break; } - printf("do quote.(%s)\n",jprint(LP_quotejson(&Q),1)); + //printf("do quote.(%s)\n",jprint(LP_quotejson(&Q),1)); return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration)); } - - diff --git a/iguana/exchanges/LP_peers.c b/iguana/exchanges/LP_peers.c index 806572415..5c7efb7e7 100644 --- a/iguana/exchanges/LP_peers.c +++ b/iguana/exchanges/LP_peers.c @@ -35,9 +35,9 @@ cJSON *LP_peerjson(struct LP_peerinfo *peer) jaddnum(item,"port",peer->port); if ( strcmp(peer->ipaddr,LP_myipaddr) == 0 ) { - jaddnum(item,"session",LP_sessionid); - if ( LP_mypeer != 0 ) - jaddnum(item,"numutxos",LP_mypeer->numutxos); + jaddnum(item,"session",G.LP_sessionid); + //if ( LP_mypeer != 0 ) + // jaddnum(item,"numutxos",LP_mypeer->numutxos); } else jaddnum(item,"session",peer->sessionid); //jaddnum(item,"profit",peer->profitmargin); return(item); @@ -58,8 +58,6 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char { uint32_t ipbits; int32_t pushsock,subsock,timeout; char checkip[64],pushaddr[64],subaddr[64]; struct LP_peerinfo *peer = 0; printf("addpeer (%s:%u)\n",ipaddr,port); - if ( port > 10000 ) - return(0); #ifdef LP_STRICTPEERS if ( strncmp("5.9.253",ipaddr,strlen("5.9.253")) != 0 ) return(0); @@ -81,7 +79,7 @@ struct LP_peerinfo *LP_addpeer(struct LP_peerinfo *mypeer,int32_t mypubsock,char { peer = calloc(1,sizeof(*peer)); if ( strcmp(peer->ipaddr,LP_myipaddr) == 0 ) - peer->sessionid = LP_sessionid; + peer->sessionid = G.LP_sessionid; else peer->sessionid = sessionid; peer->pushsock = peer->subsock = pushsock = subsock = -1; strcpy(peer->ipaddr,ipaddr); @@ -219,9 +217,9 @@ int32_t LP_peersparse(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipa void LP_peersquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *myipaddr,uint16_t myport) { - char *retstr; struct LP_peerinfo *peer,*tmp; uint32_t now,flag = 0; + char *retstr; struct LP_peerinfo *peer,*tmp; bits256 zero; uint32_t now,flag = 0; peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); - if ( (retstr= issue_LP_getpeers(destipaddr,destport,myipaddr,myport,mypeer!=0?mypeer->numpeers:0,mypeer!=0?mypeer->numutxos:0)) != 0 ) + if ( (retstr= issue_LP_getpeers(destipaddr,destport,myipaddr,myport,mypeer!=0?mypeer->numpeers:0)) != 0 ) { //printf("got.(%s)\n",retstr); now = (uint32_t)time(NULL); @@ -235,7 +233,8 @@ void LP_peersquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr { printf("{%s:%u}.%d ",peer->ipaddr,peer->port,peer->lasttime - now); flag++; - if ( (retstr= issue_LP_notify(destipaddr,destport,peer->ipaddr,peer->port,peer->numpeers,0,peer->sessionid)) != 0 ) + memset(&zero,0,sizeof(zero)); + if ( (retstr= issue_LP_notify(destipaddr,destport,peer->ipaddr,peer->port,peer->numpeers,peer->sessionid,0,zero)) != 0 ) free(retstr); } } @@ -254,3 +253,27 @@ int32_t LP_numpeers() } return(numpeers); } + +uint16_t LP_randpeer(char *destip) +{ + struct LP_peerinfo *peer,*tmp; uint16_t port = 0; int32_t n,r,numpeers = 0; + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + numpeers++; + } + if ( numpeers > 0 ) + { + r = rand() % numpeers; + n = 0; + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + if ( n++ == r ) + { + strcpy(destip,peer->ipaddr); + port = peer->port; + break; + } + } + } + return(port); +} diff --git a/iguana/exchanges/LP_portfolio.c b/iguana/exchanges/LP_portfolio.c index a3e656e70..80ce16c7b 100644 --- a/iguana/exchanges/LP_portfolio.c +++ b/iguana/exchanges/LP_portfolio.c @@ -57,13 +57,13 @@ uint64_t LP_balance(uint64_t *valuep,int32_t iambob,char *symbol,char *coinaddr) for (i=0; i 0 && is_cJSON_Array(array) != 0 ) { @@ -89,11 +89,11 @@ char *LP_portfolio() { HASH_ITER(hh,LP_coins,coin,tmp) { - if ( coin->inactive != 0 ) + if ( coin->inactive != 0 )//|| (coin->electrum != 0 && coin->obooktime == 0) ) continue; if ( iter == 0 ) { - LP_privkey_init(-1,coin,LP_mypriv25519,LP_mypub25519); + LP_privkey_init(-1,coin,G.LP_mypriv25519,G.LP_mypub25519); coin->balanceA = LP_balance(&coin->valuesumA,0,coin->symbol,coin->smartaddr); coin->balanceB = LP_balance(&coin->valuesumB,1,coin->symbol,coin->smartaddr); if ( strcmp(coin->symbol,"KMD") != 0 ) @@ -184,12 +184,16 @@ char *LP_portfolio_goal(char *symbol,double goal) coin->goal = kmdbtc * 0.5; if ( (coin= LP_coinfind("BTC")) != 0 && coin->inactive == 0 ) coin->goal = kmdbtc * 0.5; + if ( coin->goal != 0 ) + coin->obooktime = (uint32_t)time(NULL); return(LP_portfolio()); } else if ( (coin= LP_coinfind(symbol)) != 0 && coin->inactive == 0 ) { coin->goal = goal; printf("set %s goal %f\n",coin->symbol,goal); + if ( coin->goal != 0 ) + coin->obooktime = (uint32_t)time(NULL); return(LP_portfolio()); } else return(clonestr("{\"error\":\"cant set goal for inactive coin\"}")); } @@ -415,7 +419,7 @@ void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp) } } -int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,struct iguana_info *buy,struct iguana_info *sell,double relvolume,int32_t setbaserel) +int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,struct iguana_info *buy,struct iguana_info *sell,double relvolume,int32_t setbaserel,char *gui) { char *retstr2; double bid,ask,maxprice; uint32_t requestid,quoteid,iter,i; cJSON *retjson2; requestid = quoteid = 0; @@ -427,7 +431,7 @@ int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,str strcpy(LP_portfolio_rel,""); LP_portfolio_relvolume = 0.; } - printf("pending.%d base buy.%s, rel sell.%s relvolume %f maxprice %.8f (%.8f %.8f)\n",LP_pendingswaps,buy->symbol,sell->symbol,sell->relvolume,maxprice,bid,ask); + printf("pending.%d base buy.%s, rel sell.%s relvolume %f maxprice %.8f (%.8f %.8f)\n",G.LP_pendingswaps,buy->symbol,sell->symbol,sell->relvolume,maxprice,bid,ask); if ( LP_pricevalid(maxprice) > 0 ) { relvolume = sell->relvolume; @@ -437,7 +441,7 @@ int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,str break; if ( LP_utxo_bestfit(sell->symbol,SATOSHIDEN * relvolume) != 0 ) { - if ( (retstr2= LP_autotrade(ctx,"127.0.0.1",-1,buy->symbol,sell->symbol,maxprice,relvolume,60,24*3600)) != 0 ) + if ( (retstr2= LP_autobuy(ctx,"127.0.0.1",-1,buy->symbol,sell->symbol,maxprice,relvolume,60,24*3600,gui)) != 0 ) { if ( (retjson2= cJSON_Parse(retstr2)) != 0 ) { @@ -546,7 +550,7 @@ void prices_loop(void *ignore) { if ( (buycoin= jstr(retjson,"buycoin")) != 0 && (buy= LP_coinfind(buycoin)) != 0 && (sellcoin= jstr(retjson,"sellcoin")) != 0 && (sell= LP_coinfind(sellcoin)) != 0 && buy->inactive == 0 && sell->inactive == 0 ) { - if ( LP_portfolio_trade(ctx,&requestid,"eid,buy,sell,sell->relvolume,1) < 0 ) + if ( LP_portfolio_trade(ctx,&requestid,"eid,buy,sell,sell->relvolume,1,"portfolio") < 0 ) { array = jarray(&m,retjson,"portfolio"); if ( array != 0 && (n= LP_portfolio_order(trades,(int32_t)(sizeof(trades)/sizeof(*trades)),array)) > 0 ) @@ -557,7 +561,7 @@ void prices_loop(void *ignore) { buy = LP_coinfind(trades[i].buycoin); sell = LP_coinfind(trades[i].sellcoin); - if ( buy != 0 && sell != 0 && LP_portfolio_trade(ctx,&requestid,"eid,buy,sell,sell->relvolume,0) == 0 ) + if ( buy != 0 && sell != 0 && LP_portfolio_trade(ctx,&requestid,"eid,buy,sell,sell->relvolume,0,"portfolio") == 0 ) break; } } diff --git a/iguana/exchanges/LP_prices.c b/iguana/exchanges/LP_prices.c index d78570f97..723585bfb 100644 --- a/iguana/exchanges/LP_prices.c +++ b/iguana/exchanges/LP_prices.c @@ -18,7 +18,7 @@ // marketmaker // -struct LP_orderbookentry { bits256 txid,txid2,pubkey; double price; uint64_t basesatoshis; int32_t vout,vout2,age; }; +struct LP_orderbookentry { bits256 pubkey; double price; uint64_t minsatoshis,maxsatoshis; uint32_t timestamp; int32_t numutxos; char coinaddr[64]; }; #define LP_MAXPRICEINFOS 256 struct LP_priceinfo @@ -52,73 +52,9 @@ struct LP_pubkeyinfo bits256 pubkey; double matrix[LP_MAXPRICEINFOS][LP_MAXPRICEINFOS]; uint32_t timestamp,istrusted,numerrors; - uint8_t rmd160[20]; + uint8_t rmd160[20],pubsecp[33]; } *LP_pubkeyinfos; - -struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr) -{ - struct LP_address *ap; - HASH_FIND(hh,coin->addresses,coinaddr,strlen(coinaddr),ap); - return(ap); -} - -struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr) -{ - struct LP_address *ap; - ap = calloc(1,sizeof(*ap)); - safecopy(ap->coinaddr,coinaddr,sizeof(ap->coinaddr)); - HASH_ADD_KEYPTR(hh,coin->addresses,ap->coinaddr,strlen(ap->coinaddr),ap); - return(ap); -} - -struct LP_address *_LP_address(struct iguana_info *coin,char *coinaddr) -{ - struct LP_address *ap; - if ( (ap= _LP_addressfind(coin,coinaddr)) == 0 ) - ap = _LP_addressadd(coin,coinaddr); - return(ap); -} - -/*void LP_address_utxoadd(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value) -{ - struct LP_address *ap; struct LP_address_utxo *up; - portable_mutex_lock(&coin->txmutex); - if ( (ap= _LP_address(coin,coinaddr)) != 0 ) - { - up = calloc(1,sizeof(*up)); - up->U.txid = txid; - up->U.vout = vout; - up->U.value = value; - DL_APPEND(ap->utxos,up); - } - portable_mutex_unlock(&coin->txmutex); -} - -void LP_address_monitor(struct LP_pubkeyinfo *pubp) -{ - struct iguana_info *coin,*tmp; char coinaddr[64]; cJSON *retjson; struct LP_address *ap; - return; - HASH_ITER(hh,LP_coins,coin,tmp) - { - bitcoin_address(coinaddr,coin->taddr,coin->pubtype,pubp->rmd160,sizeof(pubp->rmd160)); - portable_mutex_lock(&coin->txmutex); - if ( (ap= _LP_address(coin,coinaddr)) != 0 ) - { - ap->monitor = (uint32_t)time(NULL); - } - portable_mutex_unlock(&coin->txmutex); - if ( coin->electrum != 0 ) - { - if ( (retjson= electrum_address_subscribe(coin->symbol,coin->electrum,&retjson,coinaddr)) != 0 ) - { - printf("%s MONITOR.(%s) -> %s\n",coin->symbol,coinaddr,jprint(retjson,0)); - free_json(retjson); - } - } - } -}*/ - int32_t LP_pricevalid(double price) { if ( price > SMALLVAL && isnan(price) == 0 && price < SATOSHIDEN ) @@ -190,6 +126,52 @@ struct LP_cacheinfo *LP_cachefind(char *base,char *rel,bits256 txid,int32_t vout return(ptr); } +struct LP_pubkeyinfo *LP_pubkey_rmd160find(uint8_t rmd160[20]) +{ + struct LP_pubkeyinfo *pubp=0,*tmp; + portable_mutex_lock(&LP_pubkeymutex); + HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) + { + if ( memcmp(rmd160,pubp->rmd160,sizeof(pubp->rmd160)) == 0 ) + break; + pubp = 0; + } + portable_mutex_unlock(&LP_pubkeymutex); + return(pubp); +} + +struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr) +{ + uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkeyinfo *pubp; + HASH_FIND(hh,coin->addresses,coinaddr,strlen(coinaddr),ap); + if ( ap != 0 && bits256_nonz(ap->pubkey) == 0 ) + { + bitcoin_addr2rmd160(coin->taddr,&addrtype,rmd160,coinaddr); + if ( (pubp= LP_pubkey_rmd160find(rmd160)) != 0 ) + { + ap->pubkey = pubp->pubkey; + memcpy(ap->pubsecp,pubp->pubsecp,sizeof(ap->pubsecp)); + } + } + return(ap); +} + +struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr) +{ + uint8_t rmd160[20],addrtype; struct LP_address *ap; struct LP_pubkeyinfo *pubp; + ap = calloc(1,sizeof(*ap)); + safecopy(ap->coinaddr,coinaddr,sizeof(ap->coinaddr)); + bitcoin_addr2rmd160(coin->taddr,&addrtype,rmd160,coinaddr); + if ( (pubp= LP_pubkey_rmd160find(rmd160)) != 0 ) + { + ap->pubkey = pubp->pubkey; + memcpy(ap->pubsecp,pubp->pubsecp,sizeof(ap->pubsecp)); + } + //printf("LP_ADDRESS %s ADD.(%s)\n",coin->symbol,coinaddr); + HASH_ADD_KEYPTR(hh,coin->addresses,ap->coinaddr,strlen(ap->coinaddr),ap); + return(ap); +} + struct LP_pubkeyinfo *LP_pubkeyfind(bits256 pubkey) { struct LP_pubkeyinfo *pubp=0; @@ -207,8 +189,11 @@ struct LP_pubkeyinfo *LP_pubkeyadd(bits256 pubkey) portable_mutex_lock(&LP_pubkeymutex); pubp = calloc(1,sizeof(*pubp)); pubp->pubkey = pubkey; - if ( bits256_cmp(LP_mypub25519,pubkey) == 0 ) - memcpy(pubp->rmd160,LP_myrmd160,sizeof(pubp->rmd160)); + if ( bits256_cmp(G.LP_mypub25519,pubkey) == 0 ) + { + memcpy(pubp->rmd160,G.LP_myrmd160,sizeof(pubp->rmd160)); + memcpy(pubp->pubsecp,G.LP_pubsecp,sizeof(pubp->pubsecp)); + } HASH_ADD_KEYPTR(hh,LP_pubkeyinfos,&pubp->pubkey,sizeof(pubp->pubkey),pubp); portable_mutex_unlock(&LP_pubkeymutex); if ( (pubp= LP_pubkeyfind(pubkey)) == 0 ) @@ -236,9 +221,29 @@ char *LP_pubkey_trustset(bits256 pubkey,uint32_t trustval) return(clonestr("{\"error\":\"pubkey not found\"}")); } +uint64_t LP_unspents_metric(struct iguana_info *coin,char *coinaddr) +{ + cJSON *array,*item; int32_t i,n; uint64_t metric=0,total; + LP_listunspent_both(coin->symbol,coinaddr); + if ( (array= LP_address_utxos(coin,coinaddr,1)) != 0 ) + { + total = 0; + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; ipubkey); - init_hexbytes_noT(hexstr,pubp->rmd160,sizeof(pubp->rmd160)); - jaddstr(obj,"rmd160",hexstr); + for (i=0; irmd160); i++) + { + if ( pubp->rmd160[i] != 0 ) + { + init_hexbytes_noT(hexstr,pubp->rmd160,sizeof(pubp->rmd160)); + jaddstr(obj,"rmd160",hexstr); + for (j=0; ipubsecp); i++) + { + if ( pubp->pubsecp[i] != 0 ) + { + init_hexbytes_noT(hexstr2,pubp->pubsecp,sizeof(pubp->pubsecp)); + jaddstr(obj,"pubsecp",hexstr2); + //printf("nonz rmd160 (%s %s)\n",hexstr,hexstr2); + break; + } + } + break; + } + } jaddnum(obj,"timestamp",pubp->timestamp); jadd(obj,"asks",array); if ( pubp->istrusted != 0 ) @@ -277,26 +299,38 @@ char *LP_prices() return(jprint(array,1)); } -void LP_prices_parse(cJSON *obj) +void LP_prices_parse(struct LP_peerinfo *peer,cJSON *obj) { static uint8_t zeroes[20]; - struct LP_pubkeyinfo *pubp; struct LP_priceinfo *basepp,*relpp; uint32_t timestamp; bits256 pubkey; cJSON *asks,*item; uint8_t rmd160[20]; int32_t i,n,relid; char *base,*rel,*hexstr; double askprice; + struct LP_pubkeyinfo *pubp; struct LP_priceinfo *basepp,*relpp; uint32_t timestamp; bits256 pubkey; cJSON *asks,*item; uint8_t rmd160[20]; int32_t i,n,relid,mismatch; char *base,*rel,*hexstr,*pubsecpstr; double askprice; uint32_t now; + now = (uint32_t)time(NULL); pubkey = jbits256(obj,"pubkey"); if ( bits256_nonz(pubkey) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 ) { if ( (hexstr= jstr(obj,"rmd160")) != 0 && strlen(hexstr) == 2*sizeof(rmd160) ) { decode_hex(rmd160,sizeof(rmd160),hexstr); - if ( memcmp(zeroes,rmd160,sizeof(rmd160)) != 0 && memcmp(pubp->rmd160,rmd160,sizeof(rmd160)) != 0 ) + if ( memcmp(pubp->rmd160,rmd160,sizeof(rmd160)) != 0 ) + mismatch = 1; + else mismatch = 0; + if ( bits256_cmp(pubkey,G.LP_mypub25519) == 0 && mismatch == 0 ) + peer->needping = 0; + if ( mismatch != 0 && memcmp(zeroes,rmd160,sizeof(rmd160)) != 0 ) { for (i=0; i<20; i++) printf("%02x",pubp->rmd160[i]); - char str[65]; printf(" -> rmd160.(%s) for %s\n",hexstr,bits256_str(str,pubkey)); memcpy(pubp->rmd160,rmd160,sizeof(pubp->rmd160)); - //LP_address_monitor(pubp); + if ( (pubsecpstr= jstr(obj,"pubsecp")) != 0 && is_hexstr(pubsecpstr,0) == 66 ) + { + decode_hex(pubp->pubsecp,sizeof(pubp->pubsecp),pubsecpstr); + char str[65]; printf(" -> rmd160.(%s) for %s (%s)\n",hexstr,bits256_str(str,pubkey),pubsecpstr); + } } } - if ( (timestamp= juint(obj,"timestamp")) > pubp->timestamp && (asks= jarray(&n,obj,"asks")) != 0 ) + timestamp = juint(obj,"timestamp"); + if ( timestamp > now ) + timestamp = now; + if ( timestamp > pubp->timestamp && (asks= jarray(&n,obj,"asks")) != 0 ) { pubp->timestamp = timestamp; for (i=0; iind,relid,askprice); + //char str[65]; printf("gotprice %s %s/%s (%d/%d) %.8f\n",bits256_str(str,pubkey),base,rel,basepp->ind,relid,askprice); pubp->matrix[basepp->ind][relid] = askprice; if ( (relpp= LP_priceinfofind(rel)) != 0 ) { @@ -323,22 +357,27 @@ void LP_prices_parse(cJSON *obj) } } -void LP_peer_pricesquery(char *destipaddr,uint16_t destport) +void LP_peer_pricesquery(struct LP_peerinfo *peer) { char *retstr; cJSON *array; int32_t i,n; - if ( (retstr= issue_LP_getprices(destipaddr,destport)) != 0 ) + peer->needping = (uint32_t)time(NULL); + if ( (retstr= issue_LP_getprices(peer->ipaddr,peer->port)) != 0 ) { if ( (array= cJSON_Parse(retstr)) != 0 ) { if ( is_cJSON_Array(array) && (n= cJSON_GetArraySize(array)) > 0 ) { for (i=0; ineedping != 0 ) + { + //printf("%s needs ping\n",peer->ipaddr); + } } double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,int32_t vout) @@ -353,9 +392,9 @@ double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,i ptr->price = (double)ptr->Q.destsatoshis / ptr->Q.satoshis; if ( LP_pricevalid(ptr->price) <= 0 ) ptr->price = 0.; - //printf("LP_pricecache: set %s/%s ptr->price %.8f\n",base,rel,ptr->price); + printf("LP_pricecache: set %s/%s ptr->price %.8f\n",base,rel,ptr->price); } - //printf("found %s/%s %.8f\n",base,rel,ptr->price); + printf(">>>>>>>>>> found %s/%s %.8f\n",base,rel,ptr->price); return(ptr->price); } //char str[65]; printf("cachemiss %s/%s %s/v%d\n",base,rel,bits256_str(str,txid),vout); @@ -447,7 +486,7 @@ int32_t LP_mypriceset(int32_t *changedp,char *base,char *rel,double price) basepp->myprices[relpp->ind] = price; // ask //printf("LP_mypriceset base.%s rel.%s <- price %.8f\n",base,rel,price); //relpp->myprices[basepp->ind] = (1. / price); // bid - if ( (pubp= LP_pubkeyadd(LP_mypub25519)) != 0 ) + if ( (pubp= LP_pubkeyadd(G.LP_mypub25519)) != 0 ) { pubp->matrix[basepp->ind][relpp->ind] = price; //pubp->matrix[relpp->ind][basepp->ind] = (1. / price); @@ -577,101 +616,129 @@ static int _cmp_orderbook(const void *a,const void *b) { #undef ptr_a #undef ptr_b -#define ptr_a ((struct LP_orderbookentry *)a)->basesatoshis -#define ptr_b ((struct LP_orderbookentry *)b)->basesatoshis +#define ptr_a ((struct LP_orderbookentry *)a)->maxsatoshis +#define ptr_b ((struct LP_orderbookentry *)b)->maxsatoshis if ( ptr_b > ptr_a ) return(-1); else if ( ptr_b < ptr_a ) return(1); } - // printf("%.8f vs %.8f -> %d\n",ptr_a,ptr_b,retval); + // printf("%.8f vs %.8f -> %d\n",ptr_a,ptr_b,retval); return(retval); #undef ptr_a #undef ptr_b } -cJSON *LP_orderbookjson(struct LP_orderbookentry *op) +static int _revcmp_orderbook(const void *a,const void *b) +{ + int32_t retval = 0; +#define ptr_a (*(struct LP_orderbookentry **)a)->price +#define ptr_b (*(struct LP_orderbookentry **)b)->price + if ( ptr_b > ptr_a ) + retval = 1; + else if ( ptr_b < ptr_a ) + retval = -1; + else + { +#undef ptr_a +#undef ptr_b +#define ptr_a ((struct LP_orderbookentry *)a)->maxsatoshis +#define ptr_b ((struct LP_orderbookentry *)b)->maxsatoshis + if ( ptr_b > ptr_a ) + return(-1); + else if ( ptr_b < ptr_a ) + return(1); + } + // printf("%.8f vs %.8f -> %d\n",ptr_a,ptr_b,retval); + return(retval); +#undef ptr_a +#undef ptr_b +} + +cJSON *LP_orderbookjson(char *symbol,struct LP_orderbookentry *op) { cJSON *item = cJSON_CreateObject(); if ( LP_pricevalid(op->price) > 0 ) { + jaddstr(item,"coin",symbol); + jaddstr(item,"address",op->coinaddr); jaddnum(item,"price",op->price); - jaddnum(item,"volume",dstr(op->basesatoshis)); - jaddbits256(item,"txid",op->txid); - jaddnum(item,"vout",op->vout); + jaddnum(item,"numutxos",op->numutxos); + jaddnum(item,"minvolume",dstr(op->minsatoshis)); + jaddnum(item,"maxvolume",dstr(op->maxsatoshis)); jaddbits256(item,"pubkey",op->pubkey); - jaddnum(item,"age",op->age); + jaddnum(item,"age",time(NULL)-op->timestamp); } return(item); } -struct LP_orderbookentry *LP_orderbookentry(char *base,char *rel,bits256 txid,int32_t vout,bits256 txid2,int32_t vout2,double price,uint64_t basesatoshis,bits256 pubkey,int32_t age) +struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,double price,int32_t numutxos,uint64_t minsatoshis,uint64_t maxsatoshis,bits256 pubkey,uint32_t timestamp) { struct LP_orderbookentry *op; if ( (op= calloc(1,sizeof(*op))) != 0 ) { - op->txid = txid; - op->vout = vout; - op->txid2 = txid2; - op->vout2 = vout2; + safecopy(op->coinaddr,address,sizeof(op->coinaddr)); op->price = price; - op->basesatoshis = basesatoshis; + op->numutxos = numutxos; + op->minsatoshis = minsatoshis; + op->maxsatoshis = maxsatoshis; op->pubkey = pubkey; - op->age = age; + op->timestamp = timestamp; } return(op); } -int32_t LP_orderbookfind(struct LP_orderbookentry **array,int32_t num,bits256 txid,int32_t vout) -{ - int32_t i; - for (i=0; ivout == vout && bits256_cmp(array[i]->txid,txid) == 0) || (array[i]->vout2 == vout && bits256_cmp(array[i]->txid2,txid) == 0) ) - return(i); - return(-1); -} - int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *rel,struct LP_orderbookentry *(**arrayp),int32_t num,int32_t cachednum,int32_t duration) { - struct LP_utxoinfo *utxo,*tmp; struct LP_pubkeyinfo *pubp=0; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; uint32_t oldest; double price; int32_t baseid,relid; uint64_t basesatoshis,val,val2; + char coinaddr[64]; uint8_t zeroes[20]; struct LP_pubkeyinfo *pubp=0,*tmp; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; struct LP_address *ap; struct iguana_info *basecoin; uint32_t oldest; double price; int32_t baseid,relid,n; uint64_t minsatoshis,maxsatoshis; if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 ) baseid = basepp->ind; else return(num); + if ( (basecoin= LP_coinfind(base)) == 0 ) + return(-1); now = (uint32_t)time(NULL); oldest = now - duration; - HASH_ITER(hh,LP_utxoinfos[1],utxo,tmp) + memset(zeroes,0,sizeof(zeroes)); + HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) { - if ( pubp == 0 || bits256_cmp(pubp->pubkey,utxo->pubkey) != 0 ) - pubp = LP_pubkeyfind(utxo->pubkey); - if ( pubp != 0 && pubp->numerrors >= LP_MAXPUBKEY_ERRORS ) + if ( memcmp(zeroes,pubp->rmd160,sizeof(pubp->rmd160)) == 0 ) + { + //printf("skip pubp since no rmd160\n"); continue; - //char str[65],str2[65]; printf("check utxo.%s/v%d from %s\n",bits256_str(str,utxo->payment.txid),utxo->payment.vout,bits256_str(str2,utxo->pubkey)); - if ( strcmp(base,utxo->coin) == 0 && LP_isavailable(utxo) > 0 && pubp != 0 && (price= pubp->matrix[baseid][relid]) > SMALLVAL && pubp->timestamp > oldest && pubp->timestamp <= now ) + } + bitcoin_address(coinaddr,basecoin->taddr,basecoin->pubtype,pubp->rmd160,sizeof(pubp->rmd160)); + minsatoshis = maxsatoshis = n = 0; + ap = 0; + if ( (price= pubp->matrix[baseid][relid]) > SMALLVAL ) { - if ( LP_orderbookfind(*arrayp,cachednum,utxo->payment.txid,utxo->payment.vout) < 0 ) + if ( (ap= LP_addressfind(basecoin,coinaddr)) != 0 ) { - if ( LP_iseligible(&val,&val2,utxo->iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,utxo->deposit.txid,utxo->deposit.vout) == 0 ) - continue; + n = LP_address_minmax(&minsatoshis,&maxsatoshis,ap); if ( polarity > 0 ) - basesatoshis = utxo->S.satoshis; - else basesatoshis = utxo->S.satoshis * price; - //char str[65]; printf("found utxo not in orderbook %s/v%d %.8f %.8f\n",bits256_str(str,utxo->payment.txid),utxo->payment.vout,dstr(basesatoshis),polarity > 0 ? price : 1./price); - if ( (op= LP_orderbookentry(base,rel,utxo->payment.txid,utxo->payment.vout,utxo->deposit.txid,utxo->deposit.vout,polarity > 0 ? price : 1./price,basesatoshis,utxo->pubkey,now - pubp->timestamp)) != 0 ) { - *arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1)); - (*arrayp)[num++] = op; - if ( LP_ismine(utxo) > 0 && utxo->T.lasttime == 0 ) - LP_utxo_clientpublish(utxo); + minsatoshis *= price; + maxsatoshis *= price; } + //printf("%s/%s %s n.%d ap->n.%d %.8f\n",base,rel,coinaddr,n,ap->n,dstr(ap->total)); + } + if ( (op= LP_orderbookentry(coinaddr,base,rel,polarity > 0 ? price : 1./price,n,minsatoshis,maxsatoshis,pubp->pubkey,pubp->timestamp)) != 0 ) + { + *arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1)); + (*arrayp)[num++] = op; } } + //printf("pubp.(%s) %.8f %p\n",coinaddr,price,ap); } return(num); } char *LP_orderbook(char *base,char *rel,int32_t duration) { - uint32_t now,i; struct LP_priceinfo *basepp=0,*relpp=0; struct LP_orderbookentry **bids = 0,**asks = 0; cJSON *retjson,*array; int32_t numbids=0,numasks=0,cachenumbids,cachenumasks,baseid,relid; + uint32_t now,i; struct LP_priceinfo *basepp=0,*relpp=0; struct LP_orderbookentry **bids = 0,**asks = 0; cJSON *retjson,*array; struct iguana_info *basecoin,*relcoin; int32_t n,numbids=0,numasks=0,cachenumbids,cachenumasks,baseid,relid; + basecoin = LP_coinfind(base); + relcoin = LP_coinfind(rel); + if ( basecoin == 0 || relcoin == 0 ) + return(clonestr("{\"error\":\"base or rel not added\"}")); if ( (basepp= LP_priceinfofind(base)) == 0 || (relpp= LP_priceinfofind(rel)) == 0 ) return(clonestr("{\"error\":\"base or rel not added\"}")); if ( duration <= 0 ) @@ -679,6 +746,8 @@ char *LP_orderbook(char *base,char *rel,int32_t duration) baseid = basepp->ind; relid = relpp->ind; now = (uint32_t)time(NULL); + basecoin->obooktime = now; + relcoin->obooktime = now; cachenumbids = numbids, cachenumasks = numasks; //printf("start cache.(%d %d) numbids.%d numasks.%d\n",cachenumbids,cachenumasks,numbids,numasks); numasks = LP_orderbook_utxoentries(now,1,base,rel,&asks,numasks,cachenumasks,duration); @@ -686,7 +755,7 @@ char *LP_orderbook(char *base,char *rel,int32_t duration) retjson = cJSON_CreateObject(); array = cJSON_CreateArray(); if ( numbids > 1 ) - qsort(bids,numbids,sizeof(*bids),_cmp_orderbook); + qsort(bids,numbids,sizeof(*bids),_revcmp_orderbook); if ( numasks > 1 ) { //for (i=0; iprice); //printf("sorted asks.%d\n",numasks); } - for (i=0; inumutxos == 0 )//|| relcoin->electrum == 0 ) + LP_address(relcoin,bids[i]->coinaddr), n++; free(bids[i]); bids[i] = 0; } + if ( n > 0 && relcoin->lastmonitor > 3600 ) + relcoin->lastmonitor -= 3600; jadd(retjson,"bids",array); jaddnum(retjson,"numbids",numbids); array = cJSON_CreateArray(); - for (i=0; inumutxos == 0 )//|| basecoin->electrum == 0 ) + LP_address(basecoin,asks[i]->coinaddr), n++; free(asks[i]); asks[i] = 0; } + if ( n > 0 && basecoin->lastmonitor > 3600 ) + basecoin->lastmonitor -= 3600; jadd(retjson,"asks",array); jaddnum(retjson,"numasks",numasks); jaddstr(retjson,"base",base); @@ -738,7 +815,7 @@ char *LP_pricestr(char *base,char *rel,double origprice) retjson = cJSON_CreateObject(); jaddstr(retjson,"result","success"); jaddstr(retjson,"method","postprice"); - jaddbits256(retjson,"pubkey",LP_mypub25519); + jaddbits256(retjson,"pubkey",G.LP_mypub25519); jaddstr(retjson,"base",base); jaddstr(retjson,"rel",rel); jaddnum(retjson,"price",price); @@ -915,9 +992,10 @@ void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price) } if ( (pubp= LP_pubkeyadd(pubkey)) != 0 ) { - if ( (rand() % 100) == 0 && fabs(pubp->matrix[basepp->ind][relpp->ind] - price) > SMALLVAL ) - printf("PRICEFEED UPDATE.(%-6s/%6s) %12.8f %s %12.8f\n",base,rel,price,bits256_str(str,pubkey),1./price); + if ( fabs(pubp->matrix[basepp->ind][relpp->ind] - price) > SMALLVAL ) { + if ( (rand() % 5000) == 0 ) + printf("PRICEFEED UPDATE.(%-6s/%6s) %12.8f %s %12.8f\n",base,rel,price,bits256_str(str,pubkey),1./price); pubp->matrix[basepp->ind][relpp->ind] = price; dxblend(&basepp->relvals[relpp->ind],price,0.9); dxblend(&relpp->relvals[basepp->ind],1. / price,0.9); diff --git a/iguana/exchanges/LP_remember.c b/iguana/exchanges/LP_remember.c index f8740d048..edfb8ac2a 100644 --- a/iguana/exchanges/LP_remember.c +++ b/iguana/exchanges/LP_remember.c @@ -244,18 +244,22 @@ bits256 basilisk_swap_privBn_extract(bits256 *bobrefundp,char *bobcoin,bits256 b return(privBn); } -bits256 basilisk_swap_spendupdate(char *symbol,int32_t *sentflags,bits256 *txids,int32_t utxoind,int32_t alicespent,int32_t bobspent,int32_t vout,char *aliceaddr,char *bobaddr) +bits256 basilisk_swap_spendupdate(char *symbol,char *spentaddr,int32_t *sentflags,bits256 *txids,int32_t utxoind,int32_t alicespent,int32_t bobspent,int32_t vout,char *aliceaddr,char *bobaddr) { - bits256 spendtxid,txid; char destaddr[64]; + bits256 spendtxid,txid; char destaddr[64],str[65]; struct iguana_info *coin; cJSON *histobj; + if ( (coin= LP_coinfind(symbol)) != 0 && coin->electrum != 0 ) + { + if ( (histobj= electrum_address_gethistory(symbol,coin->electrum,&histobj,spentaddr)) != 0 ) + { + //printf("processed history.(%s)\n",jprint(histobj,0)); + free_json(histobj); + } + } txid = txids[utxoind]; memset(&spendtxid,0,sizeof(spendtxid)); - /*if ( aliceaddr != 0 ) - printf("aliceaddr.(%s)\n",aliceaddr); - if ( bobaddr != 0 ) - printf("bobaddr.(%s)\n",bobaddr);*/ if ( bits256_nonz(txid) != 0 ) { - //char str[65]; + destaddr[0] = 0; spendtxid = LP_swap_spendtxid(symbol,destaddr,txid,vout); if ( bits256_nonz(spendtxid) != 0 ) { @@ -290,7 +294,7 @@ bits256 basilisk_swap_spendupdate(char *symbol,int32_t *sentflags,bits256 *txids txids[alicespent] = spendtxid; } } - } + } else printf("no spend of %s/v%d detected\n",bits256_str(str,txid),vout); } else printf("utxoind.%d null txid\n",utxoind); return(spendtxid); } @@ -396,99 +400,188 @@ uint32_t LP_extract(uint32_t requestid,uint32_t quoteid,char *rootfname,char *fi return(t); } -cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requestid,uint32_t quoteid) +void LP_totals_update(int32_t iambob,char *alicecoin,char *bobcoin,int64_t *KMDtotals,int64_t *BTCtotals,int32_t *sentflags,int64_t *values) // update to handle all coins { - static void *ctx; - FILE *fp; int32_t sentflags[sizeof(txnames)/sizeof(*txnames)],i,n,j,Predeemlen,Dredeemlen,len,needflag,secretstart,redeemlen,addflag,origfinishedflag = 0,finishedflag = 0,iambob = -1; int64_t srcamount,destamount=0,value,values[sizeof(txnames)/sizeof(*txnames)]; uint8_t secretAm[20],secretAm256[32],secretBn[20],secretBn256[32],pubkey33[33],Predeemscript[1024],Dredeemscript[1024],redeemscript[1024],userdata[1024]; uint32_t plocktime,dlocktime,expiration=0,r,q,state,otherstate; char *secretstr,*srcstr,*deststr,str[65],src[64],dest[64],fname[512],*fstr,*dest33,*rstr,*symbol,*txname,*Adest,*Bdest,*AAdest,*ABdest,destaddr[64],Adestaddr[64],alicepaymentaddr[64],bobpaymentaddr[64],bobdepositaddr[64],alicecoin[64],bobcoin[64],*txbytes[sizeof(txnames)/sizeof(*txnames)]; long fsize; cJSON *txobj,*item,*sentobj,*array; bits256 checktxid,txid,pubA0,pubB0,pubB1,privAm,privBn,paymentspent,Apaymentspent,depositspent,zero,privkey,rev,myprivs[2],txids[sizeof(txnames)/sizeof(*txnames)],signedtxid; struct iguana_info *bob=0,*alice=0; uint64_t Atxfee=0,Btxfee=0; - if ( ctx == 0 ) - ctx = bitcoin_ctx(); - bobpaymentaddr[0] = bobdepositaddr[0] = alicepaymentaddr[0] = 0; - memset(Predeemscript,0,sizeof(Predeemscript)); - memset(Dredeemscript,0,sizeof(Dredeemscript)); - Predeemlen = Dredeemlen = 0; - memset(values,0,sizeof(values)); - memset(txids,0,sizeof(txids)); - memset(secretAm,0,sizeof(secretAm)); - memset(secretAm256,0,sizeof(secretAm256)); - memset(secretBn,0,sizeof(secretBn)); - memset(secretBn256,0,sizeof(secretBn256)); - memset(pubkey33,0,sizeof(pubkey33)); - memset(txbytes,0,sizeof(txbytes)); - memset(sentflags,0,sizeof(sentflags)); - memset(myprivs,0,sizeof(myprivs)); - Apaymentspent = paymentspent = depositspent = rev = zero = pubA0 = pubB0 = pubB1 = privAm = privBn = myprivs[0]; - plocktime = dlocktime = 0; - src[0] = dest[0] = bobcoin[0] = alicecoin[0] = 0; + values[BASILISK_OTHERFEE] = 0; + if ( iambob == 0 ) + { + if ( strcmp(alicecoin,"BTC") == 0 ) + { + BTCtotals[BASILISK_ALICEPAYMENT] -= values[BASILISK_ALICEPAYMENT] * sentflags[BASILISK_ALICEPAYMENT]; + BTCtotals[BASILISK_ALICERECLAIM] += values[BASILISK_ALICEPAYMENT] * sentflags[BASILISK_ALICERECLAIM]; + BTCtotals[BASILISK_MYFEE] -= values[BASILISK_MYFEE] * sentflags[BASILISK_MYFEE]; + } + else if ( strcmp(alicecoin,"KMD") == 0 ) + { + KMDtotals[BASILISK_ALICEPAYMENT] -= values[BASILISK_ALICEPAYMENT] * sentflags[BASILISK_ALICEPAYMENT]; + KMDtotals[BASILISK_ALICERECLAIM] += values[BASILISK_ALICEPAYMENT] * sentflags[BASILISK_ALICERECLAIM]; + KMDtotals[BASILISK_MYFEE] -= values[BASILISK_MYFEE] * sentflags[BASILISK_MYFEE]; + } + if ( strcmp(bobcoin,"KMD") == 0 ) + { + KMDtotals[BASILISK_ALICESPEND] += values[BASILISK_BOBPAYMENT] * sentflags[BASILISK_ALICESPEND]; + KMDtotals[BASILISK_ALICECLAIM] += values[BASILISK_BOBDEPOSIT] * sentflags[BASILISK_ALICECLAIM]; + } + else if ( strcmp(bobcoin,"BTC") == 0 ) + { + BTCtotals[BASILISK_ALICESPEND] += values[BASILISK_BOBPAYMENT] * sentflags[BASILISK_ALICESPEND]; + BTCtotals[BASILISK_ALICECLAIM] += values[BASILISK_BOBDEPOSIT] * sentflags[BASILISK_ALICECLAIM]; + } + } + else + { + if ( strcmp(bobcoin,"BTC") == 0 ) + { + BTCtotals[BASILISK_BOBPAYMENT] -= values[BASILISK_BOBPAYMENT] * sentflags[BASILISK_BOBPAYMENT]; + BTCtotals[BASILISK_BOBDEPOSIT] -= values[BASILISK_BOBDEPOSIT] * sentflags[BASILISK_BOBDEPOSIT]; + BTCtotals[BASILISK_BOBREFUND] += values[BASILISK_BOBREFUND] * sentflags[BASILISK_BOBREFUND]; + BTCtotals[BASILISK_BOBRECLAIM] += values[BASILISK_BOBRECLAIM] * sentflags[BASILISK_BOBRECLAIM]; + BTCtotals[BASILISK_MYFEE] -= values[BASILISK_MYFEE] * sentflags[BASILISK_MYFEE]; + } + else if ( strcmp(bobcoin,"KMD") == 0 ) + { + KMDtotals[BASILISK_BOBPAYMENT] -= values[BASILISK_BOBPAYMENT] * sentflags[BASILISK_BOBPAYMENT]; + KMDtotals[BASILISK_BOBDEPOSIT] -= values[BASILISK_BOBDEPOSIT] * sentflags[BASILISK_BOBDEPOSIT]; + KMDtotals[BASILISK_BOBREFUND] += values[BASILISK_BOBDEPOSIT] * sentflags[BASILISK_BOBREFUND]; + KMDtotals[BASILISK_BOBRECLAIM] += values[BASILISK_BOBPAYMENT] * sentflags[BASILISK_BOBRECLAIM]; + KMDtotals[BASILISK_MYFEE] -= values[BASILISK_MYFEE] * sentflags[BASILISK_MYFEE]; + } + if ( strcmp(alicecoin,"KMD") == 0 ) + { + KMDtotals[BASILISK_BOBSPEND] += values[BASILISK_BOBSPEND] * sentflags[BASILISK_BOBSPEND]; + } + else if ( strcmp(alicecoin,"BTC") == 0 ) + { + BTCtotals[BASILISK_BOBSPEND] += values[BASILISK_ALICEPAYMENT] * sentflags[BASILISK_BOBSPEND]; + } + } +} + +struct LP_swap_remember +{ + bits256 pubA0,pubB0,pubB1,privAm,privBn,paymentspent,Apaymentspent,depositspent,myprivs[2],txids[sizeof(txnames)/sizeof(*txnames)]; + uint64_t Atxfee,Btxfee,srcamount,destamount; int64_t values[sizeof(txnames)/sizeof(*txnames)]; + uint32_t requestid,quoteid,plocktime,dlocktime,expiration,state,otherstate; + int32_t iambob,finishedflag,origfinishedflag,Predeemlen,Dredeemlen,sentflags[sizeof(txnames)/sizeof(*txnames)]; + uint8_t secretAm[20],secretAm256[32],secretBn[20],secretBn256[32],pubkey33[33],Predeemscript[1024],Dredeemscript[1024]; + char src[64],dest[64],destaddr[64],Adestaddr[64],alicepaymentaddr[64],bobpaymentaddr[64],bobdepositaddr[64],alicecoin[64],bobcoin[64],*txbytes[sizeof(txnames)/sizeof(*txnames)]; +}; + +cJSON *LP_swap_json(struct LP_swap_remember *rswap) +{ + cJSON *item,*array; int32_t i; + item = cJSON_CreateObject(); + jaddnum(item,"requestid",rswap->requestid); + jaddnum(item,"quoteid",rswap->quoteid); + jaddnum(item,"iambob",rswap->iambob); + jaddstr(item,"bob",rswap->src); + jaddnum(item,"srcamount",dstr(rswap->srcamount)); + jaddnum(item,"bobtxfee",dstr(rswap->Btxfee)); + jaddstr(item,"alice",rswap->dest); + jaddnum(item,"destamount",dstr(rswap->destamount)); + jaddnum(item,"alicetxfee",dstr(rswap->Atxfee)); + array = cJSON_CreateArray(); + for (i=0; isentflags[i] != 0 ) + jaddistr(array,txnames[i]); + if ( rswap->txbytes[i] != 0 ) + free(rswap->txbytes[i]); + } + jadd(item,"sentflags",array); + array = cJSON_CreateArray(); + for (i=0; ivalues[i])); + jadd(item,"values",array); + jaddstr(item,"result","success"); + if ( rswap->finishedflag != 0 ) + jaddstr(item,"status","finished"); + else jaddstr(item,"status","pending"); + jaddbits256(item,"bobdeposit",rswap->txids[BASILISK_BOBDEPOSIT]); + jaddbits256(item,"alicepayment",rswap->txids[BASILISK_ALICEPAYMENT]); + jaddbits256(item,"bobpayment",rswap->txids[BASILISK_BOBPAYMENT]); + jaddbits256(item,"paymentspent",rswap->paymentspent); + jaddbits256(item,"Apaymentspent",rswap->Apaymentspent); + jaddbits256(item,"depositspent",rswap->depositspent); + return(item); +} + +int32_t LP_rswap_init(struct LP_swap_remember *rswap,uint32_t requestid,uint32_t quoteid) +{ + char fname[1024],*fstr,*secretstr,*srcstr,*deststr,*dest33,*txname; long fsize; cJSON *item,*txobj,*array; bits256 privkey; uint32_t r,q; int32_t i,j,n; + memset(rswap,0,sizeof(*rswap)); + rswap->requestid = requestid; + rswap->quoteid = quoteid; sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname); if ( (fstr= OS_filestr(&fsize,fname)) != 0 ) { if ( (item= cJSON_Parse(fstr)) != 0 ) { - iambob = jint(item,"iambob"); + rswap->iambob = jint(item,"iambob"); if ( (secretstr= jstr(item,"secretAm")) != 0 && strlen(secretstr) == 40 ) - decode_hex(secretAm,20,secretstr); + decode_hex(rswap->secretAm,20,secretstr); if ( (secretstr= jstr(item,"secretAm256")) != 0 && strlen(secretstr) == 64 ) - decode_hex(secretAm256,32,secretstr); + decode_hex(rswap->secretAm256,32,secretstr); if ( (secretstr= jstr(item,"secretBn")) != 0 && strlen(secretstr) == 40 ) - decode_hex(secretBn,20,secretstr); + decode_hex(rswap->secretBn,20,secretstr); if ( (secretstr= jstr(item,"secretBn256")) != 0 && strlen(secretstr) == 64 ) - decode_hex(secretBn256,32,secretstr); + decode_hex(rswap->secretBn256,32,secretstr); if ( (srcstr= jstr(item,"src")) != 0 ) - safecopy(src,srcstr,sizeof(src)); + safecopy(rswap->src,srcstr,sizeof(rswap->src)); if ( (deststr= jstr(item,"dest")) != 0 ) - safecopy(dest,deststr,sizeof(dest)); + safecopy(rswap->dest,deststr,sizeof(rswap->dest)); if ( (dest33= jstr(item,"dest33")) != 0 && strlen(dest33) == 66 ) { - decode_hex(pubkey33,33,dest33); + decode_hex(rswap->pubkey33,33,dest33); //for (i=0; i<33; i++) // printf("%02x",pubkey33[i]); //printf(" <- %s dest33\n",dest33); } - if ( (plocktime= juint(item,"plocktime")) == 0 ) - plocktime = LP_extract(requestid,quoteid,fname,"plocktime"); - if ( (dlocktime= juint(item,"dlocktime")) == 0 ) - dlocktime = LP_extract(requestid,quoteid,fname,"dlocktime"); + if ( (rswap->plocktime= juint(item,"plocktime")) == 0 ) + rswap->plocktime = LP_extract(requestid,quoteid,fname,"plocktime"); + if ( (rswap->dlocktime= juint(item,"dlocktime")) == 0 ) + rswap->dlocktime = LP_extract(requestid,quoteid,fname,"dlocktime"); r = juint(item,"requestid"); q = juint(item,"quoteid"); - Atxfee = j64bits(item,"Atxfee"); - Btxfee = j64bits(item,"Btxfee"); - pubA0 = jbits256(item,"pubA0"); - pubB0 = jbits256(item,"pubB0"); - pubB1 = jbits256(item,"pubB1"); + rswap->Atxfee = j64bits(item,"Atxfee"); + rswap->Btxfee = j64bits(item,"Btxfee"); + rswap->pubA0 = jbits256(item,"pubA0"); + rswap->pubB0 = jbits256(item,"pubB0"); + rswap->pubB1 = jbits256(item,"pubB1"); privkey = jbits256(item,"myprivs0"); if ( bits256_nonz(privkey) != 0 ) - myprivs[0] = privkey; + rswap->myprivs[0] = privkey; privkey = jbits256(item,"myprivs1"); if ( bits256_nonz(privkey) != 0 ) - myprivs[1] = privkey; + rswap->myprivs[1] = privkey; privkey = jbits256(item,"privAm"); if ( bits256_nonz(privkey) != 0 ) { - privAm = privkey; + rswap->privAm = privkey; //printf("set privAm <- %s\n",bits256_str(str,privAm)); } privkey = jbits256(item,"privBn"); if ( bits256_nonz(privkey) != 0 ) { - privBn = privkey; + rswap->privBn = privkey; //printf("set privBn <- %s\n",bits256_str(str,privBn)); } - expiration = juint(item,"expiration"); - state = jint(item,"state"); - otherstate = jint(item,"otherstate"); - srcamount = SATOSHIDEN * jdouble(item,"srcamount"); - destamount = SATOSHIDEN * jdouble(item,"destamount"); - txids[BASILISK_BOBDEPOSIT] = jbits256(item,"Bdeposit"); - txids[BASILISK_BOBREFUND] = jbits256(item,"Brefund"); - txids[BASILISK_ALICECLAIM] = jbits256(item,"Aclaim"); - txids[BASILISK_BOBPAYMENT] = jbits256(item,"Bpayment"); - txids[BASILISK_ALICESPEND] = jbits256(item,"Aspend"); - txids[BASILISK_BOBRECLAIM] = jbits256(item,"Breclaim"); - txids[BASILISK_ALICEPAYMENT] = jbits256(item,"Apayment"); - txids[BASILISK_BOBSPEND] = jbits256(item,"Bspend"); - txids[BASILISK_ALICERECLAIM] = jbits256(item,"Areclaim"); - txids[BASILISK_MYFEE] = jbits256(item,"myfee"); - txids[BASILISK_OTHERFEE] = jbits256(item,"otherfee"); + rswap->expiration = juint(item,"expiration"); + rswap->state = jint(item,"state"); + rswap->otherstate = jint(item,"otherstate"); + rswap->srcamount = SATOSHIDEN * jdouble(item,"srcamount"); + rswap->destamount = SATOSHIDEN * jdouble(item,"destamount"); + rswap->txids[BASILISK_BOBDEPOSIT] = jbits256(item,"Bdeposit"); + rswap->txids[BASILISK_BOBREFUND] = jbits256(item,"Brefund"); + rswap->txids[BASILISK_ALICECLAIM] = jbits256(item,"Aclaim"); + rswap->txids[BASILISK_BOBPAYMENT] = jbits256(item,"Bpayment"); + rswap->txids[BASILISK_ALICESPEND] = jbits256(item,"Aspend"); + rswap->txids[BASILISK_BOBRECLAIM] = jbits256(item,"Breclaim"); + rswap->txids[BASILISK_ALICEPAYMENT] = jbits256(item,"Apayment"); + rswap->txids[BASILISK_BOBSPEND] = jbits256(item,"Bspend"); + rswap->txids[BASILISK_ALICERECLAIM] = jbits256(item,"Areclaim"); + rswap->txids[BASILISK_MYFEE] = jbits256(item,"myfee"); + rswap->txids[BASILISK_OTHERFEE] = jbits256(item,"otherfee"); free_json(item); } free(fstr); @@ -499,12 +592,12 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti //printf("%s -> (%s)\n",fname,fstr); if ( (txobj= cJSON_Parse(fstr)) != 0 ) { - paymentspent = jbits256(txobj,"paymentspent"); - Apaymentspent = jbits256(txobj,"Apaymentspent"); - depositspent = jbits256(txobj,"depositspent"); + rswap->paymentspent = jbits256(txobj,"paymentspent"); + rswap->Apaymentspent = jbits256(txobj,"Apaymentspent"); + rswap->depositspent = jbits256(txobj,"depositspent"); if ( (array= jarray(&n,txobj,"values")) != 0 ) for (i=0; ivalues[i] = SATOSHIDEN * jdouble(jitem(array,i),0); if ( (array= jarray(&n,txobj,"sentflags")) != 0 ) { for (i=0; isentflags[j] = 1; //printf("finished.%s\n",txnames[j]); break; } @@ -522,59 +615,61 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti } } } - origfinishedflag = finishedflag = 1; + rswap->origfinishedflag = rswap->finishedflag = 1; free(fstr); } - if ( iambob < 0 ) - return(0); - item = cJSON_CreateObject(); - array = cJSON_CreateArray(); + return(rswap->iambob); +} + +int32_t LP_swap_load(struct LP_swap_remember *rswap) +{ + int32_t i,needflag,addflag; long fsize; char fname[1024],str[65],*fstr,*symbol,*rstr; cJSON *txobj,*sentobj; bits256 txid,checktxid; uint64_t value; for (i=0; irequestid,rswap->quoteid,txnames[i]), OS_compatible_path(fname); if ( (fstr= OS_filestr(&fsize,fname)) != 0 ) { - if ( 0 && finishedflag == 0 ) + if ( 0 && rswap->finishedflag == 0 ) printf("%s\n",fname); //printf("%s -> (%s)\n",fname,fstr); if ( (txobj= cJSON_Parse(fstr)) != 0 ) { //printf("TXOBJ.(%s)\n",jprint(txobj,0)); - iambob = jint(txobj,"iambob"); + rswap->iambob = jint(txobj,"iambob"); txid = jbits256(txobj,"txid"); if ( bits256_nonz(txid) == 0 ) continue; - txids[i] = txid; + rswap->txids[i] = txid; if ( jstr(txobj,"Apayment") != 0 ) - strcpy(alicepaymentaddr,jstr(txobj,"Apayment")); + safecopy(rswap->alicepaymentaddr,jstr(txobj,"Apayment"),sizeof(rswap->alicepaymentaddr)); if ( jstr(txobj,"Bpayment") != 0 ) - strcpy(bobpaymentaddr,jstr(txobj,"Bpayment")); + safecopy(rswap->bobpaymentaddr,jstr(txobj,"Bpayment"),sizeof(rswap->bobpaymentaddr)); if ( jstr(txobj,"Bdeposit") != 0 ) - strcpy(bobdepositaddr,jstr(txobj,"Bdeposit")); + safecopy(rswap->bobdepositaddr,jstr(txobj,"Bdeposit"),sizeof(rswap->bobdepositaddr)); if ( jobj(txobj,"tx") != 0 ) { - txbytes[i] = clonestr(jstr(txobj,"tx")); + rswap->txbytes[i] = clonestr(jstr(txobj,"tx")); //printf("[%s] TX.(%s)\n",txnames[i],txbytes[i]); } - if ( strcmp(txnames[i],"bobpayment") == 0 && (rstr= jstr(txobj,"redeem")) != 0 && (Predeemlen= is_hexstr(rstr,0)) > 0 ) + if ( strcmp(txnames[i],"bobpayment") == 0 && (rstr= jstr(txobj,"redeem")) != 0 && (rswap->Predeemlen= is_hexstr(rstr,0)) > 0 ) { - Predeemlen >>= 1; - decode_hex(Predeemscript,Predeemlen,rstr); + rswap->Predeemlen >>= 1; + decode_hex(rswap->Predeemscript,rswap->Predeemlen,rstr); } - else if ( strcmp(txnames[i],"bobdeposit") == 0 && (rstr= jstr(txobj,"redeem")) != 0 && (Dredeemlen= is_hexstr(rstr,0)) > 0 ) + else if ( strcmp(txnames[i],"bobdeposit") == 0 && (rstr= jstr(txobj,"redeem")) != 0 && (rswap->Dredeemlen= is_hexstr(rstr,0)) > 0 ) { - Dredeemlen >>= 1; - decode_hex(Dredeemscript,Dredeemlen,rstr); + rswap->Dredeemlen >>= 1; + decode_hex(rswap->Dredeemscript,rswap->Dredeemlen,rstr); } - values[i] = value = LP_value_extract(txobj); + rswap->values[i] = value = LP_value_extract(txobj,1); if ( (symbol= jstr(txobj,"coin")) != 0 ) { if ( i == BASILISK_ALICESPEND || i == BASILISK_BOBPAYMENT || i == BASILISK_BOBDEPOSIT || i == BASILISK_BOBREFUND || i == BASILISK_BOBRECLAIM || i == BASILISK_ALICECLAIM ) - safecopy(bobcoin,symbol,sizeof(bobcoin)); + safecopy(rswap->bobcoin,symbol,sizeof(rswap->bobcoin)); else if ( i == BASILISK_BOBSPEND || i == BASILISK_ALICEPAYMENT || i == BASILISK_ALICERECLAIM ) - safecopy(alicecoin,symbol,sizeof(alicecoin)); - if ( finishedflag == 0 ) + safecopy(rswap->alicecoin,symbol,sizeof(rswap->alicecoin)); + if ( rswap->finishedflag == 0 ) { if ( (sentobj= LP_gettx(symbol,txid)) == 0 ) { @@ -594,58 +689,98 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti if ( bits256_cmp(checktxid,txid) == 0 ) { //printf(">>>>>> %s txid %s\n",jprint(sentobj,0),bits256_str(str,txid)); - sentflags[i] = 1; + rswap->sentflags[i] = 1; } free_json(sentobj); } - if ( finishedflag == 0 ) + if ( rswap->finishedflag == 0 ) printf("%s %s %.8f\n",txnames[i],bits256_str(str,txid),dstr(value)); } } } //else printf("no symbol\n"); free(fstr); - } else if ( 0 && finishedflag == 0 ) + } else if ( 0 && rswap->finishedflag == 0 ) printf("%s not finished\n",fname); } - //printf("alicepayment.%s bobpayment.%s bobdeposit.%s\n",alicepaymentaddr,bobpaymentaddr,bobdepositaddr); - //printf("iambob.%d src.%s dest.%s bob.%s alice.%s pubA0.(%s)\n",iambob,src,dest,bobcoin,alicecoin,bits256_str(str,pubA0)); - Adestaddr[0] = destaddr[0] = 0; + return(rswap->finishedflag); +} + +/*{ + if ( txbytes[BASILISK_BOBREFUND] != 0 ) + { + txids[BASILISK_BOBREFUND] = LP_broadcast("bobrefund",bobcoin,txbytes[BASILISK_BOBREFUND],zero); + if ( bits256_nonz(txids[BASILISK_BOBREFUND]) != 0 ) // tested + { + sentflags[BASILISK_BOBREFUND] = 1; + depositspent = txids[BASILISK_BOBREFUND]; + } + } +}*/ + +int32_t LP_rswap_checktx(struct LP_swap_remember *rswap,char *symbol,int32_t txi) +{ + cJSON *sentobj; char str[65]; + if ( rswap->sentflags[txi] == 0 && bits256_nonz(rswap->txids[txi]) != 0 ) + { + printf("[%s] txbytes.%p Apayment.%s\n",txnames[txi],rswap->txbytes[txi],bits256_str(str,rswap->txids[txi])); + if ( rswap->txbytes[txi] != 0 ) + rswap->sentflags[txi] = 1; + else if ( (sentobj= LP_gettx(symbol,rswap->txids[txi])) != 0 ) + { + rswap->sentflags[txi] = 1; + free_json(sentobj); + return(1); + } + } + return(0); +} + +cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requestid,uint32_t quoteid) +{ + static void *ctx; + struct LP_swap_remember rswap; int32_t i,j,len,secretstart,redeemlen; char str[65],*Adest,*Bdest,*AAdest,*ABdest; cJSON *item; bits256 rev,signedtxid,zero; struct iguana_info *bob=0,*alice=0; uint8_t redeemscript[1024],userdata[1024]; + if ( ctx == 0 ) + ctx = bitcoin_ctx(); + if ( (rswap.iambob= LP_rswap_init(&rswap,requestid,quoteid)) < 0 ) + return(0); + LP_swap_load(&rswap); + memset(zero.bytes,0,sizeof(zero)); Adest = Bdest = AAdest = ABdest = 0; - if ( bobcoin[0] == 0 || alicecoin[0] == 0 ) + if ( rswap.bobcoin[0] == 0 || rswap.alicecoin[0] == 0 || strcmp(rswap.bobcoin,rswap.src) != 0 || strcmp(rswap.alicecoin,rswap.dest) != 0 ) return(0); - alice = LP_coinfind(alicecoin); - bob = LP_coinfind(bobcoin); - Atxfee = LP_txfeecalc(alice,Atxfee); - Btxfee = LP_txfeecalc(bob,Btxfee); + alice = LP_coinfind(rswap.alicecoin); + bob = LP_coinfind(rswap.bobcoin); + rswap.Atxfee = LP_txfeecalc(alice,rswap.Atxfee); + rswap.Btxfee = LP_txfeecalc(bob,rswap.Btxfee); //printf("%s %.8f txfee, %s %.8f txfee\n",alicecoin,dstr(Atxfee),bobcoin,dstr(Btxfee)); //printf("privAm.(%s) %p/%p\n",bits256_str(str,privAm),Adest,AAdest); //printf("privBn.(%s) %p/%p\n",bits256_str(str,privBn),Bdest,ABdest); - if ( finishedflag == 0 && bobcoin[0] != 0 && alicecoin[0] != 0 ) + if ( rswap.finishedflag == 0 && rswap.bobcoin[0] != 0 && rswap.alicecoin[0] != 0 ) { - if ( iambob == 0 ) + if ( rswap.iambob == 0 ) { if ( alice != 0 ) { - bitcoin_address(Adestaddr,alice->taddr,alice->pubtype,pubkey33,33); - AAdest = Adestaddr; + bitcoin_address(rswap.Adestaddr,alice->taddr,alice->pubtype,rswap.pubkey33,33); + AAdest = rswap.Adestaddr; } - if ( (bob= LP_coinfind(bobcoin)) != 0 ) + if ( (bob= LP_coinfind(rswap.bobcoin)) != 0 ) { - bitcoin_address(destaddr,bob->taddr,bob->pubtype,pubkey33,33); - Adest = destaddr; + bitcoin_address(rswap.destaddr,bob->taddr,bob->pubtype,rswap.pubkey33,33); + Adest = rswap.destaddr; } } else { if ( bob != 0 ) { - bitcoin_address(destaddr,bob->taddr,bob->pubtype,pubkey33,33); - Bdest = destaddr; + bitcoin_address(rswap.destaddr,bob->taddr,bob->pubtype,rswap.pubkey33,33); + Bdest = rswap.destaddr; } - if ( (alice= LP_coinfind(alicecoin)) != 0 ) + if ( (alice= LP_coinfind(rswap.alicecoin)) != 0 ) { - bitcoin_address(Adestaddr,alice->taddr,alice->pubtype,pubkey33,33); - ABdest = Adestaddr; + bitcoin_address(rswap.Adestaddr,alice->taddr,alice->pubtype,rswap.pubkey33,33); + ABdest = rswap.Adestaddr; } } if ( bob == 0 || alice == 0 ) @@ -655,318 +790,242 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti } if ( alice->inactive != 0 || bob->inactive != 0 ) { - printf("Alice.%s inactive.%u or Bob.%s inactive.%u\n",alicecoin,alice->inactive,bobcoin,bob->inactive); + printf("Alice.%s inactive.%u or Bob.%s inactive.%u\n",rswap.alicecoin,alice->inactive,rswap.bobcoin,bob->inactive); return(0); } - if ( sentflags[BASILISK_ALICEPAYMENT] == 0 && bits256_nonz(txids[BASILISK_ALICEPAYMENT]) != 0 ) + LP_rswap_checktx(&rswap,rswap.alicecoin,BASILISK_ALICEPAYMENT); + LP_rswap_checktx(&rswap,rswap.bobcoin,BASILISK_BOBPAYMENT); + LP_rswap_checktx(&rswap,rswap.bobcoin,BASILISK_BOBDEPOSIT); + rswap.paymentspent = basilisk_swap_spendupdate(rswap.bobcoin,rswap.bobpaymentaddr,rswap.sentflags,rswap.txids,BASILISK_BOBPAYMENT,BASILISK_ALICESPEND,BASILISK_BOBRECLAIM,0,Adest,Bdest); + rswap.Apaymentspent = basilisk_swap_spendupdate(rswap.alicecoin,rswap.alicepaymentaddr,rswap.sentflags,rswap.txids,BASILISK_ALICEPAYMENT,BASILISK_ALICERECLAIM,BASILISK_BOBSPEND,0,AAdest,ABdest); + rswap.depositspent = basilisk_swap_spendupdate(rswap.bobcoin,rswap.bobdepositaddr,rswap.sentflags,rswap.txids,BASILISK_BOBDEPOSIT,BASILISK_ALICECLAIM,BASILISK_BOBREFUND,0,Adest,Bdest); + rswap.finishedflag = basilisk_swap_isfinished(rswap.iambob,rswap.txids,rswap.sentflags,rswap.paymentspent,rswap.Apaymentspent,rswap.depositspent); + if ( rswap.iambob == 0 ) { - printf("txbytes.%p Apayment.%s\n",txbytes[BASILISK_ALICEPAYMENT],bits256_str(str,txids[BASILISK_ALICEPAYMENT])); - if ( txbytes[BASILISK_ALICEPAYMENT] != 0 ) - sentflags[BASILISK_ALICEPAYMENT] = 1; - else if ( (sentobj= LP_gettx(alicecoin,txids[BASILISK_ALICEPAYMENT])) != 0 ) + if ( rswap.sentflags[BASILISK_ALICESPEND] == 0 ) { - sentflags[BASILISK_ALICEPAYMENT] = 1; - free_json(sentobj); - } - } - paymentspent = basilisk_swap_spendupdate(bobcoin,sentflags,txids,BASILISK_BOBPAYMENT,BASILISK_ALICESPEND,BASILISK_BOBRECLAIM,0,Adest,Bdest); - Apaymentspent = basilisk_swap_spendupdate(alicecoin,sentflags,txids,BASILISK_ALICEPAYMENT,BASILISK_ALICERECLAIM,BASILISK_BOBSPEND,0,AAdest,ABdest); - depositspent = basilisk_swap_spendupdate(bobcoin,sentflags,txids,BASILISK_BOBDEPOSIT,BASILISK_ALICECLAIM,BASILISK_BOBREFUND,0,Adest,Bdest); - finishedflag = basilisk_swap_isfinished(iambob,txids,sentflags,paymentspent,Apaymentspent,depositspent); - if ( iambob == 0 ) - { - if ( sentflags[BASILISK_ALICESPEND] == 0 ) - { - if ( sentflags[BASILISK_BOBPAYMENT] != 0 && bits256_nonz(paymentspent) == 0 ) + if ( rswap.sentflags[BASILISK_BOBPAYMENT] != 0 && bits256_nonz(rswap.paymentspent) == 0 ) { //if ( txbytes[BASILISK_ALICESPEND] == 0 ) { - if ( bits256_nonz(txids[BASILISK_BOBPAYMENT]) != 0 ) + if ( bits256_nonz(rswap.txids[BASILISK_BOBPAYMENT]) != 0 ) { // alicespend + memset(rev.bytes,0,sizeof(rev)); for (j=0; j<32; j++) - rev.bytes[j] = privAm.bytes[31 - j]; + rev.bytes[j] = rswap.privAm.bytes[31 - j]; //revcalc_rmd160_sha256(secretAm,rev);//privAm); //vcalc_sha256(0,secretAm256,rev.bytes,sizeof(rev)); - if ( Predeemlen != 0 ) - redeemlen = Predeemlen, memcpy(redeemscript,Predeemscript,Predeemlen); - else redeemlen = basilisk_swap_bobredeemscript(0,&secretstart,redeemscript,plocktime,pubA0,pubB0,pubB1,rev,privBn,secretAm,secretAm256,secretBn,secretBn256); - len = basilisk_swapuserdata(userdata,rev,0,myprivs[0],redeemscript,redeemlen); + if ( rswap.Predeemlen != 0 ) + redeemlen = rswap.Predeemlen, memcpy(redeemscript,rswap.Predeemscript,rswap.Predeemlen); + else redeemlen = basilisk_swap_bobredeemscript(0,&secretstart,redeemscript,rswap.plocktime,rswap.pubA0,rswap.pubB0,rswap.pubB1,rev,rswap.privBn,rswap.secretAm,rswap.secretAm256,rswap.secretBn,rswap.secretBn256); + len = basilisk_swapuserdata(userdata,rev,0,rswap.myprivs[0],redeemscript,redeemlen); { char privaddr[64]; uint8_t privpub33[33]; - bitcoin_pubkey33(ctx,privpub33,myprivs[0]); + bitcoin_pubkey33(ctx,privpub33,rswap.myprivs[0]); bitcoin_address(privaddr,0,60,privpub33,33); - printf("alicespend len.%d redeemlen.%d priv0addr.(%s) priv0.(%s)\n",len,redeemlen,privaddr,bits256_str(str,myprivs[0])); + printf("alicespend len.%d redeemlen.%d priv0addr.(%s) priv0.(%s)\n",len,redeemlen,privaddr,bits256_str(str,rswap.myprivs[0])); } for (j=0; j<32; j++) - rev.bytes[j] = myprivs[0].bytes[31 - j]; - if ( (txbytes[BASILISK_ALICESPEND]= basilisk_swap_bobtxspend(&signedtxid,Btxfee,"alicespend",bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,0,pubkey33,1,expiration,&values[BASILISK_ALICESPEND],0,0,bobpaymentaddr,1)) != 0 ) - printf("alicespend.(%s)\n",txbytes[BASILISK_ALICESPEND]); + rev.bytes[j] = rswap.myprivs[0].bytes[31 - j]; + if ( (rswap.txbytes[BASILISK_ALICESPEND]= basilisk_swap_bobtxspend(&signedtxid,rswap.Btxfee,"alicespend",rswap.bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,rswap.myprivs[0],0,redeemscript,redeemlen,userdata,len,rswap.txids[BASILISK_BOBPAYMENT],0,0,rswap.pubkey33,1,rswap.expiration,&rswap.values[BASILISK_ALICESPEND],0,0,rswap.bobpaymentaddr,1)) != 0 ) + printf("alicespend.(%s)\n",rswap.txbytes[BASILISK_ALICESPEND]); } } - if ( txbytes[BASILISK_ALICESPEND] != 0 ) + if ( rswap.txbytes[BASILISK_ALICESPEND] != 0 ) { - txids[BASILISK_ALICESPEND] = LP_broadcast("alicespend",bobcoin,txbytes[BASILISK_ALICESPEND],zero); - if ( bits256_nonz(txids[BASILISK_ALICESPEND]) != 0 ) // tested + rswap.txids[BASILISK_ALICESPEND] = LP_broadcast("alicespend",rswap.bobcoin,rswap.txbytes[BASILISK_ALICESPEND],zero); + if ( bits256_nonz(rswap.txids[BASILISK_ALICESPEND]) != 0 ) // tested { - sentflags[BASILISK_ALICESPEND] = 1; - paymentspent = txids[BASILISK_ALICESPEND]; + rswap.sentflags[BASILISK_ALICESPEND] = 1; + rswap.paymentspent = rswap.txids[BASILISK_ALICESPEND]; } } } } - if ( sentflags[BASILISK_ALICECLAIM] == 0 && sentflags[BASILISK_BOBDEPOSIT] != 0 && bits256_nonz(txids[BASILISK_BOBDEPOSIT]) != 0 && bits256_nonz(depositspent) == 0 ) + if ( rswap.sentflags[BASILISK_ALICECLAIM] == 0 && rswap.sentflags[BASILISK_BOBDEPOSIT] != 0 && bits256_nonz(rswap.txids[BASILISK_BOBDEPOSIT]) != 0 && bits256_nonz(rswap.depositspent) == 0 ) { - if ( time(NULL) > expiration ) + if ( time(NULL) > rswap.expiration ) { //if ( txbytes[BASILISK_ALICECLAIM] == 0 ) { - if ( Dredeemlen != 0 ) - redeemlen = Dredeemlen, memcpy(redeemscript,Dredeemscript,Dredeemlen); - else redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,dlocktime,pubA0,pubB0,pubB1,privAm,zero,secretAm,secretAm256,secretBn,secretBn256); + if ( rswap.Dredeemlen != 0 ) + redeemlen = rswap.Dredeemlen, memcpy(redeemscript,rswap.Dredeemscript,rswap.Dredeemlen); + else redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,rswap.dlocktime,rswap.pubA0,rswap.pubB0,rswap.pubB1,rswap.privAm,zero,rswap.secretAm,rswap.secretAm256,rswap.secretBn,rswap.secretBn256); if ( redeemlen > 0 ) { - len = basilisk_swapuserdata(userdata,zero,1,myprivs[0],redeemscript,redeemlen); - if ( (txbytes[BASILISK_ALICECLAIM]= basilisk_swap_bobtxspend(&signedtxid,Btxfee,"aliceclaim",bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,0,pubkey33,0,expiration,&values[BASILISK_ALICECLAIM],0,0,bobdepositaddr,1)) != 0 ) - printf("privBn.(%s) aliceclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICECLAIM]); + if ( bits256_nonz(rswap.privBn) == 0 ) + rswap.privBn = basilisk_swap_privBn_extract(&rswap.txids[BASILISK_BOBREFUND],rswap.bobcoin,rswap.txids[BASILISK_BOBDEPOSIT],rswap.privBn); + if ( bits256_nonz(rswap.privBn) != 0 ) + { + len = basilisk_swapuserdata(userdata,zero,1,rswap.myprivs[0],redeemscript,redeemlen); + if ( (rswap.txbytes[BASILISK_ALICECLAIM]= basilisk_swap_bobtxspend(&signedtxid,rswap.Btxfee,"aliceclaim",rswap.bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,rswap.myprivs[0],0,redeemscript,redeemlen,userdata,len,rswap.txids[BASILISK_BOBDEPOSIT],0,0,rswap.pubkey33,0,rswap.expiration,&rswap.values[BASILISK_ALICECLAIM],0,0,rswap.bobdepositaddr,1)) != 0 ) + printf("privBn.(%s) aliceclaim.(%s)\n",bits256_str(str,rswap.privBn),rswap.txbytes[BASILISK_ALICECLAIM]); + } } } - if ( txbytes[BASILISK_ALICECLAIM] != 0 ) + if ( rswap.txbytes[BASILISK_ALICECLAIM] != 0 ) { - txids[BASILISK_ALICECLAIM] = LP_broadcast("aliceclaim",bobcoin,txbytes[BASILISK_ALICECLAIM],zero); - if ( bits256_nonz(txids[BASILISK_ALICECLAIM]) != 0 ) // tested + rswap.txids[BASILISK_ALICECLAIM] = LP_broadcast("aliceclaim",rswap.bobcoin,rswap.txbytes[BASILISK_ALICECLAIM],zero); + if ( bits256_nonz(rswap.txids[BASILISK_ALICECLAIM]) != 0 ) // tested { - sentflags[BASILISK_ALICECLAIM] = 1; - depositspent = txids[BASILISK_ALICECLAIM]; + rswap.sentflags[BASILISK_ALICECLAIM] = 1; + rswap.depositspent = rswap.txids[BASILISK_ALICECLAIM]; } } - } else printf("now %u before expiration %u\n",(uint32_t)time(NULL),expiration); + } else printf("now %u before expiration %u\n",(uint32_t)time(NULL),rswap.expiration); } - if ( sentflags[BASILISK_ALICEPAYMENT] != 0 && bits256_nonz(Apaymentspent) == 0 && sentflags[BASILISK_ALICECLAIM] == 0 ) + if ( rswap.sentflags[BASILISK_ALICEPAYMENT] != 0 && bits256_nonz(rswap.Apaymentspent) == 0 && rswap.sentflags[BASILISK_ALICECLAIM] == 0 ) { //if ( txbytes[BASILISK_ALICERECLAIM] == 0 ) { - privBn = basilisk_swap_privBn_extract(&txids[BASILISK_BOBREFUND],bobcoin,txids[BASILISK_BOBDEPOSIT],privBn); - if ( bits256_nonz(txids[BASILISK_ALICEPAYMENT]) != 0 && bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 ) + rswap.privBn = basilisk_swap_privBn_extract(&rswap.txids[BASILISK_BOBREFUND],rswap.bobcoin,rswap.txids[BASILISK_BOBDEPOSIT],rswap.privBn); + if ( bits256_nonz(rswap.txids[BASILISK_ALICEPAYMENT]) != 0 && bits256_nonz(rswap.privAm) != 0 && bits256_nonz(rswap.privBn) != 0 ) { - if ( (txbytes[BASILISK_ALICERECLAIM]= basilisk_swap_Aspend("alicereclaim",alicecoin,Atxfee,alice->wiftaddr,alice->taddr,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_ALICERECLAIM],alicepaymentaddr)) != 0 ) - printf("privBn.(%s) alicereclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICERECLAIM]); + if ( (rswap.txbytes[BASILISK_ALICERECLAIM]= basilisk_swap_Aspend("alicereclaim",rswap.alicecoin,rswap.Atxfee,alice->wiftaddr,alice->taddr,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,rswap.privAm,rswap.privBn,rswap.txids[BASILISK_ALICEPAYMENT],0,rswap.pubkey33,rswap.expiration,&rswap.values[BASILISK_ALICERECLAIM],rswap.alicepaymentaddr)) != 0 ) + printf("privBn.(%s) alicereclaim.(%s)\n",bits256_str(str,rswap.privBn),rswap.txbytes[BASILISK_ALICERECLAIM]); } } - if ( txbytes[BASILISK_ALICERECLAIM] != 0 ) + if ( rswap.txbytes[BASILISK_ALICERECLAIM] != 0 ) { - txids[BASILISK_ALICERECLAIM] = LP_broadcast("alicereclaim",alicecoin,txbytes[BASILISK_ALICERECLAIM],zero); - if ( bits256_nonz(txids[BASILISK_ALICERECLAIM]) != 0 ) // tested + rswap.txids[BASILISK_ALICERECLAIM] = LP_broadcast("alicereclaim",rswap.alicecoin,rswap.txbytes[BASILISK_ALICERECLAIM],zero); + if ( bits256_nonz(rswap.txids[BASILISK_ALICERECLAIM]) != 0 ) // tested { - sentflags[BASILISK_ALICERECLAIM] = 1; - Apaymentspent = txids[BASILISK_ALICERECLAIM]; + rswap.sentflags[BASILISK_ALICERECLAIM] = 1; + rswap.Apaymentspent = rswap.txids[BASILISK_ALICERECLAIM]; } } } } - else if ( iambob == 1 ) + else if ( rswap.iambob == 1 ) { - if ( sentflags[BASILISK_BOBSPEND] == 0 && bits256_nonz(Apaymentspent) == 0 ) + if ( rswap.sentflags[BASILISK_BOBSPEND] == 0 && bits256_nonz(rswap.Apaymentspent) == 0 ) { - printf("try to bobspend aspend.%s have privAm.%d\n",bits256_str(str,txids[BASILISK_ALICESPEND]),bits256_nonz(privAm)); - if ( bits256_nonz(txids[BASILISK_ALICESPEND]) != 0 || bits256_nonz(privAm) != 0 ) + printf("try to bobspend aspend.%s have privAm.%d\n",bits256_str(str,rswap.txids[BASILISK_ALICESPEND]),bits256_nonz(rswap.privAm)); + if ( bits256_nonz(rswap.txids[BASILISK_ALICESPEND]) != 0 || bits256_nonz(rswap.privAm) != 0 ) { //if ( txbytes[BASILISK_BOBSPEND] == 0 ) { - if ( bits256_nonz(privAm) == 0 ) + if ( bits256_nonz(rswap.privAm) == 0 ) { - privAm = basilisk_swap_privbob_extract(bobcoin,txids[BASILISK_ALICESPEND],0,1); + rswap.privAm = basilisk_swap_privbob_extract(rswap.bobcoin,rswap.txids[BASILISK_ALICESPEND],0,1); } - if ( bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 ) + if ( bits256_nonz(rswap.privAm) != 0 && bits256_nonz(rswap.privBn) != 0 ) { - if ( (txbytes[BASILISK_BOBSPEND]= basilisk_swap_Aspend("bobspend",alicecoin,Atxfee,alice->wiftaddr,alice->taddr,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_BOBSPEND],alicepaymentaddr)) != 0 ) - printf("bobspend.(%s)\n",txbytes[BASILISK_BOBSPEND]); + if ( (rswap.txbytes[BASILISK_BOBSPEND]= basilisk_swap_Aspend("bobspend",rswap.alicecoin,rswap.Atxfee,alice->wiftaddr,alice->taddr,alice->pubtype,alice->p2shtype,alice->isPoS,alice->wiftype,ctx,rswap.privAm,rswap.privBn,rswap.txids[BASILISK_ALICEPAYMENT],0,rswap.pubkey33,rswap.expiration,&rswap.values[BASILISK_BOBSPEND],rswap.alicepaymentaddr)) != 0 ) + printf("bobspend.(%s)\n",rswap.txbytes[BASILISK_BOBSPEND]); } } - if ( txbytes[BASILISK_BOBSPEND] != 0 ) + if ( rswap.txbytes[BASILISK_BOBSPEND] != 0 ) { - txids[BASILISK_BOBSPEND] = LP_broadcast("bobspend",alicecoin,txbytes[BASILISK_BOBSPEND],zero); - if ( bits256_nonz(txids[BASILISK_BOBSPEND]) != 0 ) // tested + rswap.txids[BASILISK_BOBSPEND] = LP_broadcast("bobspend",rswap.alicecoin,rswap.txbytes[BASILISK_BOBSPEND],zero); + if ( bits256_nonz(rswap.txids[BASILISK_BOBSPEND]) != 0 ) // tested { - sentflags[BASILISK_BOBSPEND] = 1; - Apaymentspent = txids[BASILISK_BOBSPEND]; + rswap.sentflags[BASILISK_BOBSPEND] = 1; + rswap.Apaymentspent = rswap.txids[BASILISK_BOBSPEND]; } } } } - if ( sentflags[BASILISK_BOBRECLAIM] == 0 && sentflags[BASILISK_BOBPAYMENT] != 0 && bits256_nonz(txids[BASILISK_BOBPAYMENT]) != 0 && time(NULL) > expiration && bits256_nonz(paymentspent) == 0 ) + if ( rswap.sentflags[BASILISK_BOBRECLAIM] == 0 && rswap.sentflags[BASILISK_BOBPAYMENT] != 0 && bits256_nonz(rswap.txids[BASILISK_BOBPAYMENT]) != 0 && time(NULL) > rswap.expiration && bits256_nonz(rswap.paymentspent) == 0 ) { //if ( txbytes[BASILISK_BOBRECLAIM] == 0 ) { // bobreclaim - redeemlen = basilisk_swap_bobredeemscript(0,&secretstart,redeemscript,plocktime,pubA0,pubB0,pubB1,zero,privBn,secretAm,secretAm256,secretBn,secretBn256); + redeemlen = basilisk_swap_bobredeemscript(0,&secretstart,redeemscript,rswap.plocktime,rswap.pubA0,rswap.pubB0,rswap.pubB1,zero,rswap.privBn,rswap.secretAm,rswap.secretAm256,rswap.secretBn,rswap.secretBn256); if ( redeemlen > 0 ) { - len = basilisk_swapuserdata(userdata,zero,1,myprivs[1],redeemscript,redeemlen); - if ( (txbytes[BASILISK_BOBRECLAIM]= basilisk_swap_bobtxspend(&signedtxid,Btxfee,"bobrefund",bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[1],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,0,pubkey33,0,expiration,&values[BASILISK_BOBRECLAIM],0,0,bobpaymentaddr,1)) != 0 ) + len = basilisk_swapuserdata(userdata,zero,1,rswap.myprivs[1],redeemscript,redeemlen); + if ( (rswap.txbytes[BASILISK_BOBRECLAIM]= basilisk_swap_bobtxspend(&signedtxid,rswap.Btxfee,"bobrefund",rswap.bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,rswap.myprivs[1],0,redeemscript,redeemlen,userdata,len,rswap.txids[BASILISK_BOBPAYMENT],0,0,rswap.pubkey33,0,rswap.expiration,&rswap.values[BASILISK_BOBRECLAIM],0,0,rswap.bobpaymentaddr,1)) != 0 ) { int32_t z; for (z=0; z<20; z++) - printf("%02x",secretAm[z]); - printf(" secretAm, myprivs[1].(%s) bobreclaim.(%s)\n",bits256_str(str,myprivs[1]),txbytes[BASILISK_BOBRECLAIM]); + printf("%02x",rswap.secretAm[z]); + printf(" secretAm, myprivs[1].(%s) bobreclaim.(%s)\n",bits256_str(str,rswap.myprivs[1]),rswap.txbytes[BASILISK_BOBRECLAIM]); } } } - if ( txbytes[BASILISK_BOBRECLAIM] != 0 ) + if ( rswap.txbytes[BASILISK_BOBRECLAIM] != 0 ) { - txids[BASILISK_BOBRECLAIM] = LP_broadcast("bobreclaim",bobcoin,txbytes[BASILISK_BOBRECLAIM],zero); - if ( bits256_nonz(txids[BASILISK_BOBRECLAIM]) != 0 ) // tested + rswap.txids[BASILISK_BOBRECLAIM] = LP_broadcast("bobreclaim",rswap.bobcoin,rswap.txbytes[BASILISK_BOBRECLAIM],zero); + if ( bits256_nonz(rswap.txids[BASILISK_BOBRECLAIM]) != 0 ) // tested { - sentflags[BASILISK_BOBRECLAIM] = 1; - paymentspent = txids[BASILISK_BOBRECLAIM]; + rswap.sentflags[BASILISK_BOBRECLAIM] = 1; + rswap.paymentspent = rswap.txids[BASILISK_BOBRECLAIM]; } } } - if ( sentflags[BASILISK_BOBREFUND] == 0 && sentflags[BASILISK_BOBDEPOSIT] != 0 && bits256_nonz(txids[BASILISK_BOBDEPOSIT]) != 0 && bits256_nonz(depositspent) == 0 ) + if ( rswap.sentflags[BASILISK_BOBREFUND] == 0 && rswap.sentflags[BASILISK_BOBDEPOSIT] != 0 && bits256_nonz(rswap.txids[BASILISK_BOBDEPOSIT]) != 0 && bits256_nonz(rswap.depositspent) == 0 ) { - if ( bits256_nonz(paymentspent) != 0 || time(NULL) > expiration ) + if ( bits256_nonz(rswap.paymentspent) != 0 || time(NULL) > rswap.expiration ) { printf("do the refund!\n"); //if ( txbytes[BASILISK_BOBREFUND] == 0 ) { - revcalc_rmd160_sha256(secretBn,privBn); - vcalc_sha256(0,secretBn256,privBn.bytes,sizeof(privBn)); - redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,dlocktime,pubA0,pubB0,pubB1,privAm,privBn,secretAm,secretAm256,secretBn,secretBn256); - len = basilisk_swapuserdata(userdata,privBn,0,myprivs[0],redeemscript,redeemlen); - if ( (txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend(&signedtxid,Btxfee,"bobrefund",bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,0,pubkey33,1,expiration,&values[BASILISK_BOBREFUND],0,0,bobdepositaddr,1)) != 0 ) - printf("pubB1.(%s) bobrefund.(%s)\n",bits256_str(str,pubB1),txbytes[BASILISK_BOBREFUND]); + revcalc_rmd160_sha256(rswap.secretBn,rswap.privBn); + vcalc_sha256(0,rswap.secretBn256,rswap.privBn.bytes,sizeof(rswap.privBn)); + redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,rswap.dlocktime,rswap.pubA0,rswap.pubB0,rswap.pubB1,rswap.privAm,rswap.privBn,rswap.secretAm,rswap.secretAm256,rswap.secretBn,rswap.secretBn256); + len = basilisk_swapuserdata(userdata,rswap.privBn,0,rswap.myprivs[0],redeemscript,redeemlen); + if ( (rswap.txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend(&signedtxid,rswap.Btxfee,"bobrefund",rswap.bobcoin,bob->wiftaddr,bob->taddr,bob->pubtype,bob->p2shtype,bob->isPoS,bob->wiftype,ctx,rswap.myprivs[0],0,redeemscript,redeemlen,userdata,len,rswap.txids[BASILISK_BOBDEPOSIT],0,0,rswap.pubkey33,1,rswap.expiration,&rswap.values[BASILISK_BOBREFUND],0,0,rswap.bobdepositaddr,1)) != 0 ) + printf("pubB1.(%s) bobrefund.(%s)\n",bits256_str(str,rswap.pubB1),rswap.txbytes[BASILISK_BOBREFUND]); } - if ( txbytes[BASILISK_BOBREFUND] != 0 ) + if ( rswap.txbytes[BASILISK_BOBREFUND] != 0 ) { - txids[BASILISK_BOBREFUND] = LP_broadcast("bobrefund",bobcoin,txbytes[BASILISK_BOBREFUND],zero); - if ( bits256_nonz(txids[BASILISK_BOBREFUND]) != 0 ) // tested + rswap.txids[BASILISK_BOBREFUND] = LP_broadcast("bobrefund",rswap.bobcoin,rswap.txbytes[BASILISK_BOBREFUND],zero); + if ( bits256_nonz(rswap.txids[BASILISK_BOBREFUND]) != 0 ) // tested { - sentflags[BASILISK_BOBREFUND] = 1; - depositspent = txids[BASILISK_BOBREFUND]; + rswap.sentflags[BASILISK_BOBREFUND] = 1; + rswap.depositspent = rswap.txids[BASILISK_BOBREFUND]; } } - } else printf("bobrefund's time %u vs expiration %u\n",(uint32_t)time(NULL),expiration); + } else printf("bobrefund's time %u vs expiration %u\n",(uint32_t)time(NULL),rswap.expiration); } } } //printf("finish.%d iambob.%d REFUND %d %d %d %d\n",finishedflag,iambob,sentflags[BASILISK_BOBREFUND] == 0,sentflags[BASILISK_BOBDEPOSIT] != 0,bits256_nonz(txids[BASILISK_BOBDEPOSIT]) != 0,bits256_nonz(depositspent) == 0); - if ( sentflags[BASILISK_ALICESPEND] != 0 || sentflags[BASILISK_BOBRECLAIM] != 0 ) - sentflags[BASILISK_BOBPAYMENT] = 1; - if ( sentflags[BASILISK_ALICERECLAIM] != 0 || sentflags[BASILISK_BOBSPEND] != 0 ) - sentflags[BASILISK_ALICEPAYMENT] = 1; - if ( sentflags[BASILISK_ALICECLAIM] != 0 || sentflags[BASILISK_BOBREFUND] != 0 ) - sentflags[BASILISK_BOBDEPOSIT] = 1; + if ( rswap.sentflags[BASILISK_ALICESPEND] != 0 || rswap.sentflags[BASILISK_BOBRECLAIM] != 0 ) + rswap.sentflags[BASILISK_BOBPAYMENT] = 1; + if ( rswap.sentflags[BASILISK_ALICERECLAIM] != 0 || rswap.sentflags[BASILISK_BOBSPEND] != 0 ) + rswap.sentflags[BASILISK_ALICEPAYMENT] = 1; + if ( rswap.sentflags[BASILISK_ALICECLAIM] != 0 || rswap.sentflags[BASILISK_BOBREFUND] != 0 ) + rswap.sentflags[BASILISK_BOBDEPOSIT] = 1; for (i=0; inumswaps; i++) - if ( (swap= myinfo->swaps[i]) != 0 && swap->I.req.requestid == requestid && swap->I.req.quoteid == quoteid ) + for (i=0; i> 32); + q = (uint32_t)G.LP_skipstatus[i]; + if ( r == requestid && q == quoteid ) { - jaddi(array,basilisk_swapjson(swap)); + item = cJSON_CreateObject(); + jaddstr(item,"status","realtime"); + jaddnum(item,"requestid",r); + jaddnum(item,"quoteid",q); + jaddi(array,item); flag = 1; break; - }*/ + } + } if ( flag == 0 ) { if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid)) != 0 ) @@ -1014,7 +1081,7 @@ char *basilisk_swaplist() } jaddstr(retjson,"result","success"); jadd(retjson,"swaps",array); - if ( cJSON_GetArraySize(array) > 0 ) + if ( 0 && cJSON_GetArraySize(array) > 0 ) { totalsobj = cJSON_CreateObject(); for (Btotal=i=0; i 0 ) jaddnum(retjson,"avesell",(double)-Btotal/Ktotal); } - array = cJSON_CreateArray(); - /*for (i=0; ilinfos)/sizeof(*myinfo->linfos); i++) + /*array = cJSON_CreateArray(); + for (i=0; ilinfos)/sizeof(*myinfo->linfos); i++) { if ( myinfo->linfos[i].base[0] != 0 && myinfo->linfos[i].rel[0] != 0 ) jaddi(array,linfo_json(&myinfo->linfos[i])); diff --git a/iguana/exchanges/LP_rpc.c b/iguana/exchanges/LP_rpc.c index 641d547ab..c612cfa3f 100644 --- a/iguana/exchanges/LP_rpc.c +++ b/iguana/exchanges/LP_rpc.c @@ -48,48 +48,37 @@ char *LP_isitme(char *destip,uint16_t destport) } else return(0); } -char *issue_LP_getpeers(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers,int32_t numutxos) +char *issue_LP_getpeers(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers) { char url[512],*retstr; - sprintf(url,"http://%s:%u/api/stats/getpeers?ipaddr=%s&port=%u&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,numpeers,numutxos); + sprintf(url,"http://%s:%u/api/stats/getpeers?ipaddr=%s&port=%u&numpeers=%d",destip,destport,ipaddr,port,numpeers); retstr = LP_issue_curl("getpeers",destip,port,url); //printf("%s -> getpeers.(%s)\n",destip,retstr); return(retstr); } -char *issue_LP_numutxos(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers,int32_t numutxos) +char *issue_LP_uitem(char *destip,uint16_t destport,char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t height,uint64_t value) { - char url[512],*retstr; - sprintf(url,"http://%s:%u/api/stats/numutxos?ipaddr=%s&port=%u&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,numpeers,numutxos); - retstr = LP_issue_curl("numutxos",destip,port,url); - //printf("%s -> getpeers.(%s)\n",destip,retstr); + char url[512],*retstr,str[65]; + if ( (retstr= LP_isitme(destip,destport)) != 0 ) + return(retstr); + sprintf(url,"http://%s:%u/api/stats/uitem?coin=%s&coinaddr=%s&txid=%s&vout=%d&ht=%d&value=%llu",destip,destport,symbol,coinaddr,bits256_str(str,txid),vout,height,(long long)value); + retstr = LP_issue_curl("uitem",destip,destport,url); + //printf("uitem.(%s)\n",retstr); return(retstr); } -char *issue_LP_getutxos(char *destip,uint16_t destport,char *coin,int32_t lastn,char *ipaddr,uint16_t port,int32_t numpeers,int32_t numutxos) -{ - char url[512]; - sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=%s&port=%u&numpeers=%d&numutxos=%d",destip,destport,coin,lastn,ipaddr,port,numpeers,numutxos); - return(LP_issue_curl("getutxos",destip,destport,url)); - //return(issue_curlt(url,LP_HTTP_TIMEOUT)); -} - -char *issue_LP_clientgetutxos(char *destip,uint16_t destport,char *coin,int32_t lastn) +char *issue_LP_notify(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers,uint32_t sessionid,char *rmd160str,bits256 pub) { - char url[512];//,*retstr; - sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=127.0.0.1&port=0",destip,destport,coin,lastn); - return(LP_issue_curl("clientgetutxos",destip,destport,url)); - //retstr = issue_curlt(url,LP_HTTP_TIMEOUT); - //printf("%s clientgetutxos.(%s)\n",url,retstr); - //return(retstr); -} - -char *issue_LP_notify(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers,int32_t numutxos,uint32_t sessionid) -{ - char url[512],*retstr; + char url[512],*retstr,str[65]; if ( (retstr= LP_isitme(destip,destport)) != 0 ) return(retstr); - sprintf(url,"http://%s:%u/api/stats/notify?ipaddr=%s&port=%u&numpeers=%d&numutxos=%d&session=%u",destip,destport,ipaddr,port,numpeers,numutxos,sessionid); + sprintf(url,"http://%s:%u/api/stats/notify?ipaddr=%s&port=%u&numpeers=%d&session=%u",destip,destport,ipaddr,port,numpeers,sessionid); + if ( rmd160str != 0 && bits256_nonz(pub) != 0 ) + { + sprintf(url+strlen(url),"&rmd160=%s&pub=%s",rmd160str,bits256_str(str,pub)); + //printf("SEND (%s)\n",url); + } return(LP_issue_curl("notify",destip,destport,url)); //return(issue_curlt(url,LP_HTTP_TIMEOUT)); } @@ -103,9 +92,19 @@ char *issue_LP_getprices(char *destip,uint16_t destport) //return(issue_curlt(url,LP_HTTP_TIMEOUT)); } +char *issue_LP_listunspent(char *destip,uint16_t destport,char *symbol,char *coinaddr) +{ + char url[512]; + sprintf(url,"http://%s:%u/api/stats/listunspent?coin=%s&address=%s",destip,destport,symbol,coinaddr); + //printf("listunspent.(%s)\n",url); + return(LP_issue_curl("listunspent",destip,destport,url)); +} + char *LP_apicall(struct iguana_info *coin,char *method,char *params) { cJSON *retjson; char *retstr; + if ( coin == 0 ) + return(0); if ( coin->electrum != 0 ) { if ( (retjson= electrum_submit(coin->symbol,coin->electrum,&retjson,method,params,LP_HTTP_TIMEOUT)) != 0 ) @@ -125,6 +124,8 @@ cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params) if ( coin != 0 ) { //printf("issue.(%s, %s, %s, %s, %s)\n",coin->symbol,coin->serverport,coin->userpass,method,params); + if ( coin->electrum != 0 && (strcmp(method,"getblock") == 0 || strcmp(method,"paxprice") == 0 || strcmp(method,"getrawmempool") == 0) ) + return(cJSON_Parse("{\"error\":\"illegal electrum call\"}")); if ( coin->inactive == 0 || strcmp(method,"importprivkey") == 0 || strcmp(method,"validateaddress") == 0 ) { if ( coin->electrum == 0 ) @@ -141,6 +142,11 @@ cJSON *bitcoin_json(struct iguana_info *coin,char *method,char *params) { if ( (retjson= electrum_submit(coin->symbol,coin->electrum,&retjson,method,params,LP_HTTP_TIMEOUT)) != 0 ) { + if ( jobj(retjson,"error") != 0 ) + { + free_json(retjson); + retjson = 0; + } //printf("electrum %s.%s -> (%s)\n",method,params,jprint(retjson,0)); /*if ( (resultjson= jobj(retjson,"result")) != 0 ) { @@ -195,9 +201,10 @@ cJSON *LP_assethbla(char *assetid) int32_t LP_getheight(struct iguana_info *coin) { - cJSON *retjson; char *method = "getinfo"; int32_t height = coin->height; + cJSON *retjson; char *method = "getinfo"; int32_t height; if ( coin == 0 ) return(-1); + height = coin->height; if ( coin->electrum == 0 && time(NULL) > coin->heighttime+60 ) { if ( strcmp(coin->symbol,"BTC") == 0 ) @@ -214,7 +221,10 @@ int32_t LP_getheight(struct iguana_info *coin) cJSON *LP_getmempool(char *symbol,char *coinaddr) { - cJSON *array; struct iguana_info *coin = LP_coinfind(symbol); + cJSON *array; struct iguana_info *coin; + if ( symbol == 0 || symbol[0] == 0 ) + return(cJSON_Parse("{\"error\":\"null symbol\"}")); + coin = LP_coinfind(symbol); if ( coin == 0 || (coin->electrum != 0 && coinaddr == 0) ) return(cJSON_Parse("{\"error\":\"no native coin\"}")); if ( coin->electrum == 0 ) @@ -233,10 +243,14 @@ cJSON *LP_paxprice(char *fiat) cJSON *LP_gettx(char *symbol,bits256 txid) { - char buf[128],str[65],*hexstr; int32_t len; bits256 checktxid; cJSON *retjson; struct iguana_info *coin; struct iguana_msgtx msgtx; uint8_t *extraspace,*serialized; + struct iguana_info *coin; char buf[512],str[65]; cJSON *retjson; + if ( symbol == 0 || symbol[0] == 0 ) + return(cJSON_Parse("{\"error\":\"null symbol\"}")); coin = LP_coinfind(symbol); if ( coin == 0 ) return(cJSON_Parse("{\"error\":\"no coin\"}")); + if ( bits256_nonz(txid) == 0 ) + return(cJSON_Parse("{\"error\":\"null txid\"}")); if ( coin->electrum == 0 ) { sprintf(buf,"[\"%s\", 1]",bits256_str(str,txid)); @@ -244,38 +258,41 @@ cJSON *LP_gettx(char *symbol,bits256 txid) } else { - sprintf(buf,"[\"%s\"]",bits256_str(str,txid)); - if ( (retjson= bitcoin_json(coin,"blockchain.transaction.get",buf)) != 0 ) - { - hexstr = jprint(retjson,1); - if ( hexstr[0] == '"' && hexstr[strlen(hexstr)-1] == '"' ) - hexstr[strlen(hexstr)-1] = 0; - if ( (len= is_hexstr(hexstr+1,0)) > 2 ) - { - memset(&msgtx,0,sizeof(msgtx)); - len = (int32_t)strlen(hexstr+1) >> 1; - serialized = malloc(len); - decode_hex(serialized,len,hexstr+1); - //printf("DATA.(%s)\n",hexstr+1); - extraspace = calloc(1,100000); - retjson = bitcoin_data2json(coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->height,&checktxid,&msgtx,extraspace,100000,serialized,len,0,0); - free(serialized); - free(extraspace); - //printf("TX.(%s) match.%d\n",jprint(retjson,0),bits256_cmp(txid,checktxid)); - return(retjson); - } else printf("non-hex tx.(%s)\n",hexstr); - return(cJSON_Parse("{\"error\":\"non hex transaction\"}")); - } else printf("failed blockcjhain.transaction.get\n"); + if ( (retjson= electrum_transaction(symbol,coin->electrum,&retjson,txid)) != 0 ) + return(retjson); + else printf("failed blockchain.transaction.get %s %s\n",coin->symbol,buf); return(cJSON_Parse("{\"error\":\"no transaction bytes\"}")); } } -cJSON *LP_gettxout(char *symbol,bits256 txid,int32_t vout) +cJSON *LP_gettxout_json(bits256 txid,int32_t vout,int32_t height,char *coinaddr,uint64_t value) { - char buf[128],str[65],coinaddr[64],*hexstr; uint64_t value; uint8_t *serialized; cJSON *sobj,*addresses,*item,*array,*hexobj,*retjson=0; int32_t i,n,v,len; bits256 t; struct iguana_info *coin; - coin = LP_coinfind(symbol); - if ( coin == 0 ) + cJSON *retjson,*addresses,*sobj; + retjson = cJSON_CreateObject(); + jaddnum(retjson,"value",dstr(value)); + jaddnum(retjson,"height",height); + jaddbits256(retjson,"txid",txid); + jaddnum(retjson,"vout",vout); + addresses = cJSON_CreateArray(); + jaddistr(addresses,coinaddr); + sobj = cJSON_CreateObject(); + jaddnum(sobj,"reqSigs",1); + jaddstr(sobj,"type","pubkey"); + jadd(sobj,"addresses",addresses); + jadd(retjson,"scriptPubKey",sobj); + printf("GETTXOUT.(%s)\n",jprint(retjson,0)); + return(retjson); +} + +cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout) +{ + char buf[128],str[65]; cJSON *item,*array,*vouts,*txobj,*retjson=0; int32_t i,v,n; bits256 t; struct iguana_info *coin; struct LP_transaction *tx; struct LP_address_utxo *up; + if ( symbol == 0 || symbol[0] == 0 ) + return(cJSON_Parse("{\"error\":\"null symbol\"}")); + if ( (coin= LP_coinfind(symbol)) == 0 ) return(cJSON_Parse("{\"error\":\"no coin\"}")); + if ( bits256_nonz(txid) == 0 ) + return(cJSON_Parse("{\"error\":\"null txid\"}")); if ( coin->electrum == 0 ) { sprintf(buf,"[\"%s\", %d, true]",bits256_str(str,txid),vout); @@ -283,87 +300,56 @@ cJSON *LP_gettxout(char *symbol,bits256 txid,int32_t vout) } else { - sprintf(buf,"[\"%s\"]",bits256_str(str,txid)); - if ( (hexobj= bitcoin_json(coin,"blockchain.transaction.get",buf)) != 0 ) + if ( (tx= LP_transactionfind(coin,txid)) != 0 && vout < tx->numvouts ) { - hexstr = jprint(hexobj,1); - if ( hexstr[0] == '"' && hexstr[strlen(hexstr)-1] == '"' ) - hexstr[strlen(hexstr)-1] = 0; - if ( (len= is_hexstr(hexstr+1,0)) > 2 ) + if ( tx->outpoints[vout].spendheight > 0 ) + return(0); + return(LP_gettxout_json(txid,vout,tx->height,tx->outpoints[vout].coinaddr,tx->outpoints[vout].value)); + } + if ( coinaddr[0] == 0 ) + { + if ( (txobj= electrum_transaction(symbol,coin->electrum,&txobj,txid)) != 0 ) { - len = (int32_t)strlen(hexstr+1) >> 1; - serialized = malloc(len); - decode_hex(serialized,len,hexstr+1); - LP_swap_coinaddr(coin,coinaddr,&value,serialized,len,vout); - //printf("HEX.(%s) len.%d %s %.8f\n",hexstr+1,len,coinaddr,dstr(value)); - if ( (array= electrum_address_listunspent(coin->symbol,0,&array,coinaddr)) != 0 ) + if ( (vouts= jarray(&n,txobj,"vout")) != 0 && n > 0 ) + LP_destaddr(coinaddr,jitem(vouts,vout)); + free_json(txobj); + } + } + if ( coinaddr[0] != 0 ) + { + if ( (up= LP_address_utxofind(coin,coinaddr,txid,vout)) != 0 ) + { + if ( up->spendheight > 0 ) + return(0); + return(LP_gettxout_json(txid,vout,up->U.height,coinaddr,up->U.value)); + } + if ( (array= electrum_address_listunspent(coin->symbol,0,&array,coinaddr)) != 0 ) + { + //printf("array.(%s)\n",jprint(array,0)); + if ( array != 0 && (n= cJSON_GetArraySize(array)) > 0 ) { - //printf("array.(%s)\n",jprint(array,0)); - if ( array != 0 && (n= cJSON_GetArraySize(array)) > 0 ) + for (i=0; iinactive != 0 ) - return(cJSON_Parse("{\"error\":\"no coin\"}")); - if ( coin->electrum == 0 ) - { - sprintf(buf,"[0, 99999999, [\"%s\"]]",coinaddr); - return(bitcoin_json(coin,"listunspent",buf)); - } else return(electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr)); -} - /*cJSON *LP_listtransactions(char *symbol,char *coinaddr,int32_t count,int32_t skip) { char buf[128]; struct iguana_info *coin = LP_coinfind(symbol); @@ -377,7 +363,10 @@ cJSON *LP_listunspent(char *symbol,char *coinaddr) cJSON *LP_validateaddress(char *symbol,char *address) { - char buf[512],coinaddr[64],checkaddr[64],script[128]; int32_t i; uint8_t rmd160[20],addrtype; cJSON *retjson; struct iguana_info *coin = LP_coinfind(symbol); + char buf[512],coinaddr[64],checkaddr[64],script[128]; int32_t i; uint8_t rmd160[20],addrtype; cJSON *retjson; struct iguana_info *coin; + if ( symbol == 0 || symbol[0] == 0 ) + return(cJSON_Parse("{\"error\":\"null symbol\"}")); + coin = LP_coinfind(symbol); if ( coin == 0 ) return(cJSON_Parse("{\"error\":\"no coin\"}")); if ( coin != 0 && coin->electrum != 0 ) @@ -396,9 +385,8 @@ cJSON *LP_validateaddress(char *symbol,char *address) strcat(script,"88ac"); jaddstr(retjson,"scriptPubKey",script); } - bitcoin_address(coinaddr,coin->taddr,coin->pubtype,LP_myrmd160,20); - if ( strcmp(address,coinaddr) == 0 ) - jadd(retjson,"ismine",cJSON_CreateTrue()); + bitcoin_address(coinaddr,coin->taddr,coin->pubtype,G.LP_myrmd160,20); + jadd(retjson,"ismine",strcmp(address,coin->smartaddr) == 0 ? cJSON_CreateTrue() : cJSON_CreateFalse()); jadd(retjson,"iswatchonly",cJSON_CreateFalse()); jadd(retjson,"isscript",addrtype == coin->p2shtype ? cJSON_CreateTrue() : cJSON_CreateFalse()); return(retjson); @@ -410,10 +398,94 @@ cJSON *LP_validateaddress(char *symbol,char *address) } } +int32_t LP_address_ismine(char *symbol,char *address) +{ + int32_t doneflag = 0; cJSON *retjson; + if ( symbol == 0 || symbol[0] == 0 ) + return(0); + if ( (retjson= LP_validateaddress(symbol,address)) != 0 ) + { + if ( jobj(retjson,"ismine") != 0 && is_cJSON_True(jobj(retjson,"ismine")) != 0 ) + { + doneflag = 1; + //printf("%s ismine (%s)\n",address,jprint(retjson,0)); + } + //printf("%s\n",jprint(retjson,0)); + free_json(retjson); + } + return(doneflag); +} + +cJSON *LP_listunspent(char *symbol,char *coinaddr) +{ + char buf[128]; cJSON *retjson; struct iguana_info *coin; + if ( symbol == 0 || symbol[0] == 0 ) + return(cJSON_Parse("{\"error\":\"null symbol\"}")); + coin = LP_coinfind(symbol); + //printf("LP_listunspent.(%s %s)\n",symbol,coinaddr); + if ( coin == 0 || coin->inactive != 0 ) + return(cJSON_Parse("{\"error\":\"no coin\"}")); + if ( coin->electrum == 0 ) + { + if ( LP_address_ismine(symbol,coinaddr) > 0 ) + { + sprintf(buf,"[0, 99999999, [\"%s\"]]",coinaddr); + return(bitcoin_json(coin,"listunspent",buf)); + } else return(LP_address_utxos(coin,coinaddr,0)); + } else return(electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr)); +} + +int32_t LP_listunspent_issue(char *symbol,char *coinaddr) +{ + struct iguana_info *coin; int32_t n = 0; cJSON *retjson=0; char *retstr=0,destip[64]; uint16_t destport; + if ( symbol == 0 || symbol[0] == 0 ) + return(0); + if ( (coin= LP_coinfind(symbol)) != 0 ) + { + if ( coin->electrum != 0 ) + { + if ( (retjson= electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr)) != 0 ) + { + n = cJSON_GetArraySize(retjson); + //printf("LP_listunspent_issue.%s %s.%d %s\n",symbol,coinaddr,n,jprint(retjson,0)); + } + } + else + { + if ( strcmp(coin->smartaddr,coinaddr) == 0 ) + { + retjson = LP_listunspent(symbol,coinaddr); + //printf("SELF_LISTUNSPENT.(%s %s)\n",symbol,coinaddr); + } + else if ( (destport= LP_randpeer(destip)) > 0 ) + { + retstr = issue_LP_listunspent(destip,destport,symbol,coinaddr); + retjson = cJSON_Parse(retstr); + } else printf("LP_listunspent_issue couldnt get a random peer?\n"); + if ( retjson != 0 ) + { + n = cJSON_GetArraySize(retjson); + if ( electrum_process_array(coin,0,coinaddr,retjson) != 0 ) + { + //LP_postutxos(symbol,coinaddr); // might be good to not saturate + } + } + } + //printf("issue listunspent %s (%s)\n",coinaddr,jprint(retjson,0)); + if ( retjson != 0 ) + free_json(retjson); + if ( retstr != 0 ) + free(retstr); + } + return(n); +} + cJSON *LP_importprivkey(char *symbol,char *wifstr,char *label,int32_t flag) { static void *ctx; char buf[512],address[64]; cJSON *retjson; struct iguana_info *coin; int32_t doneflag = 0; + if ( symbol == 0 || symbol[0] == 0 ) + return(cJSON_Parse("{\"error\":\"null symbol\"}")); coin = LP_coinfind(symbol); if ( coin == 0 ) return(cJSON_Parse("{\"error\":\"no coin\"}")); @@ -443,16 +515,19 @@ cJSON *LP_importprivkey(char *symbol,char *wifstr,char *label,int32_t flag) int32_t LP_importaddress(char *symbol,char *address) { - char buf[1024],*retstr; cJSON *validatejson,*retjson; int32_t isvalid=0,doneflag = 0; struct iguana_info *coin = LP_coinfind(symbol); + char buf[1024],*retstr; cJSON *validatejson; int32_t isvalid=0,doneflag = 0; struct iguana_info *coin; + if ( symbol == 0 || symbol[0] == 0 ) + return(-2); + coin = LP_coinfind(symbol); if ( coin == 0 ) return(-2); if ( coin->electrum != 0 ) { - if ( (retjson= electrum_address_subscribe(symbol,coin->electrum,&retjson,address)) != 0 ) + /*if ( (retjson= electrum_address_subscribe(symbol,coin->electrum,&retjson,address)) != 0 ) { printf("importaddress.(%s) -> %s\n",address,jprint(retjson,0)); free_json(retjson); - } + }*/ return(0); } else @@ -480,37 +555,54 @@ int32_t LP_importaddress(char *symbol,char *address) } } -double LP_getestimatedrate(struct iguana_info *coin) +double _LP_getestimatedrate(struct iguana_info *coin) { - char buf[512],*retstr; double rate = 0.00000020; - if ( coin == 0 ) - return(0.0001); - if ( (strcmp(coin->symbol,"BTC") == 0 || coin->txfee == 0) ) + char buf[512],*retstr; cJSON *errjson; double rate = 0.00000020; + if ( coin->rate < 0. || time(NULL) > coin->ratetime+30 ) { - if ( coin->rate == 0. || time(NULL) > coin->ratetime+600 ) + sprintf(buf,"[%d]",strcmp(coin->symbol,"BTC") == 0 ? 6 : 2); + if ( (retstr= LP_apicall(coin,coin->electrum==0?"estimatefee" : "blockchain.estimatefee",buf)) != 0 ) { - sprintf(buf,"[%d]",3); - if ( (retstr= LP_apicall(coin,coin->electrum==0?"estimatefee" : "blockchain.estimatefee",buf)) != 0 ) + if ( retstr[0] == '{' && (errjson= cJSON_Parse(retstr)) != 0 ) { - if ( retstr[0] != '-' ) - { - rate = atof(retstr) / 1024.; - if ( rate < 0.00000020 ) - rate = 0.00000020; - coin->rate = rate; - coin->ratetime = (uint32_t)time(NULL); - printf("estimated rate.(%s) %s -> %.8f\n",coin->symbol,retstr,rate); - } - free(retstr); + if ( jobj(errjson,"error") != 0 ) + rate = 0.; + free_json(errjson); } - } else rate = coin->rate; - } else return((double)coin->txfee / LP_AVETXSIZE); - return(SATOSHIDEN * rate); + else if ( retstr[0] != '-' ) + { + rate = atof(retstr) / 1024.; + if ( rate < 0.00000020 ) + rate = 0.00000020; + rate *= 1.1; + if ( coin->electrum != 0 ) + rate *= 1.667; + if ( fabs(rate - coin->rate) > SMALLVAL ) + printf("t%u estimated rate.(%s) (%s) -> %.8f %.8f\n",coin->ratetime,coin->symbol,retstr,rate,coin->rate); + coin->rate = rate; + coin->ratetime = (uint32_t)time(NULL); + } + free(retstr); + } + } else rate = coin->rate; + return(rate); +} + +double LP_getestimatedrate(struct iguana_info *coin) +{ + double rate = 0.00000020; + if ( coin == 0 ) + return(rate); + if ( (rate= _LP_getestimatedrate(coin)) <= 0. ) + rate = dstr(coin->txfee) / LP_AVETXSIZE; + return(rate); } char *LP_sendrawtransaction(char *symbol,char *signedtx) { - cJSON *array; char *paramstr,*tmpstr,*retstr=0; int32_t n; cJSON *retjson; struct iguana_info *coin; + cJSON *array,*errobj; char *paramstr,*tmpstr,*retstr=0; int32_t n,alreadyflag = 0; cJSON *retjson; struct iguana_info *coin; + if ( symbol == 0 || symbol[0] == 0 ) + return(0); coin = LP_coinfind(symbol); if ( coin == 0 ) return(0); @@ -528,14 +620,27 @@ char *LP_sendrawtransaction(char *symbol,char *signedtx) if ( (retjson= electrum_sendrawtransaction(symbol,coin->electrum,&retjson,signedtx)) != 0 ) { retstr = jprint(retjson,1); - printf("electrum sendrawtx.(%s) -> %s\n",signedtx,retstr); - n = (int32_t)strlen(retstr); - if ( retstr[0] == '"' && retstr[n-1] == '"' ) + //electrum sendrawtx (the transaction was rejected by network rules.\n\ntransaction already in block chain) + if ( strstr(retstr,"already in block") != 0 ) + alreadyflag = 1; + //printf("electrum sendrawtx.(%s) -> %s already.%d\n",signedtx,retstr,alreadyflag); + if ( alreadyflag != 0 ) + { + errobj = cJSON_CreateObject(); + jaddstr(errobj,"error","rejected"); + jaddnum(errobj,"code",-27); + retstr = jprint(errobj,1); + } + else { - retstr[n-1] = 0; - tmpstr = clonestr(retstr+1); - free(retstr); - retstr = tmpstr; + n = (int32_t)strlen(retstr); + if ( retstr[0] == '"' && retstr[n-1] == '"' ) + { + retstr[n-1] = 0; + tmpstr = clonestr(retstr+1); + free(retstr); + retstr = tmpstr; + } } } } @@ -544,7 +649,10 @@ char *LP_sendrawtransaction(char *symbol,char *signedtx) char *LP_signrawtx(char *symbol,bits256 *signedtxidp,int32_t *completedp,cJSON *vins,char *rawtx,cJSON *privkeys,struct vin_info *V) { - cJSON *array,*json,*retjson; int32_t len; uint8_t *data; char str[65],*paramstr,*retstr,*hexstr,*signedtx=0; struct iguana_msgtx msgtx; struct iguana_info *coin = LP_coinfind(symbol); + cJSON *array,*json,*retjson; int32_t len; uint8_t *data; char str[65],*paramstr,*retstr,*hexstr,*signedtx=0; struct iguana_msgtx msgtx; struct iguana_info *coin; + if ( symbol == 0 || symbol[0] == 0 ) + return(0); + coin = LP_coinfind(symbol); memset(signedtxidp,0,sizeof(*signedtxidp)); *completedp = 0; if ( coin == 0 ) @@ -594,9 +702,10 @@ char *LP_signrawtx(char *symbol,bits256 *signedtxidp,int32_t *completedp,cJSON * signedtx = calloc(1,len+1); strcpy(signedtx,hexstr); *completedp = is_cJSON_True(jobj(json,"complete")); - data = malloc(len >> 1); - decode_hex(data,len>>1,hexstr); - *signedtxidp = bits256_doublesha256(0,data,len >> 1); + len >>= 1; + data = malloc(len); + decode_hex(data,len,hexstr); + *signedtxidp = bits256_doublesha256(0,data,len); } //else printf("%s signrawtransaction.(%s) params.(%s)\n",coin->symbol,retstr,paramstr); @@ -610,7 +719,10 @@ char *LP_signrawtx(char *symbol,bits256 *signedtxidp,int32_t *completedp,cJSON * cJSON *LP_getblock(char *symbol,bits256 txid) { - char buf[128],str[65]; struct iguana_info *coin = LP_coinfind(symbol); + char buf[128],str[65]; struct iguana_info *coin; + if ( symbol == 0 || symbol[0] == 0 ) + return(cJSON_Parse("{\"error\":\"null symbol\"}")); + coin = LP_coinfind(symbol); if ( coin == 0 || coin->electrum != 0 ) return(cJSON_Parse("{\"error\":\"no native coin\"}")); sprintf(buf,"[\"%s\"]",bits256_str(str,txid)); @@ -621,6 +733,8 @@ cJSON *LP_getblock(char *symbol,bits256 txid) uint64_t LP_txfee(char *symbol) { uint64_t txfee = 0; + if ( symbol == 0 || symbol[0] == 0 ) + return(LP_MIN_TXFEE); if ( strcmp(symbol,"BTC") != 0 ) txfee = LP_MIN_TXFEE; return(txfee); @@ -628,7 +742,10 @@ uint64_t LP_txfee(char *symbol) char *LP_blockhashstr(char *symbol,int32_t height) { - cJSON *array; char *paramstr,*retstr; struct iguana_info *coin = LP_coinfind(symbol); + cJSON *array; char *paramstr,*retstr; struct iguana_info *coin; + if ( symbol == 0 || symbol[0] == 0 ) + return(0); + coin = LP_coinfind(symbol); if ( coin == 0 || coin->electrum != 0 ) return(0); array = cJSON_CreateArray(); @@ -641,7 +758,10 @@ char *LP_blockhashstr(char *symbol,int32_t height) cJSON *LP_getblockhashstr(char *symbol,char *blockhashstr) { - char buf[128]; struct iguana_info *coin = LP_coinfind(symbol); + char buf[128]; struct iguana_info *coin; + if ( symbol == 0 || symbol[0] == 0 ) + return(cJSON_Parse("{\"error\":\"null symbol\"}")); + coin = LP_coinfind(symbol); if ( coin == 0 || coin->electrum != 0 ) return(cJSON_Parse("{\"error\":\"no native coin daemon\"}")); sprintf(buf,"[\"%s\"]",blockhashstr); @@ -650,7 +770,10 @@ cJSON *LP_getblockhashstr(char *symbol,char *blockhashstr) cJSON *LP_blockjson(int32_t *heightp,char *symbol,char *blockhashstr,int32_t height) { - cJSON *json = 0; int32_t flag = 0; struct iguana_info *coin = LP_coinfind(symbol); + cJSON *json = 0; int32_t flag = 0; struct iguana_info *coin; + if ( symbol == 0 || symbol[0] == 0 ) + return(cJSON_Parse("{\"error\":\"null symbol\"}")); + coin = LP_coinfind(symbol); if ( coin == 0 || coin->electrum != 0 ) { printf("unexpected electrum path for %s\n",symbol); diff --git a/iguana/exchanges/LP_scan.c b/iguana/exchanges/LP_scan.c index ddd95f458..23e76098e 100644 --- a/iguana/exchanges/LP_scan.c +++ b/iguana/exchanges/LP_scan.c @@ -21,42 +21,31 @@ int32_t LP_blockinit(struct iguana_info *coin,int32_t height) { - int32_t i,j,iter,numtx,checkht=-1; cJSON *blockobj,*txs; bits256 txid; struct LP_transaction *tx; + int32_t i,iter,numtx,checkht=-1; cJSON *blockobj,*txs,*txobj; bits256 txid; struct LP_transaction *tx; if ( (blockobj= LP_blockjson(&checkht,coin->symbol,0,height)) != 0 && checkht == height ) { if ( (txs= jarray(&numtx,blockobj,"tx")) != 0 ) { for (iter=0; iter<2; iter++) - for (i=0; iheight == 0 ) - tx->height = height; - else if ( tx->height != height ) + txid = jbits256i(txs,i); + if ( (tx= LP_transactionfind(coin,txid)) != 0 ) { - printf("LP_blockinit: tx->height %d != %d\n",tx->height,height); - tx->height = height; - } - if ( iter == 1 ) - for (j=0; j<10; j++) + if ( tx->height == 0 ) + tx->height = height; + else if ( tx->height != height ) { - if (LP_transactioninit(coin,txid,iter) == 0 ) - break; - printf("transaction ht.%d init error.%d, pause\n",height,j); - sleep(1); + printf("LP_blockinit: tx->height %d != %d\n",tx->height,height); + tx->height = height; } - } - else - { - for (j=0; j<10; j++) - { - if (LP_transactioninit(coin,txid,iter) == 0 ) - break; - printf("transaction ht.%d init error.%d, pause\n",height,j); - sleep(1); - } + if ( iter == 1 ) + txobj = LP_transactioninit(coin,txid,iter,0); + } else txobj = LP_transactioninit(coin,txid,iter,0); + if ( txobj != 0 ) + free_json(txobj), txobj = 0; } } } @@ -184,6 +173,7 @@ cJSON *LP_snapshot(struct iguana_info *coin,int32_t height) } } portable_mutex_lock(&coin->txmutex); + portable_mutex_lock(&coin->addrmutex); HASH_ITER(hh,coin->addresses,ap,atmp) { ap->balance = 0; @@ -220,6 +210,7 @@ cJSON *LP_snapshot(struct iguana_info *coin,int32_t height) } } HASH_SORT(coin->addresses,sort_balance); + portable_mutex_unlock(&coin->addrmutex); portable_mutex_unlock(&coin->txmutex); printf("%s balance %.8f at height.%d\n",coin->symbol,dstr(balance),height); array = cJSON_CreateArray(); @@ -421,7 +412,7 @@ int32_t LP_spendsearch(bits256 *spendtxidp,int32_t *indp,char *symbol,bits256 se int32_t LP_mempoolscan(char *symbol,bits256 searchtxid) { - int32_t i,n; cJSON *array; bits256 txid; struct iguana_info *coin; struct LP_transaction *tx; + int32_t i,n; cJSON *array,*txobj; bits256 txid; struct iguana_info *coin; struct LP_transaction *tx; if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 || coin->electrum != 0 ) return(-1); if ( (array= LP_getmempool(symbol,0)) != 0 ) @@ -433,8 +424,10 @@ int32_t LP_mempoolscan(char *symbol,bits256 searchtxid) txid = jbits256i(array,i); if ( (tx= LP_transactionfind(coin,txid)) == 0 ) { - LP_transactioninit(coin,txid,0); - LP_transactioninit(coin,txid,1); + txobj = LP_transactioninit(coin,txid,0,0); + txobj = LP_transactioninit(coin,txid,1,txobj); + if ( txobj != 0 ) + free_json(txobj); } if ( bits256_cmp(txid,searchtxid) == 0 ) { @@ -448,49 +441,65 @@ int32_t LP_mempoolscan(char *symbol,bits256 searchtxid) return(-1); } -int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t duration) +int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t duration) { - struct iguana_info *coin; struct LP_transaction *tx; cJSON *array,*item; uint32_t expiration,i,n; + struct iguana_info *coin; cJSON *array,*item; uint32_t expiration,i,n; int32_t numconfirms = -1; if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) + { + printf("LP_waitmempool missing coin.%p or inactive\n",coin); return(-1); + } expiration = (uint32_t)time(NULL) + duration; while ( 1 ) { - if ( coin->electrum == 0 ) - { - if ( LP_mempoolscan(symbol,txid) >= 0 ) - return(0); - } + if ( LP_gettx_presence(symbol,txid) != 0 ) + numconfirms = 0; else { - if ( (tx= LP_transactionfind(coin,txid)) != 0 && tx->height >= 0 ) + if ( coin->electrum == 0 ) { - char str[65]; printf("LP_waitmempool found %s %s\n",symbol,bits256_str(str,txid)); - return(tx->height); + if ( LP_mempoolscan(symbol,txid) >= 0 ) + numconfirms = 0; } - if ( (array= electrum_address_getmempool(symbol,coin->electrum,&array,coinaddr)) != 0 ) + else { - if ( (n= cJSON_GetArraySize(array)) > 0 ) + if ( (array= electrum_address_getmempool(symbol,coin->electrum,&array,coinaddr)) != 0 ) { - for (i=0; i 0 ) { - item = jitem(array,i); - if ( bits256_cmp(txid,jbits256(item,"tx_hash")) == 0 ) + for (i=0; isymbol,coinaddr); + struct LP_address_utxo *up; + if ( (up= LP_address_utxofind(coin,coinaddr,txid,vout)) != 0 ) + { + char str[65]; printf("address_utxofind found confirmed %s %s %s ht.%d vs %d\n",symbol,coinaddr,bits256_str(str,txid),up->U.height,coin->height); + if ( coin->electrum != 0 && (array= electrum_address_gethistory(symbol,coin->electrum,&array,coinaddr)) != 0 ) + free_json(array); + if ( coin->height >= up->U.height ) + numconfirms = (coin->height - up->U.height + 1); } - free(array); } } - if ( time(NULL) < expiration ) + if ( time(NULL) > expiration || numconfirms >= 0 ) break; - usleep(500000); + sleep(10); } - return(-1); + //if ( numconfirms <= 0 ) + // numconfirms = LP_numconfirms(symbol,coinaddr,txid,vout,1); // no, no recursion occurs! + return(numconfirms); } int32_t LP_mempool_vinscan(bits256 *spendtxidp,int32_t *spendvinp,char *symbol,char *coinaddr,bits256 searchtxid,int32_t searchvout,bits256 searchtxid2,int32_t searchvout2) diff --git a/iguana/exchanges/LP_socket.c b/iguana/exchanges/LP_socket.c index 2866205a8..e4727bada 100644 --- a/iguana/exchanges/LP_socket.c +++ b/iguana/exchanges/LP_socket.c @@ -26,7 +26,7 @@ #include #endif -#define ELECTRUM_TIMEOUT 3 +#define ELECTRUM_TIMEOUT 5 int32_t LP_socket(int32_t bindflag,char *hostname,uint16_t port) { @@ -198,7 +198,7 @@ int32_t LP_socketsend(int32_t sock,uint8_t *serialized,int32_t len) flags = MSG_NOSIGNAL; #endif remains = len; - while ( remains > 0 ) + while ( sock >= 0 && remains > 0 ) { if ( (numsent= (int32_t)send(sock,serialized,remains,flags)) < 0 ) { @@ -225,7 +225,7 @@ int32_t LP_socketsend(int32_t sock,uint8_t *serialized,int32_t len) int32_t LP_socketrecv(int32_t sock,uint8_t *recvbuf,int32_t maxlen) { int32_t recvlen = -1; - while ( 1 ) + while ( sock >= 0 ) { if ( (recvlen= (int32_t)recv(sock,recvbuf,maxlen,0)) < 0 ) { @@ -243,6 +243,7 @@ int32_t LP_socketrecv(int32_t sock,uint8_t *recvbuf,int32_t maxlen) struct electrum_info { queue_t sendQ,pendingQ; + struct electrum_info *prev; int32_t bufsize,sock,*heightp; struct iguana_info *coin; uint32_t stratumid,lasttime,pending,*heighttimep; @@ -252,16 +253,6 @@ struct electrum_info } *Electrums[8192]; int32_t Num_electrums; -// purge timedout -/* -if ( (retjson= electrum_address_listunspent(symbol,ep,&retjson,addr)) != 0 ) -you can call it like the above, where symbol is the coin, ep is the electrum server info pointer, the 0 is a callback ptr where 0 means to block till it is done -all the API calls have the same three args -if the callback ptr is &retjson, then on completion it will put the cJSON *ptr into it, so to spawn a bunch of calls you need to call with symbol,ep,&retjsons[i],... -default timeout is set to 2 seconds, not sure if that is enough, on each receive from any server, requests that are timeout are purged (and if a callback set, will just return and "error" timeout JSON -a null value for ep will make it choose a random server for that coin - */ - struct electrum_info *electrum_server(char *symbol,struct electrum_info *ep) { struct electrum_info *rbuf[128],*recent_ep; uint32_t recent,mostrecent = 0; int32_t i,n = 0; @@ -304,41 +295,67 @@ struct electrum_info *electrum_server(char *symbol,struct electrum_info *ep) return(ep); } -void electrum_process_array(struct iguana_info *coin,cJSON *array) +int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep,char *coinaddr,cJSON *array) { - int32_t i,v,n; char str[65]; uint64_t value; bits256 txid; cJSON *item; struct LP_transaction *tx; + int32_t i,v,n,ht,flag = 0; char str[65]; uint64_t value; bits256 txid; cJSON *item,*retjson,*txobj; struct LP_transaction *tx; if ( array != 0 && coin != 0 && (n= cJSON_GetArraySize(array)) > 0 ) { + //printf("PROCESS %s/%s %s num.%d\n",coin->symbol,ep!=0?ep->symbol:"nanolistunspent",coinaddr,n); for (i=0; ielectrum == 0 ) + { + txid = jbits256(item,"txid"); + v = jint(item,"vout"); + value = LP_value_extract(item,0); + ht = LP_txheight(coin,txid); + if ( (retjson= LP_gettxout(coin->symbol,coinaddr,txid,v)) != 0 ) + free_json(retjson); + else + { + //printf("external unspent has no gettxout\n"); + flag += LP_address_utxoadd(coin,coinaddr,txid,v,value,0,1); + } + } + else + { + txid = jbits256(item,"tx_hash"); + v = jint(item,"tx_pos"); + value = j64bits(item,"value"); + ht = jint(item,"height"); + } + if ( bits256_nonz(txid) == 0 ) + continue; if ( (tx= LP_transactionfind(coin,txid)) == 0 ) { - LP_transactioninit(coin,txid,0); - LP_transactioninit(coin,txid,1); + txobj = LP_transactioninit(coin,txid,0,0); + LP_transactioninit(coin,txid,1,txobj); + free_json(txobj); tx = LP_transactionfind(coin,txid); } if ( tx != 0 ) { if (tx->height <= 0 ) { - tx->height = jint(item,"height"); - printf(">>>>>>>>>> set %s <- height %d\n",bits256_str(str,txid),tx->height); + tx->height = ht; + //printf("%s %s >>>>>>>>>> set %s <- height %d\n",coin->symbol,coinaddr,bits256_str(str,txid),tx->height); } - if ( jobj(item,"tx_pos") != 0 && jobj(item,"value") != 0 && (v= jint(item,"tx_pos")) >= 0 && v < tx->numvouts ) + if ( v >= 0 && v < tx->numvouts ) { - value = j64bits(item,"value"); if ( tx->outpoints[v].value == 0 && value != tx->outpoints[v].value ) { - printf(">>>>>>>>>> set %s/v%d <- %.8f vs %.8f\n",bits256_str(str,txid),v,dstr(value),dstr(tx->outpoints[v].value)); + printf("%s %s >>>>>>>>>> set %s/v%d <- %.8f vs %.8f\n",coin->symbol,coinaddr,bits256_str(str,txid),v,dstr(value),dstr(tx->outpoints[v].value)); tx->outpoints[v].value = value; } } - printf("v.%d numvouts.%d %.8f (%s)\n",jint(item,"tx_pos"),tx->numvouts,dstr(tx->outpoints[jint(item,"tx_pos")].value),jprint(item,0)); - } + if ( value != 0 || tx->height > 0 ) + flag += LP_address_utxoadd(coin,coinaddr,txid,v,value,tx->height,-1); + //printf("v.%d numvouts.%d %.8f (%s)\n",v,tx->numvouts,dstr(tx->outpoints[jint(item,"tx_pos")].value),jprint(item,0)); + } //else printf("cant find tx\n"); } } + return(flag); } cJSON *electrum_submit(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *method,char *params,int32_t timeout) @@ -347,31 +364,33 @@ cJSON *electrum_submit(char *symbol,struct electrum_info *ep,cJSON **retjsonp,ch char stratumreq[16384]; uint32_t expiration; struct stritem *sitem; if ( ep == 0 ) ep = electrum_server(symbol,0); - if ( ep != 0 && retjsonp != 0 ) + while ( ep != 0 ) { - *retjsonp = 0; - if ( strcmp(method,"getrawmempool") == 0 ) - { - *retjsonp = cJSON_Parse("{\"error\":\"unsupported method\"}"); - return(*retjsonp); - } - sprintf(stratumreq,"{ \"jsonrpc\":\"2.0\", \"id\": %u, \"method\":\"%s\", \"params\": %s }\n",ep->stratumid,method,params); - ep->buf[0] = 0; - sitem = (struct stritem *)queueitem(stratumreq); - sitem->expiration = timeout; - sitem->DL.type = ep->stratumid++; - sitem->retptrp = (void **)retjsonp; - queue_enqueue("sendQ",&ep->sendQ,&sitem->DL); - expiration = (uint32_t)time(NULL) + timeout + 1; - while ( *retjsonp == 0 && time(NULL) <= expiration ) - usleep(10000); - if ( *retjsonp == 0 ) + if ( ep != 0 && ep->sock >= 0 && retjsonp != 0 ) { - printf("unexpected timeout with null retjson: %s %s\n",method,params); - *retjsonp = cJSON_Parse("{\"error\":\"timeout\"}"); - } - return(*retjsonp); - } else printf("couldnt find electrum server for (%s %s) or no retjsonp.%p\n",method,params,retjsonp); + *retjsonp = 0; + sprintf(stratumreq,"{ \"jsonrpc\":\"2.0\", \"id\": %u, \"method\":\"%s\", \"params\": %s }\n",ep->stratumid,method,params); + memset(ep->buf,0,ep->bufsize); + sitem = (struct stritem *)queueitem(stratumreq); + sitem->expiration = timeout; + sitem->DL.type = ep->stratumid++; + sitem->retptrp = (void **)retjsonp; + queue_enqueue("sendQ",&ep->sendQ,&sitem->DL); + expiration = (uint32_t)time(NULL) + timeout + 1; + while ( *retjsonp == 0 && time(NULL) <= expiration ) + usleep(10000); + if ( ep->prev == 0 ) + { + if ( *retjsonp == 0 ) + { + //printf("unexpected %s timeout with null retjson: %s %s\n",ep->symbol,method,params); + *retjsonp = cJSON_Parse("{\"error\":\"timeout\"}"); + } + return(*retjsonp); + } + } else printf("couldnt find electrum server for (%s %s) or no retjsonp.%p\n",method,params,retjsonp); + ep = ep->prev; + } return(0); } @@ -413,8 +432,6 @@ cJSON *electrum_hasharg(char *symbol,struct electrum_info *ep,cJSON **retjsonp,c return(electrum_submit(symbol,ep,retjsonp,method,params,timeout)); } -//" "--blockchain.numblocks.subscribe", "--blockchain.address.get_proof", "--blockchain.utxo.get_address", - cJSON *electrum_version(char *symbol,struct electrum_info *ep,cJSON **retjsonp) { return(electrum_noargs(symbol,ep,retjsonp,"server.version",ELECTRUM_TIMEOUT)); } cJSON *electrum_banner(char *symbol,struct electrum_info *ep,cJSON **retjsonp) { return(electrum_noargs(symbol,ep,retjsonp,"server.banner",ELECTRUM_TIMEOUT)); } cJSON *electrum_donation(char *symbol,struct electrum_info *ep,cJSON **retjsonp) { return(electrum_noargs(symbol,ep,retjsonp,"server.donation_address",ELECTRUM_TIMEOUT)); } @@ -440,10 +457,34 @@ cJSON *electrum_address_subscribe(char *symbol,struct electrum_info *ep,cJSON ** cJSON *electrum_address_gethistory(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr) { - cJSON *retjson; struct iguana_info *coin = LP_coinfind(symbol); + struct LP_transaction *tx; cJSON *retjson,*txobj,*item; int32_t i,n,height; bits256 txid; struct iguana_info *coin = LP_coinfind(symbol); retjson = electrum_strarg(symbol,ep,retjsonp,"blockchain.address.get_history",addr,ELECTRUM_TIMEOUT); - printf("history.(%s)\n",jprint(retjson,0)); - electrum_process_array(coin,retjson); + //printf("history.(%s)\n",jprint(retjson,0)); + if ( retjson != 0 && (n= cJSON_GetArraySize(retjson)) > 0 ) + { + for (i=0; i 0 ) + { + if ( (tx= LP_transactionfind(coin,txid)) != 0 ) + { + tx->height = height; + LP_address_utxoadd(coin,addr,txid,0,0,height,-1); + } + } + } + } + } return(retjson); } @@ -451,25 +492,26 @@ cJSON *electrum_address_getmempool(char *symbol,struct electrum_info *ep,cJSON * { cJSON *retjson; struct iguana_info *coin = LP_coinfind(symbol); retjson = electrum_strarg(symbol,ep,retjsonp,"blockchain.address.get_mempool",addr,ELECTRUM_TIMEOUT); - printf("MEMPOOL.(%s)\n",jprint(retjson,0)); - electrum_process_array(coin,retjson); + //printf("MEMPOOL.(%s)\n",jprint(retjson,0)); + electrum_process_array(coin,ep,addr,retjson); return(retjson); } cJSON *electrum_address_listunspent(char *symbol,struct electrum_info *ep,cJSON **retjsonp,char *addr) { cJSON *retjson=0; struct iguana_info *coin = LP_coinfind(symbol); - //printf("electrum listunspent last.(%s lag %d)\n",coin->lastunspent,(int32_t)(time(NULL) - coin->unspenttime)); - //if ( strcmp(coin->lastunspent,addr) != 0 || time(NULL) > coin->unspenttime+10 ) + //printf("electrum.%s/%s listunspent last.(%s lag %d)\n",ep->symbol,coin->symbol,coin->lastunspent,(int32_t)(time(NULL) - coin->unspenttime)); + if ( 1 || strcmp(coin->lastunspent,addr) != 0 || time(NULL) > coin->unspenttime+30 ) { if ( (retjson= electrum_strarg(symbol,ep,retjsonp,"blockchain.address.listunspent",addr,ELECTRUM_TIMEOUT)) != 0 ) { - printf("LISTUNSPENT.(%s)\n",jprint(retjson,0)); - electrum_process_array(coin,retjson); - strcpy(coin->lastunspent,addr); + //printf("LISTUNSPENT.(%s)\n",jprint(retjson,0)); + if ( electrum_process_array(coin,ep,addr,retjson) != 0 ) + LP_postutxos(coin->symbol,addr); + safecopy(coin->lastunspent,addr,sizeof(coin->lastunspent)); coin->unspenttime = (uint32_t)time(NULL); } - } + } else retjson = LP_address_utxos(coin,addr,1); return(retjson); } @@ -485,18 +527,94 @@ cJSON *electrum_estimatefee(char *symbol,struct electrum_info *ep,cJSON **retjso cJSON *electrum_getheader(char *symbol,struct electrum_info *ep,cJSON **retjsonp,int32_t n) { return(electrum_intarg(symbol,ep,retjsonp,"blockchain.block.get_header",n,ELECTRUM_TIMEOUT)); } cJSON *electrum_getchunk(char *symbol,struct electrum_info *ep,cJSON **retjsonp,int32_t n) { return(electrum_intarg(symbol,ep,retjsonp,"blockchain.block.get_chunk",n,ELECTRUM_TIMEOUT)); } +cJSON *LP_transaction_fromdata(struct iguana_info *coin,bits256 txid,uint8_t *serialized,int32_t len) +{ + uint8_t *extraspace; cJSON *txobj; char str[65],str2[65]; struct iguana_msgtx msgtx; bits256 checktxid; + extraspace = calloc(1,1000000); + memset(&msgtx,0,sizeof(msgtx)); + txobj = bitcoin_data2json(coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->height,&checktxid,&msgtx,extraspace,1000000,serialized,len,0,0); + //printf("TX.(%s) match.%d\n",jprint(txobj,0),bits256_cmp(txid,checktxid)); + free(extraspace); + if ( bits256_cmp(txid,checktxid) != 0 ) + { + printf("LP_transaction_fromdata mismatched txid %s vs %s\n",bits256_str(str,txid),bits256_str(str2,checktxid)); + free_json(txobj); + txobj = 0; + } + return(txobj); +} + cJSON *electrum_transaction(char *symbol,struct electrum_info *ep,cJSON **retjsonp,bits256 txid) { - char str[65]; printf("%s TRANSACTION.(%s)\n",symbol,bits256_str(str,txid)); - if ( bits256_nonz(txid) != 0 ) - return(electrum_hasharg(symbol,ep,retjsonp,"blockchain.transaction.get",txid,ELECTRUM_TIMEOUT)); - else return(cJSON_Parse("{\"error\":\"null txid\"}")); + char *hexstr,str[65]; int32_t len; cJSON *hexjson,*txobj=0; struct iguana_info *coin; uint8_t *serialized; struct LP_transaction *tx; + //printf("electrum_transaction %s %s\n",symbol,bits256_str(str,txid)); + if ( bits256_nonz(txid) != 0 && (coin= LP_coinfind(symbol)) != 0 ) + { + if ( (tx= LP_transactionfind(coin,txid)) != 0 && tx->serialized != 0 ) + { + //char str[65]; printf("%s cache hit -> TRANSACTION.(%s)\n",symbol,bits256_str(str,txid)); + if ( (txobj= LP_transaction_fromdata(coin,txid,tx->serialized,tx->len)) != 0 ) + { + *retjsonp = txobj; + return(txobj); + } + } + hexjson = electrum_hasharg(symbol,ep,&hexjson,"blockchain.transaction.get",txid,ELECTRUM_TIMEOUT); + hexstr = jprint(hexjson,0); + if ( strlen(hexstr) > 60000 ) + { + static uint32_t counter; + if ( counter++ < 3 ) + printf("rawtransaction too big %d\n",(int32_t)strlen(hexstr)); + free(hexstr); + free_json(hexjson); + *retjsonp = cJSON_Parse("{\"error\":\"transaction too big\"}"); + return(*retjsonp); + } + if ( hexstr[0] == '"' && hexstr[strlen(hexstr)-1] == '"' ) + hexstr[strlen(hexstr)-1] = 0; + if ( (len= is_hexstr(hexstr+1,0)) > 2 ) + { + len = (int32_t)strlen(hexstr+1) >> 1; + serialized = malloc(len); + decode_hex(serialized,len,hexstr+1); + free(hexstr); + //printf("DATA.(%s) from (%s)\n",hexstr+1,jprint(hexjson,0)); + txobj = LP_transaction_fromdata(coin,txid,serialized,len); + if ( (tx= LP_transactionfind(coin,txid)) == 0 || tx->serialized == 0 ) + { + txobj = LP_transactioninit(coin,txid,0,txobj); + LP_transactioninit(coin,txid,1,txobj); + tx = LP_transactionfind(coin,txid); + } + if ( tx != 0 ) + { + tx->serialized = serialized; + tx->len = len; + } + else + { + printf("unexpected couldnt find tx %s %s\n",coin->symbol,bits256_str(str,txid)); + free(serialized); + } + *retjsonp = txobj; + free_json(hexjson); + //printf("return from electrum_transaction\n"); + return(*retjsonp); + } else printf("non-hex tx.(%s)\n",jprint(hexjson,0)); + free(hexstr); + free_json(hexjson); + } + *retjsonp = 0; + return(*retjsonp); } cJSON *electrum_getmerkle(char *symbol,struct electrum_info *ep,cJSON **retjsonp,bits256 txid,int32_t height) { char params[128],str[65]; sprintf(params,"[\"%s\", %d]",bits256_str(str,txid),height); + if ( bits256_nonz(txid) == 0 ) + return(cJSON_Parse("{\"error\":\"null txid\"}")); return(electrum_submit(symbol,ep,retjsonp,"blockchain.transaction.get_merkle",params,ELECTRUM_TIMEOUT)); } @@ -567,7 +685,7 @@ void electrum_test() struct electrum_info *LP_electrum_info(int32_t *alreadyp,char *symbol,char *ipaddr,uint16_t port,int32_t bufsize) { - struct electrum_info *ep=0; int32_t i; struct stritem *sitem; char name[512],*str = "init string"; + struct electrum_info *ep=0; int32_t i,sock; struct stritem *sitem; char name[512],*str = "init string"; *alreadyp = 0; portable_mutex_lock(&LP_electrummutex); for (i=0; isock = LP_socket(0,ipaddr,port); + ep->sock = sock; safecopy(ep->symbol,symbol,sizeof(ep->symbol)); safecopy(ep->ipaddr,ipaddr,sizeof(ep->ipaddr)); ep->port = port; @@ -608,12 +731,12 @@ struct electrum_info *LP_electrum_info(int32_t *alreadyp,char *symbol,char *ipad int32_t LP_recvfunc(struct electrum_info *ep,char *str,int32_t len) { - cJSON *strjson,*errjson,*resultjson,*paramsjson; char *method; int32_t i,n,height; uint32_t idnum=0; struct stritem *stritem; struct queueitem *item = 0; + cJSON *strjson,*errjson,*resultjson,*paramsjson; char *method; int32_t i,n,height; uint32_t idnum=0; struct stritem *stritem; struct iguana_info *coin; struct queueitem *tmp,*item = 0; ep->lasttime = (uint32_t)time(NULL); if ( (strjson= cJSON_Parse(str)) != 0 ) { resultjson = jobj(strjson,"result"); - printf("strjson.(%s)\n",jprint(strjson,0)); + //printf("strjson.(%s)\n",jprint(strjson,0)); if ( (method= jstr(strjson,"method")) != 0 ) { if ( strcmp(method,"blockchain.headers.subscribe") == 0 ) @@ -625,11 +748,11 @@ int32_t LP_recvfunc(struct electrum_info *ep,char *str,int32_t len) resultjson = jitem(paramsjson,i); } } - else if ( strcmp(method,"blockchain.address.subscribe") == 0 ) + /*else if ( strcmp(method,"blockchain.address.subscribe") == 0 ) never is called { printf("recv addr subscribe.(%s)\n",jprint(resultjson,0)); electrum_process_array(ep->coin,resultjson); - } + }*/ } if ( resultjson != 0 ) { @@ -637,18 +760,18 @@ int32_t LP_recvfunc(struct electrum_info *ep,char *str,int32_t len) { *(ep->heightp) = height; *(ep->heighttimep) = (uint32_t)time(NULL); - printf("ELECTRUM >>>>>>>>> set height.%d\n",height); + if ( (coin= LP_coinfind(ep->symbol)) != 0 ) + coin->updaterate = (uint32_t)time(NULL); + //printf("%s ELECTRUM >>>>>>>>> set height.%d\n",ep->symbol,height); } } idnum = juint(strjson,"id"); portable_mutex_lock(&ep->pendingQ.mutex); if ( ep->pendingQ.list != 0 ) { - DL_FOREACH(ep->pendingQ.list,item) + DL_FOREACH_SAFE(ep->pendingQ.list,item,tmp) { stritem = (struct stritem *)item; - if ( *stritem->retptrp != 0 ) - continue; if ( item->type == idnum ) { //printf("matched idnum.%d result.%p\n",idnum,resultjson); @@ -660,13 +783,16 @@ int32_t LP_recvfunc(struct electrum_info *ep,char *str,int32_t len) } if ( stritem->expiration < ep->lasttime ) { - //DL_DELETE(ep->pendingQ.list,item); - printf("expired (%s)\n",stritem->str); - errjson = cJSON_CreateObject(); - jaddnum(errjson,"id",item->type); - jaddstr(errjson,"error","timeout"); - *((cJSON **)stritem->retptrp) = errjson; - //free(item); + DL_DELETE(ep->pendingQ.list,item); + if ( 0 ) + { + printf("expired %s (%s)\n",ep->symbol,stritem->str); + errjson = cJSON_CreateObject(); + jaddnum(errjson,"id",item->type); + jaddstr(errjson,"error","timeout"); + *((cJSON **)stritem->retptrp) = errjson; + } + free(item); } } } @@ -708,7 +834,7 @@ void LP_dedicatedloop(void *arg) if ( ep->pendingQ.list != 0 ) { printf("list %p\n",ep->pendingQ.list); - DL_FOREACH(ep->pendingQ.list,item) + DL_FOREACH_SAFE(ep->pendingQ.list,item,tmp) { printf("item.%p\n",item); if ( item->type == 0xffffffff ) @@ -721,7 +847,7 @@ void LP_dedicatedloop(void *arg) } DL_APPEND(ep->pendingQ.list,&sitem->DL); portable_mutex_unlock(&ep->pendingQ.mutex);*/ - //printf("%p SEND.(%s) to %s:%u\n",sitem,sitem->str,ep->ipaddr,ep->port); + //printf("%p SENT.(%s) to %s:%u\n",sitem,sitem->str,ep->ipaddr,ep->port); queue_enqueue("pendingQ",&ep->pendingQ,&sitem->DL); flag++; } @@ -740,7 +866,12 @@ void LP_dedicatedloop(void *arg) usleep(100000); } } - printf("close %s:%u\n",ep->ipaddr,ep->port); + if ( coin->electrum == ep ) + { + coin->electrum = ep->prev; + printf("set %s electrum to %p\n",coin->symbol,coin->electrum); + } else printf("backup electrum server closing\n"); + printf(">>>>>>>>>> electrum close %s:%u\n",ep->ipaddr,ep->port); if ( Num_electrums > 0 ) { portable_mutex_lock(&LP_electrummutex); @@ -755,7 +886,8 @@ void LP_dedicatedloop(void *arg) } portable_mutex_unlock(&LP_electrummutex); } - free(ep); + ep->sock = -1; + //free(ep); } cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port) @@ -763,7 +895,11 @@ cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port) struct electrum_info *ep; int32_t already; cJSON *retjson = cJSON_CreateObject(); jaddstr(retjson,"ipaddr",ipaddr); jaddnum(retjson,"port",port); - ep = LP_electrum_info(&already,coin->symbol,ipaddr,port,IGUANA_MAXPACKETSIZE * 10); + if ( (ep= LP_electrum_info(&already,coin->symbol,ipaddr,port,IGUANA_MAXPACKETSIZE * 10)) == 0 ) + { + jaddstr(retjson,"error","couldnt connect to electrum server"); + return(retjson); + } if ( already == 0 ) { if ( ep != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_dedicatedloop,(void *)ep) != 0 ) @@ -775,6 +911,7 @@ cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port) { printf("launched.(%s:%u)\n",ep->ipaddr,ep->port); jaddstr(retjson,"result","success"); + ep->prev = coin->electrum; coin->electrum = ep; } } diff --git a/iguana/exchanges/LP_statemachine.c b/iguana/exchanges/LP_statemachine.c index 860c796e1..29af48553 100644 --- a/iguana/exchanges/LP_statemachine.c +++ b/iguana/exchanges/LP_statemachine.c @@ -1473,6 +1473,407 @@ if ( (array= LP_tradecandidates(base)) != 0 ) printf("metrics, best %f\n",bestmetric); */ +int32_t LP_utxosquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *coin,int32_t lastn,char *myipaddr,uint16_t myport,int32_t maxentries) +{ + char *retstr; struct LP_peerinfo *peer; uint32_t now; int32_t retval = -1; + printf("deprecated LP_utxosquery\n"); + return(-1); + peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); + if ( coin == 0 ) + coin = ""; + //printf("utxo query.(%s)\n",destipaddr); + if ( IAMLP != 0 ) + retstr = issue_LP_getutxos(destipaddr,destport,coin,lastn,myipaddr,myport,mypeer != 0 ? mypeer->numpeers : 0,maxentries); + else retstr = issue_LP_clientgetutxos(destipaddr,destport,coin,maxentries); + if ( retstr != 0 ) + { + now = (uint32_t)time(NULL); + retval = LP_utxosparse(destipaddr,destport,retstr,now); + //printf("got.(%s)\n",retstr); + free(retstr); + } + return(retval); +} + +char *issue_LP_numutxos(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers,int32_t numutxos) +{ + char url[512],*retstr; + printf("deprecated issue_LP_numutxos\n"); + return(0); + sprintf(url,"http://%s:%u/api/stats/numutxos?ipaddr=%s&port=%u&numpeers=%d&numutxos=%d",destip,destport,ipaddr,port,numpeers,numutxos); + retstr = LP_issue_curl("numutxos",destip,port,url); + //printf("%s -> getpeers.(%s)\n",destip,retstr); + return(retstr); +} + +char *issue_LP_getutxos(char *destip,uint16_t destport,char *coin,int32_t lastn,char *ipaddr,uint16_t port,int32_t numpeers,int32_t numutxos) +{ + char url[512]; + printf("deprecated issue_LP_getutxos\n"); + return(0); + sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=%s&port=%u&numpeers=%d&numutxos=%d",destip,destport,coin,lastn,ipaddr,port,numpeers,numutxos); + return(LP_issue_curl("getutxos",destip,destport,url)); + //return(issue_curlt(url,LP_HTTP_TIMEOUT)); +} + +char *issue_LP_clientgetutxos(char *destip,uint16_t destport,char *coin,int32_t lastn) +{ + char url[512];//,*retstr; + printf("deprecated issue_LP_clientgetutxos\n"); + return(0); + sprintf(url,"http://%s:%u/api/stats/getutxos?coin=%s&lastn=%d&ipaddr=127.0.0.1&port=0",destip,destport,coin,lastn); + return(LP_issue_curl("clientgetutxos",destip,destport,url)); + //retstr = issue_curlt(url,LP_HTTP_TIMEOUT); + //printf("%s clientgetutxos.(%s)\n",url,retstr); + //return(retstr); +} +void LP_address_monitor(struct LP_pubkeyinfo *pubp) +{ + struct iguana_info *coin,*tmp; char coinaddr[64]; cJSON *retjson; struct LP_address *ap; + return; + HASH_ITER(hh,LP_coins,coin,tmp) + { + bitcoin_address(coinaddr,coin->taddr,coin->pubtype,pubp->rmd160,sizeof(pubp->rmd160)); + portable_mutex_lock(&coin->addrmutex); + if ( (ap= _LP_address(coin,coinaddr)) != 0 ) + { + ap->monitor = (uint32_t)time(NULL); + } + portable_mutex_unlock(&coin->addrmutex); + if ( coin->electrum != 0 ) + { + if ( (retjson= electrum_address_subscribe(coin->symbol,coin->electrum,&retjson,coinaddr)) != 0 ) + { + printf("%s MONITOR.(%s) -> %s\n",coin->symbol,coinaddr,jprint(retjson,0)); + free_json(retjson); + } + } + } +} + +/*else if ( strcmp(method,"ordermatch") == 0 ) + { + if ( price > SMALLVAL ) + return(LP_ordermatch(base,j64bits(argjson,"txfee"),price,jdouble(argjson,"relvolume"),rel,jbits256(argjson,"txid"),jint(argjson,"vout"),jbits256(argjson,"feetxid"),jint(argjson,"feevout"),j64bits(argjson,"desttxfee"),jint(argjson,"duration"))); + else return(clonestr("{\"error\":\"no price set\"}")); + } + else if ( strcmp(method,"trade") == 0 ) + { + struct LP_quoteinfo Q; + if ( price > SMALLVAL || jobj(argjson,"quote") != 0 ) + { + LP_quoteparse(&Q,jobj(argjson,"quote")); + return(LP_trade(ctx,myipaddr,pubsock,&Q,price,jint(argjson,"timeout"),jint(argjson,"duration"))); + } else return(clonestr("{\"error\":\"no price set or no quote object\"}")); + } + else if ( strcmp(method,"autotrade") == 0 ) + { + if ( price > SMALLVAL ) + { + return(LP_autotrade(ctx,myipaddr,pubsock,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration"))); + } else return(clonestr("{\"error\":\"no price set\"}")); + }*/ +int32_t LP_utxopurge(int32_t allutxos) +{ + char str[65]; struct LP_utxoinfo *utxo,*tmp; int32_t iambob,n = 0; + printf("LP_utxopurge mypub.(%s)\n",bits256_str(str,LP_mypub25519)); + portable_mutex_lock(&LP_utxomutex); + for (iambob=0; iambob<=1; iambob++) + { + HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) + { + if ( LP_isavailable(utxo) > 0 ) + { + if ( allutxos != 0 || LP_ismine(utxo) > 0 ) + { + printf("iambob.%d delete.(%s)\n",iambob,bits256_str(str,utxo->payment.txid)); + HASH_DELETE(hh,LP_utxoinfos[iambob],utxo); + //free(utxo); let the LP_utxoinfos2 free the utxo, should be 1:1 + } else n++; + } else n++; + } + HASH_ITER(hh,LP_utxoinfos2[iambob],utxo,tmp) + { + if ( LP_isavailable(utxo) > 0 ) + { + if ( allutxos != 0 || LP_ismine(utxo) > 0 ) + { + printf("iambob.%d delete2.(%s)\n",iambob,bits256_str(str,utxo->payment.txid)); + HASH_DELETE(hh2,LP_utxoinfos2[iambob],utxo); + free(utxo); + } else n++; + } else n++; + } + } + portable_mutex_unlock(&LP_utxomutex); + return(n); +} +/*struct LP_utxoinfo *_LP_butxo_find(struct LP_utxoinfo *butxo) + { + int32_t i; struct LP_utxoinfo *utxo=0; uint32_t now = (uint32_t)time(NULL); + //portable_mutex_lock(&LP_butxomutex); + for (i=0; ipayment.vout == utxo->payment.vout && butxo->deposit.vout == utxo->deposit.vout && bits256_nonz(butxo->payment.txid) != 0 && bits256_nonz(butxo->deposit.txid) != 0 && bits256_cmp(butxo->payment.txid,utxo->payment.txid) == 0 && bits256_cmp(butxo->deposit.txid,utxo->deposit.txid) == 0 ) + break; + if ( utxo->S.swap == 0 && now > utxo->T.swappending ) + memset(utxo,0,sizeof(*utxo)); + utxo = 0; + } + //portable_mutex_unlock(&LP_butxomutex); + return(utxo); + } + + struct LP_utxoinfo *LP_butxo_add(struct LP_utxoinfo *butxo) + { + static struct LP_utxoinfo zeroes; + int32_t i; struct LP_utxoinfo *utxo=0; + portable_mutex_lock(&LP_butxomutex); + if ( (utxo= _LP_butxo_find(butxo)) == 0 ) + { + for (i=0; iS = srcutxo->S; + destutxo->T = srcutxo->T; + } + + void LP_butxo_swapfields(struct LP_utxoinfo *butxo) + { + struct LP_utxoinfo *getutxo=0; + portable_mutex_lock(&LP_butxomutex); + if ( (getutxo= _LP_butxo_find(butxo)) != 0 ) + LP_butxo_swapfields_copy(butxo,getutxo); + portable_mutex_unlock(&LP_butxomutex); + } + + void LP_butxo_swapfields_set(struct LP_utxoinfo *butxo) + { + struct LP_utxoinfo *setutxo; + if ( (setutxo= LP_butxo_add(butxo)) != 0 ) + { + LP_butxo_swapfields_copy(setutxo,butxo); + } + }*/ +/*struct LP_utxoinfo BUTXOS[100]; + + int32_t LP_butxo_findeither(bits256 txid,int32_t vout) + { + struct LP_utxoinfo *utxo; int32_t i,retval = 0; + portable_mutex_lock(&LP_butxomutex); + for (i=0; ipayment.vout && bits256_cmp(txid,utxo->payment.txid)) == 0 || (vout == utxo->deposit.vout && bits256_cmp(txid,utxo->deposit.txid) == 0) ) + { + retval = 1; + break; + } + } + portable_mutex_unlock(&LP_butxomutex); + return(retval); + }*/ + +struct LP_utxoinfo *LP_utxoaddjson(int32_t iambob,int32_t pubsock,cJSON *argjson) +{ + struct LP_utxoinfo *utxo; + if ( jobj(argjson,"iambob") == 0 || iambob != jint(argjson,"iambob") ) + { + printf("LP_utxoaddjson: iambob.%d != arg.%d obj.%p (%s)\n",iambob,jint(argjson,"iambob"),jobj(argjson,"iambob"),jprint(argjson,0)); + return(0); + } + portable_mutex_lock(&LP_UTXOmutex); + utxo = LP_utxoadd(iambob,pubsock,jstr(argjson,"coin"),jbits256(argjson,"txid"),jint(argjson,"vout"),j64bits(argjson,"value"),jbits256(argjson,"txid2"),jint(argjson,"vout2"),j64bits(argjson,"value2"),jstr(argjson,"script"),jstr(argjson,"address"),jbits256(argjson,"pubkey"),jstr(argjson,"gui"),juint(argjson,"session")); + if ( LP_ismine(utxo) > 0 && utxo->T.lasttime == 0 ) + { + utxo->T.lasttime = (uint32_t)time(NULL); + printf("set lasttime!\n"); + } + portable_mutex_unlock(&LP_UTXOmutex); + return(utxo); +} + + +int32_t LP_utxosparse(char *destipaddr,uint16_t destport,char *retstr,uint32_t now) +{ + struct LP_peerinfo *peer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; bits256 txid; struct LP_utxoinfo *utxo; + //printf("parse.(%s)\n",retstr); + if ( (array= cJSON_Parse(retstr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; iT.lasttime = now; + } + } + if ( (destpeer= LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport)) != 0 ) + { + destpeer->numutxos = n; + } + } + free_json(array); + } + return(n); +} +void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector) +{ + //cJSON *argjson; struct _LP_utxoinfo u; char *msg; + if ( utxo == 0 ) + return; + utxo->T.spentflag = (uint32_t)time(NULL); + /*if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 ) + LP_mypeer->numutxos--; + if ( LP_mypubsock >= 0 ) + { + argjson = cJSON_CreateObject(); + jaddstr(argjson,"method","checktxid"); + jaddbits256(argjson,"txid",utxo->payment.txid); + jaddnum(argjson,"vout",utxo->payment.vout); + if ( selector != 0 ) + { + if ( bits256_nonz(utxo->deposit.txid) != 0 ) + u = utxo->deposit; + else u = utxo->fee; + jaddbits256(argjson,"checktxid",u.txid); + jaddnum(argjson,"checkvout",u.vout); + } + msg = jprint(argjson,1); + /LP_send(LP_mypubsock,msg,(int32_t)strlen(msg)+1,1); + }*/ +} +char *LP_utxos(int32_t iambob,struct LP_peerinfo *mypeer,char *symbol,int32_t lastn) +{ + int32_t i,n,m; uint64_t val,val2; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray(); + printf("deprecated! LP_utxos\n"); + //n = mypeer != 0 ? mypeer->numutxos : 0; + if ( lastn <= 0 ) + lastn = LP_PROPAGATION_SLACK * 2; + HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) + { + //char str[65]; printf("check %s.%s\n",utxo->coin,bits256_str(str,utxo->payment.txid)); + if ( (symbol == 0 || symbol[0] == 0 || strcmp(symbol,utxo->coin) == 0) && utxo->T.spentflag == 0 ) + { + u = (iambob != 0) ? utxo->deposit : utxo->fee; + if ( LP_iseligible(&val,&val2,utxo->iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,u.txid,u.vout) == 0 ) + { + char str[65]; printf("iambob.%d not eligible (%.8f %.8f) %s %s/v%d\n",iambob,dstr(val),dstr(val2),utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout); + continue; + } else jaddi(utxosjson,LP_utxojson(utxo)); + } + } + if ( (n= cJSON_GetArraySize(utxosjson)) > lastn ) + { + m = n - lastn; + for (i=0; i 0 ) + { + memset(zero.bytes,0,sizeof(zero)); + msg = jprint(LP_utxojson(utxo),1); + LP_broadcast_message(LP_mypubsock,utxo->coin,"",zero,msg); + } +} + +void LP_utxo_spentcheck(int32_t pubsock,struct LP_utxoinfo *utxo) +{ + struct _LP_utxoinfo u; struct iguana_info *coin; char str[65]; uint32_t now = (uint32_t)time(NULL); + if ( IAMLP != 0 && (coin= LP_coinfind(utxo->coin)) != 0 && coin->inactive != 0 ) + return; + //printf("%s lag.%d\n",bits256_str(str,utxo->txid),now-utxo->lastspentcheck); + if ( utxo->T.spentflag == 0 && now > utxo->T.lastspentcheck+60 ) + { + u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; + utxo->T.lastspentcheck = now; + if ( LP_txvalue(0,utxo->coin,utxo->payment.txid,utxo->payment.vout) == 0 ) + { + printf("txid.%s %s/v%d %.8f has been spent\n",utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout,dstr(utxo->payment.value)); + LP_spentnotify(utxo,0); + } + else if ( LP_txvalue(0,utxo->coin,u.txid,u.vout) == 0 ) + { + printf("txid2.%s %s/v%d %.8f has been spent\n",utxo->coin,bits256_str(str,u.txid),u.vout,dstr(u.value)); + LP_spentnotify(utxo,1); + } + } +} + +int32_t LP_peer_utxosquery(struct LP_peerinfo *mypeer,uint16_t myport,int32_t pubsock,struct LP_peerinfo *peer,uint32_t now,int32_t interval,int32_t maxentries) +{ + int32_t lastn,n = -1; + if ( peer->lastutxos < now-interval ) + { + //lastn = peer->numutxos - mypeer->numutxos + LP_PROPAGATION_SLACK; + //if ( lastn < LP_PROPAGATION_SLACK * 2 ) + lastn = LP_PROPAGATION_SLACK * 2; + if ( mypeer == 0 || strcmp(peer->ipaddr,mypeer->ipaddr) != 0 ) + { + peer->lastutxos = now; + //printf("query utxos from %s\n",peer->ipaddr); + n = LP_utxosquery(mypeer,pubsock,peer->ipaddr,peer->port,"",lastn,mypeer != 0 ? mypeer->ipaddr : "127.0.0.1",myport,maxentries); + } + } //else printf("LP_peer_utxosquery skip.(%s) %u\n",peer->ipaddr,peer->lastutxos); + return(n); +} +/*if ( time(NULL) > coin->lastmonitor+60 ) + { + //portable_mutex_lock(&coin->addrmutex); + HASH_ITER(hh,coin->addresses,ap,atmp) + { + if ( coin->electrum == 0 ) + { + LP_listunspent_issue(coin->symbol,ap->coinaddr); + DL_FOREACH_SAFE(ap->utxos,up,utmp) + { + if ( up->spendheight <= 0 ) + { + if ( LP_txvalue(0,coin->symbol,up->U.txid,up->U.vout) == 0 ) + up->spendheight = 1; + } + } + } + } + //portable_mutex_unlock(&coin->addrmutex); + coin->lastmonitor = (uint32_t)time(NULL); + }*/ + /*cJSON *LP_tradecandidates(char *base) { struct LP_peerinfo *peer,*tmp; struct LP_quoteinfo Q; char *utxostr,coinstr[16]; cJSON *array,*retarray=0,*item; int32_t i,n,totaladded,added; @@ -1600,4 +2001,211 @@ if ( (array= LP_tradecandidates(base)) != 0 ) } }*/ +/*int32_t LP_orderbookfind(struct LP_orderbookentry **array,int32_t num,bits256 txid,int32_t vout) + { + int32_t i; + for (i=0; ivout == vout && bits256_cmp(array[i]->txid,txid) == 0) || (array[i]->vout2 == vout && bits256_cmp(array[i]->txid2,txid) == 0) ) + return(i); + return(-1); + }*/ +//char str[65],str2[65]; printf("check utxo.%s/v%d from %s\n",bits256_str(str,utxo->payment.txid),utxo->payment.vout,bits256_str(str2,utxo->pubkey)); +//if ( strcmp(base,utxo->coin) == 0 && LP_isavailable(utxo) > 0 && pubp != 0 && (price= pubp->matrix[baseid][relid]) > SMALLVAL ) +//if ( polarity > 0 ) +// minsatoshis = utxo->S.satoshis; +//else minsatoshis = utxo->S.satoshis * price; +/*if ( LP_orderbookfind(*arrayp,cachednum,utxo->payment.txid,utxo->payment.vout) < 0 ) + { + if ( LP_iseligible(&val,&val2,utxo->iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,utxo->deposit.txid,utxo->deposit.vout) == 0 ) + continue; + if ( polarity > 0 ) + basesatoshis = utxo->S.satoshis; + else basesatoshis = utxo->S.satoshis * price; + //char str[65]; printf("found utxo not in orderbook %s/v%d %.8f %.8f\n",bits256_str(str,utxo->payment.txid),utxo->payment.vout,dstr(basesatoshis),polarity > 0 ? price : 1./price); + if ( (op= LP_orderbookentry(base,rel,utxo->payment.txid,utxo->payment.vout,utxo->deposit.txid,utxo->deposit.vout,polarity > 0 ? price : 1./price,basesatoshis,utxo->pubkey,now - pubp->timestamp)) != 0 ) + { + *arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1)); + (*arrayp)[num++] = op; + if ( LP_ismine(utxo) > 0 && utxo->T.lasttime == 0 ) + LP_utxo_clientpublish(utxo); + } + }*/ + +#ifdef oldway +struct LP_utxoinfo *LP_bestutxo(double *ordermatchpricep,int64_t *bestsatoshisp,int64_t *bestdestsatoshisp,struct LP_utxoinfo *autxo,char *base,double maxprice,int32_t duration,uint64_t txfee,uint64_t desttxfee,uint64_t maxdestsatoshis) +{ + int64_t satoshis,destsatoshis; uint64_t val,val2; bits256 txid,pubkey; char *obookstr; cJSON *orderbook,*asks,*item; struct LP_utxoinfo *butxo,*bestutxo = 0; int32_t i,n,j,vout,numasks; double bestmetric=0.,metric,vol,price,qprice,bestprice = 0.; struct LP_pubkeyinfo *pubp; + *ordermatchpricep = 0.; + *bestsatoshisp = *bestdestsatoshisp = 0; + if ( duration <= 0 ) + duration = LP_ORDERBOOK_DURATION; + if ( maxprice <= 0. || LP_priceinfofind(base) == 0 ) + return(0); + LP_txfees(&txfee,&desttxfee,base,autxo->coin); + if ( (obookstr= LP_orderbook(base,autxo->coin,duration)) != 0 ) + { + if ( (orderbook= cJSON_Parse(obookstr)) != 0 ) + { + if ( (asks= jarray(&numasks,orderbook,"asks")) != 0 ) + { + for (i=0; i 0 && price <= maxprice ) + { + //price *= 1.0001; + //if ( price > maxprice ) + // price = maxprice; + pubkey = jbits256(item,"pubkey"); + if ( bits256_cmp(pubkey,LP_mypub25519) != 0 && (pubp= LP_pubkeyadd(pubkey)) != 0 && pubp->numerrors < LP_MAXPUBKEY_ERRORS ) + { + if ( bestprice == 0. ) // assumes price ordered asks + bestprice = price; + printf("item.[%d] %s\n",i,jprint(item,0)); + txid = jbits256(item,"txid"); + vout = jint(item,"vout"); + vol = jdouble(item,"volume"); + metric = price / bestprice; + printf("maxdest %.8f metric %f vol %f add pings numutxos.%d min %.8f max %.8f\n",dstr(maxdestsatoshis),metric,vol,jint(item,"numutxos"),jdouble(item,"minvolume"),jdouble(item,"maxvolume")); + // check utxos > 1 for pubkey, SPV validate recv'ed + /*if ( (butxo= LP_utxofind(1,txid,vout)) != 0 && (long long)(vol*SATOSHIDEN) == butxo->S.satoshis && LP_isavailable(butxo) > 0 && LP_ismine(butxo) == 0 && butxo->T.bestflag == 0 ) + { + printf("got butxo? %p\n",butxo); + if ( LP_iseligible(&val,&val2,butxo->iambob,butxo->coin,butxo->payment.txid,butxo->payment.vout,butxo->S.satoshis,butxo->deposit.txid,butxo->deposit.vout) > 0 ) + { + destsatoshis = ((butxo->S.satoshis - txfee) * price); + satoshis = (destsatoshis / price + 0.49) - txfee; + if ( satoshis <= 0 ) + continue; + qprice = (double)destsatoshis / satoshis; + n = (int32_t)((double)destsatoshis / desttxfee); + if ( n < 10 ) + n = 10; + else n = 3; + for (j=0; jS.satoshis,txfee,autxo->payment.value,maxdestsatoshis,desttxfee)) > price+SMALLVAL ) + break; + } + //printf("j.%d/%d qprice %.8f vs price %.8f best.(%.8f %.8f)\n",j,n,qprice,price,dstr(satoshis),dstr(destsatoshis)); + if ( metric < 1.2 && destsatoshis > desttxfee && destsatoshis-desttxfee > (autxo->payment.value / LP_MINCLIENTVOL) && satoshis-txfee > (butxo->S.satoshis / LP_MINVOL) && satoshis <= butxo->payment.value-txfee ) + { + printf("value %.8f price %.8f/%.8f best %.8f destsatoshis %.8f * metric %.8f -> (%f)\n",dstr(autxo->payment.value),price,bestprice,bestmetric,dstr(destsatoshis),metric,dstr(destsatoshis) * metric * metric * metric); + metric = dstr(destsatoshis) * metric * metric * metric; + if ( bestmetric == 0. || metric < bestmetric ) + { + bestutxo = butxo; + *ordermatchpricep = price; + *bestdestsatoshisp = destsatoshis; + *bestsatoshisp = satoshis; + bestmetric = metric; + printf("set best!\n"); + } + } // else printf("skip.(%d %d %d %d %d) metric %f destsatoshis %.8f value %.8f destvalue %.8f txfees %.8f %.8f sats %.8f\n",metric < 1.2,destsatoshis > desttxfee,destsatoshis-desttxfee > (autxo->payment.value / LP_MINCLIENTVOL),satoshis-txfee > (butxo->S.satoshis / LP_MINVOL),satoshis < butxo->payment.value-txfee,metric,dstr(destsatoshis),dstr(butxo->S.satoshis),dstr(autxo->payment.value),dstr(txfee),dstr(desttxfee),dstr(satoshis)); + } + else + { + printf("ineligible.(%.8f %.8f)\n",price,dstr(butxo->S.satoshis)); + //if ( butxo->T.spentflag == 0 ) + // butxo->T.spentflag = (uint32_t)time(NULL); + } + } + else + { + if ( butxo != 0 ) + printf("%llu %llu %d %d %d: ",(long long)(vol*SATOSHIDEN),(long long)butxo->S.satoshis,vol*SATOSHIDEN == butxo->S.satoshis,LP_isavailable(butxo) > 0,LP_ismine(butxo) == 0); + printf("cant find butxo.%p or value mismatch %.8f != %.8f or bestflag.%d\n",butxo,vol,butxo!=0?dstr(butxo->S.satoshis):0,butxo->T.bestflag); + }*/ + } else printf("self trading or blacklisted peer\n"); + } + else + { + if ( i == 0 ) + printf("maxprice %.8f vs %.8f\n",maxprice,price); + break; + } + } + if ( bestutxo == 0 ) + { + int32_t numrestraints; + for (i=numrestraints=0; iT.bestflag = 0; + pubp->numerrors = 0; + } + } + } + printf("no bob utxo found -> cleared %d restraints\n",numrestraints); + } + } + free_json(orderbook); + } + free(obookstr); + } + printf("bestutxo.%p %.8f %.8f\n",bestutxo,*ordermatchpricep,dstr(*bestdestsatoshisp)); + if ( bestutxo == 0 || *ordermatchpricep == 0. || *bestdestsatoshisp == 0 ) + return(0); + bestutxo->T.bestflag = 1; + int32_t changed; + LP_mypriceset(&changed,autxo->coin,base,1. / *ordermatchpricep); + return(bestutxo); +} + +char *LP_ordermatch(char *base,int64_t txfee,double maxprice,double maxvolume,char *rel,bits256 txid,int32_t vout,bits256 feetxid,int32_t feevout,int64_t desttxfee,int32_t duration) +{ + struct LP_quoteinfo Q; int64_t bestsatoshis=0,bestdestsatoshis = 0; double ordermatchprice = 0.; struct LP_utxoinfo *autxo,*bestutxo; + txfee = LP_txfeecalc(LP_coinfind(base),txfee); + desttxfee = LP_txfeecalc(LP_coinfind(rel),desttxfee); + if ( (autxo= LP_utxopairfind(0,txid,vout,feetxid,feevout)) == 0 ) + return(clonestr("{\"error\":\"cant find alice utxopair\"}")); + if ( (bestutxo= LP_bestutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,SATOSHIDEN*maxvolume)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) + return(clonestr("{\"error\":\"cant find ordermatch utxo\"}")); + if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestsatoshis,bestdestsatoshis) < 0 ) + return(clonestr("{\"error\":\"cant set ordermatch quote\"}")); + if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,LP_mypub25519,autxo->coinaddr) < 0 ) + return(clonestr("{\"error\":\"cant set ordermatch quote info\"}")); + return(jprint(LP_quotejson(&Q),1)); +} + +char *LP_autotrade(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel,double maxprice,double relvolume,int32_t timeout,int32_t duration) +{ + uint64_t desttxfee,txfee; int64_t bestsatoshis=0,bestdestsatoshis=0; struct LP_utxoinfo *autxo,*butxo,*bestutxo = 0; double qprice,ordermatchprice=0.; struct LP_quoteinfo Q; + if ( duration <= 0 ) + duration = LP_ORDERBOOK_DURATION; + if ( timeout <= 0 ) + timeout = LP_AUTOTRADE_TIMEOUT; + if ( maxprice <= 0. || relvolume <= 0. || LP_priceinfofind(base) == 0 || LP_priceinfofind(rel) == 0 ) + return(clonestr("{\"error\":\"invalid parameter\"}")); + if ( (autxo= LP_utxo_bestfit(rel,SATOSHIDEN * relvolume)) == 0 ) + return(clonestr("{\"error\":\"cant find utxo that is big enough\"}")); + LP_txfees(&txfee,&desttxfee,base,rel); + if ( (bestutxo= LP_bestutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,SATOSHIDEN*relvolume)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) + { + printf("bestutxo.%p ordermatchprice %.8f bestdestsatoshis %.8f\n",bestutxo,ordermatchprice,dstr(bestdestsatoshis)); + return(clonestr("{\"error\":\"cant find ordermatch utxo\"}")); + } + if ( LP_quoteinfoinit(&Q,bestutxo,rel,ordermatchprice,bestsatoshis,bestdestsatoshis) < 0 ) + return(clonestr("{\"error\":\"cant set ordermatch quote\"}")); + if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,LP_mypub25519,autxo->coinaddr) < 0 ) + return(clonestr("{\"error\":\"cant set ordermatch quote info\"}")); + if ( (qprice= LP_quote_validate(&autxo,&butxo,&Q,0)) <= SMALLVAL ) + { + printf("quote validate error %.0f\n",qprice); + return(clonestr("{\"error\":\"quote validation error\"}")); + } + printf("do quote.(%s)\n",jprint(LP_quotejson(&Q),1)); + return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration)); +} +#endif + diff --git a/iguana/exchanges/LP_swap.c b/iguana/exchanges/LP_swap.c index 5c024221c..e08f3aa36 100644 --- a/iguana/exchanges/LP_swap.c +++ b/iguana/exchanges/LP_swap.c @@ -121,7 +121,11 @@ void basilisk_swap_finished(struct basilisk_swap *swap) { int32_t i; if ( swap->utxo != 0 && swap->sentflag == 0 ) + { LP_availableset(swap->utxo); + swap->utxo = 0; + //LP_butxo_swapfields_set(swap->utxo); + } swap->I.finished = (uint32_t)time(NULL); // save to permanent storage basilisk_rawtx_purge(&swap->bobdeposit); @@ -408,10 +412,10 @@ int32_t LP_waitfor(int32_t pairsock,struct basilisk_swap *swap,int32_t timeout,i pfd.events = NN_POLLIN; if ( nn_poll(&pfd,1,1) > 0 ) { - //printf("start wait\n"); + printf("start wait\n"); if ( (datalen= nn_recv(pairsock,&data,NN_MSG,0)) >= 0 ) { - //printf("wait for got.%d\n",datalen); + printf("wait for got.%d\n",datalen); retval = (*verify)(swap,data,datalen); nn_freemsg(data); //printf("retval.%d\n",retval); @@ -560,7 +564,7 @@ int32_t LP_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct ba if ( recvlen != datalen+rawtx->I.redeemlen+75 ) printf("RECVLEN %d != %d + %d\n",recvlen,datalen,rawtx->I.redeemlen); txid = bits256_doublesha256(0,data,datalen); - //char str[65]; printf("rawtx.%s txid %s\n",rawtx->name,bits256_str(str,txid)); + char str[65]; printf("rawtx.%s txid %s\n",rawtx->name,bits256_str(str,txid)); if ( bits256_cmp(txid,rawtx->I.actualtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 ) rawtx->I.actualtxid = txid; if ( (txobj= bitcoin_data2json(rawtx->coin->taddr,rawtx->coin->pubtype,rawtx->coin->p2shtype,rawtx->coin->isPoS,height,&rawtx->I.signedtxid,&rawtx->msgtx,rawtx->extraspace,sizeof(rawtx->extraspace),data,datalen,0,suppress_pubkeys)) != 0 ) @@ -613,8 +617,11 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3 rawtx->I.actualtxid = LP_broadcast_tx(rawtx->name,rawtx->coin->symbol,rawtx->txbytes,rawtx->I.datalen); if ( bits256_cmp(rawtx->I.actualtxid,rawtx->I.signedtxid) != 0 ) { - //printf("%s rawtxsend.[%d] %s vs %s\n",rawtx->name,rawtx->I.datalen,bits256_str(str,rawtx->I.signedtxid),bits256_str(str2,rawtx->I.actualtxid)); - rawtx->I.actualtxid = rawtx->I.signedtxid; + char str[65],str2[65]; + printf("%s rawtxsend.[%d] %s vs %s\n",rawtx->name,rawtx->I.datalen,bits256_str(str,rawtx->I.signedtxid),bits256_str(str2,rawtx->I.actualtxid)); + if ( bits256_nonz(rawtx->I.signedtxid) != 0 ) + rawtx->I.actualtxid = rawtx->I.signedtxid; + else rawtx->I.signedtxid = rawtx->I.actualtxid; } if ( bits256_nonz(rawtx->I.actualtxid) != 0 && msgbits != 0 ) { @@ -635,7 +642,7 @@ uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint3 if ( suppress_swapsend == 0 ) { retval = LP_swapsend(pairsock,swap,msgbits,sendbuf,sendlen,nextbits,rawtx->I.crcs); - if ( LP_waitmempool(rawtx->coin->symbol,rawtx->I.destaddr,rawtx->I.signedtxid,LP_SWAPSTEP_TIMEOUT*10) < 0 ) + if ( LP_waitmempool(rawtx->coin->symbol,rawtx->I.destaddr,rawtx->I.signedtxid,0,LP_SWAPSTEP_TIMEOUT*10) < 0 ) { char str[65]; printf("failed to find %s %s %s in the mempool?\n",rawtx->name,rawtx->I.destaddr,bits256_str(str,rawtx->I.actualtxid)); retval = -1; @@ -720,7 +727,7 @@ void LP_bobloop(void *_swap) printf("error waiting for alicefee\n"); else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x200,data,maxlen,&swap->bobdeposit,0x100,0) == 0 ) printf("error sending bobdeposit\n"); - else if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT*10,LP_verify_alicepayment) < 0 ) + else if ( LP_waitfor(swap->N.pair,swap,1800,LP_verify_alicepayment) < 0 ) printf("error waiting for alicepayment\n"); else { @@ -731,9 +738,9 @@ void LP_bobloop(void *_swap) if ( strcmp(swap->alicecoin.symbol,"BTC") == 0 ) m = 0; else m = 1; - while ( (n= LP_numconfirms(swap->alicecoin.symbol,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,1)) < m ) // sync with alice + while ( (n= LP_numconfirms(swap->alicecoin.symbol,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,1)) < m ) // sync with alice { - char str[65];printf("%d waiting for alicepayment to be confirmed.%d %s %s\n",n,1,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid)); + char str[65];printf("%d waiting for alicepayment %s to be confirmed.%d %s %s\n",n,swap->alicepayment.I.destaddr,1,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid)); sleep(3); } if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x8000,data,maxlen,&swap->bobpayment,0x4000,0) == 0 ) @@ -749,7 +756,7 @@ void LP_bobloop(void *_swap) } } basilisk_swap_finished(swap); - free(swap); + //free(swap); } else printf("swap timed out\n"); } @@ -775,7 +782,7 @@ void LP_aliceloop(void *_swap) LP_swapsfp_update(&swap->I.req); if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x80,data,maxlen,&swap->myfee,0x40,0) == 0 ) printf("error sending alicefee\n"); - else if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT*10,LP_verify_bobdeposit) < 0 ) + else if ( LP_waitfor(swap->N.pair,swap,1800,LP_verify_bobdeposit) < 0 ) printf("error waiting for bobdeposit\n"); else if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0) == 0 ) printf("error sending alicepayment\n"); @@ -784,26 +791,26 @@ void LP_aliceloop(void *_swap) if ( strcmp(swap->alicecoin.symbol,"BTC") == 0 ) m = 0; else m = 1; - while ( (n= LP_numconfirms(swap->alicecoin.symbol,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,1)) < m ) + while ( (n= LP_numconfirms(swap->alicecoin.symbol,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,1)) < m ) { - char str[65];printf("%d waiting for alicepayment to be confirmed.%d %s %s\n",n,1,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid)); + char str[65];printf("%d waiting for alicepayment %s to be confirmed.%d %s %s\n",n,swap->alicepayment.I.destaddr,1,swap->alicecoin.symbol,bits256_str(str,swap->alicepayment.I.signedtxid)); sleep(10); } swap->sentflag = 1; - if ( LP_waitfor(swap->N.pair,swap,LP_SWAPSTEP_TIMEOUT*10,LP_verify_bobpayment) < 0 ) + if ( LP_waitfor(swap->N.pair,swap,1800,LP_verify_bobpayment) < 0 ) printf("error waiting for bobpayment\n"); else { - while ( (n= LP_numconfirms(swap->bobcoin.symbol,swap->bobpayment.I.destaddr,swap->bobpayment.I.signedtxid,1)) < swap->I.bobconfirms ) + while ( (n= LP_numconfirms(swap->bobcoin.symbol,swap->bobpayment.I.destaddr,swap->bobpayment.I.signedtxid,0,1)) < swap->I.bobconfirms ) { - char str[65];printf("%d waiting for bobpayment to be confirmed.%d %s %s\n",n,swap->I.bobconfirms,swap->bobcoin.symbol,bits256_str(str,swap->bobpayment.I.signedtxid)); + char str[65];printf("%d waiting for bobpayment %s to be confirmed.%d %s %s\n",n,swap->bobpayment.I.destaddr,swap->I.bobconfirms,swap->bobcoin.symbol,bits256_str(str,swap->bobpayment.I.signedtxid)); sleep(LP_SWAPSTEP_TIMEOUT); } if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x20000,data,maxlen,&swap->alicespend,0x40000,0) == 0 ) printf("error sending alicespend\n"); - while ( (n= LP_numconfirms(swap->alicecoin.symbol,swap->alicespend.I.destaddr,swap->alicespend.I.signedtxid,1)) < swap->I.aliceconfirms ) + while ( (n= LP_numconfirms(swap->alicecoin.symbol,swap->alicespend.I.destaddr,swap->alicespend.I.signedtxid,0,1)) < swap->I.aliceconfirms ) { - char str[65];printf("%d waiting for alicespend to be confirmed.%d %s %s\n",n,swap->I.aliceconfirms,swap->bobcoin.symbol,bits256_str(str,swap->alicespend.I.signedtxid)); + char str[65];printf("%d waiting for alicespend %s to be confirmed.%d %s %s\n",n,swap->alicespend.I.destaddr,swap->I.aliceconfirms,swap->bobcoin.symbol,bits256_str(str,swap->alicespend.I.signedtxid)); sleep(LP_SWAPSTEP_TIMEOUT); } if ( swap->N.pair >= 0 ) @@ -812,8 +819,6 @@ void LP_aliceloop(void *_swap) } } } - basilisk_swap_finished(swap); - free(swap); } free(data); if ( swap->N.pair >= 0 ) @@ -821,6 +826,10 @@ void LP_aliceloop(void *_swap) nn_close(swap->N.pair); swap->N.pair = -1; } + basilisk_swap_finished(swap); + printf("finish swap.%p\n",swap); + //free(swap); + G.LP_pendingswaps--; } bits256 instantdex_derivekeypair(void *ctx,bits256 *newprivp,uint8_t pubkey[33],bits256 privkey,bits256 orderhash) @@ -1062,6 +1071,9 @@ struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 swap->ctx = bitcoin_ctx(); vcalc_sha256(0,swap->I.orderhash.bytes,(uint8_t *)rp,sizeof(*rp)); swap->I.req = *rp; + G.LP_skipstatus[G.LP_numskips] = ((uint64_t)rp->requestid << 32) | rp->quoteid; + if ( G.LP_numskips < sizeof(G.LP_skipstatus)/sizeof(*G.LP_skipstatus) ) + G.LP_numskips++; printf("basilisk_thread_start request.%u iambob.%d (%s/%s) quoteid.%u\n",rp->requestid,iambob,rp->src,rp->dest,rp->quoteid); bitcoin_pubkey33(swap->ctx,pubkey33,privkey); pubkey25519 = curve25519(privkey,curve25519_basepoint9()); diff --git a/iguana/exchanges/LP_transaction.c b/iguana/exchanges/LP_transaction.c index 71bde88e4..2c8bcff35 100644 --- a/iguana/exchanges/LP_transaction.c +++ b/iguana/exchanges/LP_transaction.c @@ -19,19 +19,40 @@ // marketmaker // +int32_t LP_gettx_presence(char *symbol,bits256 expectedtxid) +{ + cJSON *txobj; bits256 txid; int32_t flag = 0; + if ( (txobj= LP_gettx(symbol,expectedtxid)) != 0 ) + { + txid = jbits256(txobj,"txid"); + if ( jobj(txobj,"error") == 0 && bits256_cmp(txid,expectedtxid) == 0 ) + { + //char str[65]; printf("%s already in gettx (%s)\n",bits256_str(str,txid),jprint(txobj,0)); + flag = 1; + } + free_json(txobj); + } + return(flag); +} + bits256 LP_broadcast(char *txname,char *symbol,char *txbytes,bits256 expectedtxid) { char *retstr; bits256 txid; cJSON *retjson,*errorobj; int32_t i,sentflag = 0; memset(&txid,0,sizeof(txid)); - for (i=0; i<1; i++) + for (i=0; i<2; i++) { - if ( (retstr= LP_sendrawtransaction(symbol,txbytes)) != 0 ) + if ( sentflag == 0 && LP_gettx_presence(symbol,expectedtxid) != 0 ) + sentflag = 1; + if ( sentflag == 0 && (retstr= LP_sendrawtransaction(symbol,txbytes)) != 0 ) { if ( is_hexstr(retstr,0) == 64 ) { decode_hex(txid.bytes,32,retstr); if ( bits256_cmp(txid,expectedtxid) == 0 || (bits256_nonz(expectedtxid) == 0 && bits256_nonz(txid) != 0) ) + { sentflag = 1; + expectedtxid = txid; + } } else if ( (retjson= cJSON_Parse(retstr)) != 0 ) { @@ -50,7 +71,10 @@ bits256 LP_broadcast(char *txname,char *symbol,char *txbytes,bits256 expectedtxi } if ( sentflag != 0 ) break; + sleep(3); } + if ( sentflag != 0 ) + return(expectedtxid); return(txid); } @@ -396,7 +420,7 @@ int64_t iguana_lockval(int32_t finalized,int64_t locktime) int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,struct iguana_msgtx *msgtx,char **signedtxp,bits256 *signedtxidp,struct vin_info *V,int32_t numinputs,char *rawtx,cJSON *vins,cJSON *privkeysjson) { - uint8_t *serialized,*serialized2,*serialized3,*serialized4,*extraspace,pubkeys[64][33]; int32_t finalized,i,len,n,z,plen,maxsize,complete = 0,extralen = 65536; char *privkeystr,*signedtx = 0; bits256 privkeys[64],privkey,txid; cJSON *item; cJSON *txobj = 0; + uint8_t *serialized,*serialized2,*serialized3,*serialized4,*extraspace,pubkeys[64][33]; int32_t finalized,i,len,n,z,plen,maxsize,complete = 0,extralen = 100000; char *privkeystr,*signedtx = 0; bits256 privkeys[64],privkey,txid; cJSON *item; cJSON *txobj = 0; maxsize = 1000000; memset(privkey.bytes,0,sizeof(privkey)); if ( rawtx != 0 && rawtx[0] != 0 && (len= (int32_t)strlen(rawtx)>>1) < maxsize ) @@ -417,7 +441,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_ { //printf("numinputs.%d msgtx.%d\n",numinputs,msgtx->tx_in); memset(msgtx,0,sizeof(*msgtx)); - if ( iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,0,0,serialized,maxsize,msgtx,&txid,"",extraspace,65536,vins,V->suppress_pubkeys) > 0 && numinputs == msgtx->tx_in ) + if ( iguana_rwmsgtx(taddr,pubtype,p2shtype,isPoS,height,0,0,serialized,maxsize,msgtx,&txid,"",extraspace,extralen,vins,V->suppress_pubkeys) > 0 && numinputs == msgtx->tx_in ) { memset(pubkeys,0,sizeof(pubkeys)); memset(privkeys,0,sizeof(privkeys)); @@ -526,7 +550,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,uint8_t wiftype,void *ctx,bits256 privkey,bits256 *privkey2p,uint8_t *redeemscript,int32_t redeemlen,uint8_t *userdata,int32_t userdatalen,bits256 utxotxid,int32_t vout,char *destaddr,uint8_t *pubkey33,int32_t finalseqid,uint32_t expiration,int64_t *destamountp,uint64_t satoshis,char *changeaddr,char *vinaddr,int32_t suppress_pubkeys) { - char *rawtxbytes=0,*signedtx=0,tmpaddr[64],hexstr[999],wifstr[128],txdestaddr[64],_destaddr[64]; uint8_t spendscript[512],addrtype,rmd160[20]; cJSON *txobj,*vins,*item,*privkeys; int32_t completed,spendlen,ignore_cltverr=1; struct vin_info V[2]; uint32_t timestamp,locktime = 0,sequenceid = 0xffffffff * finalseqid; bits256 txid; uint64_t value,change = 0; struct iguana_msgtx msgtx; + char *rawtxbytes=0,*signedtx=0,str[65],tmpaddr[64],hexstr[999],wifstr[128],_destaddr[64]; uint8_t spendscript[512],addrtype,rmd160[20]; cJSON *txobj,*vins,*obj,*vouts,*item,*privkeys; int32_t completed,spendlen,n,ignore_cltverr=1; struct vin_info V[2]; uint32_t timestamp,locktime = 0,sequenceid = 0xffffffff * finalseqid; bits256 txid; uint64_t value=0,change = 0; struct iguana_msgtx msgtx; struct iguana_info *coin; *destamountp = 0; memset(signedtxidp,0,sizeof(*signedtxidp)); if ( finalseqid == 0 ) @@ -534,15 +558,28 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch //printf("bobtxspend.%s redeem.[%d]\n",symbol,redeemlen); if ( redeemlen < 0 ) return(0); + value = 0; #ifndef BASILISK_DISABLESENDTX - if ( (value= LP_txvalue(txdestaddr,symbol,utxotxid,vout)) == 0 ) + if ( (coin= LP_coinfind(symbol)) != 0 ) { - char str[65]; - printf("basilisk_swap_bobtxspend.%s %s utxo.(%s) already spent or doesnt exist\n",name,symbol,bits256_str(str,utxotxid)); - return(0); + if ( (txobj= LP_gettx(symbol,utxotxid)) != 0 ) + { + if ( (vouts= jarray(&n,txobj,"vout")) != 0 && vout < n ) + { + obj = jitem(vouts,vout); + value = LP_value_extract(obj,1); + //printf("value in vout.%d %.8f (%s)\n",vout,dstr(value),jprint(txobj,0)); + } + free_json(txobj); + //if ( value != 0 ) + // gettxout + } + if ( value == 0 ) + { + printf("basilisk_swap_bobtxspend.%s %s utxo.(%s) already spent or doesnt exist\n",name,symbol,bits256_str(str,utxotxid)); + return(0); + } } -#else - value = satoshis; #endif if ( satoshis != 0 ) { @@ -795,33 +832,13 @@ char *basilisk_swap_Aspend(char *name,char *symbol,uint64_t Atxfee,uint8_t wifta return(signedtx); } -int32_t LP_swap_txdestaddr(char *destaddr,bits256 txid,int32_t vout,cJSON *txobj) -{ - int32_t n,m,retval = -1; cJSON *vouts,*item,*addresses,*skey; char *addr; - if ( (vouts= jarray(&n,txobj,"vout")) != 0 && vout < n ) - { - item = jitem(vouts,vout); - if ( (skey= jobj(item,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 ) - { - item = jitem(addresses,0); - if ( (addr= jstr(item,0)) != 0 ) - { - safecopy(destaddr,addr,64); - retval = 0; - } - //printf("item.(%s) -> dest.(%s)\n",jprint(item,0),destaddr); - } - } - return(retval); -} - int32_t LP_swap_getcoinaddr(char *symbol,char *coinaddr,bits256 txid,int32_t vout) { cJSON *retjson; coinaddr[0] = 0; if ( (retjson= LP_gettx(symbol,txid)) != 0 ) { - LP_swap_txdestaddr(coinaddr,txid,vout,retjson); + LP_txdestaddr(coinaddr,txid,vout,retjson); free_json(retjson); } return(coinaddr[0] != 0); @@ -1073,7 +1090,7 @@ int32_t basilisk_bobdeposit_refund(struct basilisk_swap *swap,int32_t delay) void LP_swap_coinaddr(struct iguana_info *coin,char *coinaddr,uint64_t *valuep,uint8_t *data,int32_t datalen,int32_t v) { - cJSON *txobj,*vouts,*vout,*addresses,*item,*skey; uint8_t extraspace[32768]; bits256 signedtxid; struct iguana_msgtx msgtx; char *addr; int32_t n,m,suppress_pubkeys = 0; + cJSON *txobj,*vouts,*vout; uint8_t extraspace[32768]; bits256 signedtxid; struct iguana_msgtx msgtx; int32_t n,suppress_pubkeys = 0; if ( valuep != 0 ) *valuep = 0; if ( (txobj= bitcoin_data2json(coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->longestchain,&signedtxid,&msgtx,extraspace,sizeof(extraspace),data,datalen,0,suppress_pubkeys)) != 0 ) @@ -1083,9 +1100,9 @@ void LP_swap_coinaddr(struct iguana_info *coin,char *coinaddr,uint64_t *valuep,u { vout = jitem(vouts,v); if ( valuep != 0 ) - *valuep = LP_value_extract(vout); + *valuep = LP_value_extract(vout,1); //printf("VOUT.(%s)\n",jprint(vout,0)); - if ( (skey= jobj(vout,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 ) + /*if ( (skey= jobj(vout,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 ) { item = jitem(addresses,0); //printf("item.(%s)\n",jprint(item,0)); @@ -1094,7 +1111,8 @@ void LP_swap_coinaddr(struct iguana_info *coin,char *coinaddr,uint64_t *valuep,u safecopy(coinaddr,addr,64); //printf("extracted.(%s)\n",coinaddr); } - } + }*/ + LP_destaddr(coinaddr,vout); } free_json(txobj); } @@ -1302,22 +1320,24 @@ int32_t LP_verify_bobdeposit(struct basilisk_swap *swap,uint8_t *data,int32_t da if ( LP_rawtx_spendscript(swap,swap->bobcoin.longestchain,&swap->bobdeposit,0,data,datalen,0) == 0 ) { swap->aliceclaim.utxovout = 0; - swap->aliceclaim.utxotxid = swap->bobdeposit.I.signedtxid = LP_broadcast_tx(swap->bobdeposit.name,swap->bobcoin.symbol,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen); + swap->bobdeposit.I.signedtxid = LP_broadcast_tx(swap->bobdeposit.name,swap->bobcoin.symbol,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen); if ( bits256_nonz(swap->bobdeposit.I.signedtxid) != 0 ) swap->depositunconf = 1; + else swap->bobdeposit.I.signedtxid = swap->bobdeposit.I.actualtxid; len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); + swap->aliceclaim.utxotxid = swap->bobdeposit.I.signedtxid; memcpy(swap->I.userdata_aliceclaim,userdata,len); swap->I.userdata_aliceclaimlen = len; bitcoin_address(swap->bobdeposit.p2shaddr,swap->bobcoin.taddr,swap->bobcoin.p2shtype,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); strcpy(swap->bobdeposit.I.destaddr,swap->bobdeposit.p2shaddr); basilisk_dontforget_update(swap,&swap->bobdeposit); //LP_importaddress(swap->bobcoin.symbol,swap->bobdeposit.I.destaddr); - /*for (i=0; ibobdeposit.I.datalen; i++) + int32_t i; char str[65]; for (i=0; ibobdeposit.I.datalen; i++) printf("%02x",swap->bobdeposit.txbytes[i]); printf(" <- bobdeposit.%d %s\n",swap->bobdeposit.I.datalen,bits256_str(str,swap->bobdeposit.I.signedtxid)); for (i=0; ibobdeposit.I.redeemlen; i++) printf("%02x",swap->bobdeposit.redeemscript[i]); - printf(" <- bobdeposit redeem %d %s suppress.%d\n",i,swap->bobdeposit.I.destaddr,swap->aliceclaim.I.suppress_pubkeys);*/ + printf(" <- bobdeposit redeem %d %s suppress.%d\n",i,swap->bobdeposit.I.destaddr,swap->aliceclaim.I.suppress_pubkeys); memcpy(swap->aliceclaim.redeemscript,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen); swap->aliceclaim.I.redeemlen = swap->bobdeposit.I.redeemlen; memcpy(swap->aliceclaim.I.pubkey33,swap->persistent_pubkey33,33); @@ -1325,14 +1345,14 @@ int32_t LP_verify_bobdeposit(struct basilisk_swap *swap,uint8_t *data,int32_t da retval = 0; if ( (retval= basilisk_rawtx_sign(swap->bobcoin.symbol,swap->bobcoin.wiftaddr,swap->bobcoin.taddr,swap->bobcoin.pubtype,swap->bobcoin.p2shtype,swap->bobcoin.isPoS,swap->bobcoin.wiftype,swap,&swap->aliceclaim,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,1,swap->changermd160,swap->bobdeposit.I.destaddr)) == 0 ) { - /*for (i=0; ibobdeposit.I.datalen; i++) + int32_t i; for (i=0; ibobdeposit.I.datalen; i++) printf("%02x",swap->bobdeposit.txbytes[i]); printf(" <- bobdeposit\n"); for (i=0; ialiceclaim.I.datalen; i++) printf("%02x",swap->aliceclaim.txbytes[i]); - printf(" <- aliceclaim\n");*/ + printf(" <- aliceclaim\n"); //basilisk_txlog(swap,&swap->aliceclaim,swap->I.putduration+swap->I.callduration); - return(LP_waitmempool(swap->bobcoin.symbol,swap->bobdeposit.I.destaddr,swap->bobdeposit.I.signedtxid,10)); + return(LP_waitmempool(swap->bobcoin.symbol,swap->bobdeposit.I.destaddr,swap->bobdeposit.I.signedtxid,0,60)); } else printf("error signing aliceclaim suppress.%d vin.(%s)\n",swap->aliceclaim.I.suppress_pubkeys,swap->bobdeposit.I.destaddr); } printf("error with bobdeposit\n"); @@ -1350,7 +1370,7 @@ int32_t LP_verify_alicepayment(struct basilisk_swap *swap,uint8_t *data,int32_t if ( bits256_nonz(swap->alicepayment.I.signedtxid) != 0 ) swap->aliceunconf = 1; basilisk_dontforget_update(swap,&swap->alicepayment); - return(LP_waitmempool(swap->alicecoin.symbol,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,10)); + return(LP_waitmempool(swap->alicecoin.symbol,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,60)); //printf("import alicepayment address.(%s)\n",swap->alicepayment.p2shaddr); //LP_importaddress(swap->alicecoin.symbol,swap->alicepayment.p2shaddr); return(0); @@ -1397,7 +1417,7 @@ int32_t LP_verify_bobpayment(struct basilisk_swap *swap,uint8_t *data,int32_t da printf("%02x",swap->alicespend.txbytes[i]); printf(" <- alicespend\n\n");*/ swap->I.alicespent = 1; - return(LP_waitmempool(swap->bobcoin.symbol,swap->bobpayment.I.destaddr,swap->bobpayment.I.signedtxid,10)); + return(LP_waitmempool(swap->bobcoin.symbol,swap->bobpayment.I.destaddr,swap->bobpayment.I.signedtxid,0,60)); } else printf("error signing aliceclaim suppress.%d vin.(%s)\n",swap->alicespend.I.suppress_pubkeys,swap->bobpayment.I.destaddr); } printf("error validating bobpayment\n"); diff --git a/iguana/exchanges/LP_utxo.c b/iguana/exchanges/LP_utxo.c index 5c327dc99..ab9219412 100644 --- a/iguana/exchanges/LP_utxo.c +++ b/iguana/exchanges/LP_utxo.c @@ -18,17 +18,383 @@ // marketmaker // -uint64_t LP_value_extract(cJSON *obj) +// listunspent: valid for local node, mostly valid for electrum + +// full node + electrum for external listunspent, gettxout to validate +// pruned node + electrum for external listunspent, gettxout to validate +// full node, network for external listunspent, gettxout to validate +// pruned node, network for external listunspent, gettxout to validate +// electrum only, network for gettxout + +// handle spurious errors +// handle invalid data + +//REJECT KMD ccee27b53b52ca61bbc9fdc7de5feb0a12c14d4d92639414d372f002cc3d092f/v0 value.468169379 vs 468169380 ({"bestblock":"080400d4216c02d100004fd2f4f3505ddb507b643785e02703d3412feba39fb1","confirmations":2356,"value":4.68169380,"scriptPubKey":{"asm":"0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842 OP_CHECKSIG","hex":"210224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842ac","reqSigs":1,"type":"pubkey","addresses":["RFssbc211PJdVy1bvcvAG5X2N4ovPAoy5o"]},"version":1,"coinbase":true}) + +uint64_t LP_value_extract(cJSON *obj,int32_t addinterest) { - double val = 0.; uint64_t value; + double val = 0.; uint64_t value = 0; if ( (val= jdouble(obj,"amount")) < SMALLVAL ) val = jdouble(obj,"value"); - if ( val > SMALLVAL ) - value = (val * SATOSHIDEN + 0.0000000049); - else value = 0; + value = (val + 0.0000000049) * SATOSHIDEN; + if ( value != 0 ) + { + if ( addinterest != 0 && jobj(obj,"interest") != 0 ) + value += (jdouble(obj,"interest") * SATOSHIDEN); + } return(value); } +int32_t LP_destaddr(char *destaddr,cJSON *item) +{ + int32_t m,retval = -1; cJSON *addresses,*skey; char *addr; + if ( (skey= jobj(item,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 ) + { + item = jitem(addresses,0); + if ( (addr= jstr(item,0)) != 0 ) + { + safecopy(destaddr,addr,64); + retval = 0; + } + //printf("item.(%s) -> dest.(%s)\n",jprint(item,0),destaddr); + } + return(retval); +} + +int32_t LP_txdestaddr(char *destaddr,bits256 txid,int32_t vout,cJSON *txobj) +{ + int32_t n,retval = -1; cJSON *vouts; + if ( (vouts= jarray(&n,txobj,"vout")) != 0 && vout < n ) + retval = LP_destaddr(destaddr,jitem(vouts,vout)); + return(retval); +} + +struct LP_address *_LP_address(struct iguana_info *coin,char *coinaddr) +{ + struct LP_address *ap = 0; + if ( (ap= _LP_addressfind(coin,coinaddr)) == 0 ) + ap = _LP_addressadd(coin,coinaddr); + return(ap); +} + +struct LP_address *LP_addressfind(struct iguana_info *coin,char *coinaddr) +{ + struct LP_address *ap = 0; + if ( coin != 0 ) + { + portable_mutex_lock(&coin->addrmutex); + ap = _LP_addressfind(coin,coinaddr); + portable_mutex_unlock(&coin->addrmutex); + } + return(ap); +} + +struct LP_address *LP_address(struct iguana_info *coin,char *coinaddr) +{ + struct LP_address *ap = 0; + if ( coin != 0 ) + { + portable_mutex_lock(&coin->addrmutex); + ap = _LP_address(coin,coinaddr); + portable_mutex_unlock(&coin->addrmutex); + } + return(ap); +} + +int32_t LP_address_minmax(uint64_t *minp,uint64_t *maxp,struct LP_address *ap) +{ + struct LP_address_utxo *up,*tmp; int32_t n = 0; + *minp = *maxp = 0; + DL_FOREACH_SAFE(ap->utxos,up,tmp) + { + if ( up->spendheight <= 0 ) + { + if ( up->U.value > *maxp ) + *maxp = up->U.value; + if ( *minp == 0 || up->U.value < *minp ) + *minp = up->U.value; + n++; + } + } + if ( 0 && n > 0 ) + printf("n.%d %s min %.8f max %.8f\n",n,ap->coinaddr,dstr(*minp),dstr(*maxp)); + return(n); +} + +struct LP_utxoinfo *LP_allocated(bits256 txid,int32_t vout) +{ + struct LP_utxoinfo *utxo; + if ( (utxo= _LP_utxofind(0,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + { + char str[65]; printf("%s/v%d not available\n",bits256_str(str,txid),vout); + return(utxo); + } + if ( (utxo= _LP_utxo2find(0,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + { + char str[65]; printf("%s/v%d not available2\n",bits256_str(str,txid),vout); + return(utxo); + } + if ( (utxo= _LP_utxofind(1,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + { + char str[65]; printf("%s/v%d not available\n",bits256_str(str,txid),vout); + return(utxo); + } + if ( (utxo= _LP_utxo2find(1,txid,vout)) != 0 && LP_isavailable(utxo) == 0 ) + { + char str[65]; printf("%s/v%d not available2\n",bits256_str(str,txid),vout); + return(utxo); + } + return(0); +} + +int32_t LP_address_utxo_ptrs(int32_t iambob,struct LP_address_utxo **utxos,int32_t max,struct LP_address *ap) +{ + struct LP_address_utxo *up,*tmp; int32_t n = 0; + portable_mutex_lock(&LP_utxomutex); + DL_FOREACH_SAFE(ap->utxos,up,tmp) + { + if ( up->spendheight <= 0 ) + { + if ( LP_allocated(up->U.txid,up->U.vout) == 0 ) + { + utxos[n++] = up; + if ( n >= max ) + break; + } + } + } + portable_mutex_unlock(&LP_utxomutex); + return(n); +} + +struct LP_address_utxo *LP_address_utxofind(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout) +{ + struct LP_address *ap; struct LP_address_utxo *up,*tmp; + //printf("%s add addr.%s ht.%d\n",coin->symbol,coinaddr,height); + if ( (ap= _LP_address(coin,coinaddr)) != 0 ) + { + DL_FOREACH_SAFE(ap->utxos,up,tmp) + { + if ( vout == up->U.vout && bits256_cmp(up->U.txid,txid) == 0 ) + return(up); + } + } + return(0); +} + +int32_t LP_address_utxoadd(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight) +{ + struct LP_address *ap; struct LP_address_utxo *up,*tmp; int32_t flag,retval = 0; char str[65]; + //printf("%s add addr.%s ht.%d\n",coin->symbol,coinaddr,height); + if ( coin == 0 ) + return(0); + if ( spendheight > 0 ) // dont autocreate entries for spends we dont care about + ap = LP_addressfind(coin,coinaddr); + else ap = LP_address(coin,coinaddr); + if ( ap != 0 ) + { + flag = 0; + DL_FOREACH_SAFE(ap->utxos,up,tmp) + { + if ( vout == up->U.vout && bits256_cmp(up->U.txid,txid) == 0 ) + { + flag = 1; + if ( up->U.height <= 0 && height > 0 && up->U.height != height ) + up->U.height = height, flag |= 2; + if ( spendheight > 0 && up->spendheight != spendheight ) + up->spendheight = spendheight, flag |= 4; + if ( up->U.value == 0 && up->U.value != value ) + up->U.value = value, flag |= 8; + //printf("found >>>>>>>>>> %s %s %s/v%d ht.%d %.8f\n",coin->symbol,coinaddr,bits256_str(str,txid),vout,height,dstr(value)); + break; + } + } + if ( flag == 0 ) + { + up = calloc(1,sizeof(*up)); + up->U.txid = txid; + up->U.vout = vout; + up->U.height = height; + up->U.value = value; + up->spendheight = spendheight; + portable_mutex_lock(&coin->addrmutex); + DL_APPEND(ap->utxos,up); + portable_mutex_unlock(&coin->addrmutex); + retval = 1; + if ( 0 && height > 0 ) + printf("ADDRESS_UTXO >>>>>>>>>> %s %s %s/v%d ht.%d %.8f\n",coin->symbol,coinaddr,bits256_str(str,txid),vout,height,dstr(value)); + } + } // else printf("cant get ap %s %s\n",coin->symbol,coinaddr); + //printf("done %s add addr.%s ht.%d\n",coin->symbol,coinaddr,height); + return(retval); +} + +cJSON *LP_address_item(struct iguana_info *coin,struct LP_address_utxo *up,int32_t electrumret) +{ + cJSON *item = cJSON_CreateObject(); + if ( electrumret == 0 ) + { + jaddbits256(item,"txid",up->U.txid); + jaddnum(item,"vout",up->U.vout); + jaddnum(item,"confirmations",LP_getheight(coin) - up->U.height); + jaddnum(item,"amount",dstr(up->U.value)); + jaddstr(item,"scriptPubKey",""); + } + else + { + jaddbits256(item,"tx_hash",up->U.txid); + jaddnum(item,"tx_pos",up->U.vout); + jaddnum(item,"height",up->U.height); + jadd64bits(item,"value",up->U.value); + } + return(item); +} + +uint64_t _LP_unspents_metric(uint64_t total,int32_t n) { return((total<<16) | (n & 0xffff)); } + +cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrumret) +{ + cJSON *array,*item; int32_t n; uint64_t total; struct LP_address *ap=0,*atmp; struct LP_address_utxo *up,*tmp; + array = cJSON_CreateArray(); + if ( coinaddr != 0 && coinaddr[0] != 0 ) + { + //portable_mutex_lock(&coin->addrmutex); + if ( (ap= _LP_addressfind(coin,coinaddr)) != 0 ) + { + total = n = 0; + DL_FOREACH_SAFE(ap->utxos,up,tmp) + { + //char str[65]; printf("LP_address_utxos %s/v%d %.8f ht.%d spend.%d\n",bits256_str(str,up->U.txid),up->U.vout,dstr(up->U.value),up->U.height,up->spendheight); + if ( up->spendheight <= 0 && up->U.height > 0 ) + { + jaddi(array,LP_address_item(coin,up,electrumret)); + n++; + total += up->U.value; + //printf("new array %s\n",jprint(array,0)); + } + } + ap->total = total; + ap->n = n; + } + //portable_mutex_unlock(&coin->addrmutex); + } + else + { + HASH_ITER(hh,coin->addresses,ap,atmp) + { + if ( ap->total > 0 && ap->n > 0 ) + { + item = cJSON_CreateObject(); + jadd64bits(item,ap->coinaddr,_LP_unspents_metric(ap->total,ap->n)); + jaddi(array,item); + } + } + } + //printf("%s %s utxos.(%s) ap.%p\n",coin->symbol,coinaddr,jprint(array,0),ap); + return(array); +} + +cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electrumret) +{ + cJSON *array,*retjson; int32_t i,n; uint64_t balance = 0; + if ( (array= LP_address_utxos(coin,coinaddr,1)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; isymbol); + jaddstr(retjson,"address",coinaddr); + jaddnum(retjson,"balance",dstr(balance)); + return(retjson); +} + +void LP_postutxos(char *symbol,char *coinaddr) +{ + bits256 zero; char *msg; struct iguana_info *coin; cJSON *array,*reqjson = cJSON_CreateObject(); + if ( (coin= LP_coinfind(symbol)) != 0 && (array= LP_address_utxos(coin,coinaddr,1)) != 0 ) + { + //printf("LP_postutxos pubsock.%d %s %s\n",pubsock,symbol,coin->smartaddr); + if ( cJSON_GetArraySize(array) == 0 ) + free_json(array); + else + { + memset(zero.bytes,0,sizeof(zero)); + jaddstr(reqjson,"method","postutxos"); + jaddstr(reqjson,"coin",symbol); + jaddstr(reqjson,"coinaddr",coinaddr); + jadd(reqjson,"utxos",array); + msg = jprint(reqjson,1); + //printf("post (%s) -> %d\n",msg,LP_mypubsock); + LP_broadcast_message(LP_mypubsock,symbol,symbol,zero,msg); + } + } +} + +int32_t LP_unspents_array(struct iguana_info *coin,char *coinaddr,cJSON *array) +{ + int32_t i,n,v,ht,errs,height,count=0; uint64_t value,val; cJSON *item,*txobj; bits256 txid; + if ( (n= cJSON_GetArraySize(array)) <= 0 ) + return(0); + //printf("%s %s LP_unspents.(%s)\n",coin->symbol,coinaddr,jprint(array,0)); + for (i=0; isymbol,"LBC") == 0 ) + // printf("(%s)\n",jprint(item,0)); + if ( coin->electrum == 0 && (txobj= LP_gettxout(coin->symbol,coinaddr,txid,v)) != 0 ) + { + value = LP_value_extract(txobj,0); + if ( value != 0 && value != val ) + { + char str[65]; printf("REJECT %s %s/v%d value.%llu vs %llu (%s)\n",coin->symbol,bits256_str(str,txid),v,(long long)value,(long long)val,jprint(txobj,0)); + errs++; + } + if ( coin->height != 0 ) + ht = LP_getheight(coin) - jint(txobj,"confirmations"); + else ht = 0; + /*if ( ht != 0 && ht < height-2 ) + { + printf("REJECT %s %s/v%d ht.%d vs %d confs.%d (%s)\n",symbol,bits256_str(str,txid),v,ht,height,jint(txobj,"confirmations"),jprint(item,0)); + errs++; + }*/ + free_json(txobj); + } + if ( errs == 0 ) + { + LP_address_utxoadd(coin,coinaddr,txid,v,val,height,-1); + count++; + } + } + return(count); +} + +char *LP_postedutxos(cJSON *argjson) +{ + int32_t n; char *symbol,*coinaddr; struct LP_address *ap; struct iguana_info *coin; cJSON *array; + //printf("posted.(%s)\n",jprint(argjson,0)); + if ( (coinaddr= jstr(argjson,"coinaddr")) != 0 && (symbol= jstr(argjson,"coin")) != 0 && (coin= LP_coinfind(symbol)) != 0 ) // addsig + { + if ( coin->electrum == 0 || (ap= LP_addressfind(coin,coinaddr)) != 0 ) + { + if ( (array= jarray(&n,argjson,"utxos")) != 0 ) + LP_unspents_array(coin,coinaddr,array); + } + else if ( (array= electrum_address_listunspent(symbol,coin->electrum,&array,coinaddr)) != 0 ) + free_json(array); + } + return(clonestr("{\"result\":\"success\"}")); +} + void LP_utxosetkey(uint8_t *key,bits256 txid,int32_t vout) { memcpy(key,txid.bytes,sizeof(txid)); @@ -38,22 +404,39 @@ void LP_utxosetkey(uint8_t *key,bits256 txid,int32_t vout) struct LP_utxoinfo *_LP_utxofind(int32_t iambob,bits256 txid,int32_t vout) { struct LP_utxoinfo *utxo=0; uint8_t key[sizeof(txid) + sizeof(vout)]; + /*if ( iambob != 0 ) + { + static uint32_t counter; + if ( counter++ < 3 ) + printf("_LP_utxofind deprecated iambob\n"); + return(0); + }*/ LP_utxosetkey(key,txid,vout); - HASH_FIND(hh,LP_utxoinfos[iambob],key,sizeof(key),utxo); + HASH_FIND(hh,G.LP_utxoinfos[iambob],key,sizeof(key),utxo); return(utxo); } struct LP_utxoinfo *_LP_utxo2find(int32_t iambob,bits256 txid2,int32_t vout2) { struct LP_utxoinfo *utxo=0; uint8_t key2[sizeof(txid2) + sizeof(vout2)]; + /*if ( iambob != 0 ) + { + printf("_LP_utxo2find deprecated iambob\n"); + return(0); + }*/ LP_utxosetkey(key2,txid2,vout2); - HASH_FIND(hh2,LP_utxoinfos2[iambob],key2,sizeof(key2),utxo); + HASH_FIND(hh2,G.LP_utxoinfos2[iambob],key2,sizeof(key2),utxo); return(utxo); } struct LP_utxoinfo *LP_utxofind(int32_t iambob,bits256 txid,int32_t vout) { struct LP_utxoinfo *utxo=0; + /*if ( iambob != 0 ) + { + printf("LP_utxofind deprecated iambob\n"); + return(0); + }*/ portable_mutex_lock(&LP_utxomutex); utxo = _LP_utxofind(iambob,txid,vout); portable_mutex_unlock(&LP_utxomutex); @@ -63,6 +446,11 @@ struct LP_utxoinfo *LP_utxofind(int32_t iambob,bits256 txid,int32_t vout) struct LP_utxoinfo *LP_utxo2find(int32_t iambob,bits256 txid2,int32_t vout2) { struct LP_utxoinfo *utxo=0; + /*if ( iambob != 0 ) + { + printf("LP_utxo2find deprecated iambob\n"); + return(0); + }*/ portable_mutex_lock(&LP_utxomutex); utxo = _LP_utxo2find(iambob,txid2,vout2); portable_mutex_unlock(&LP_utxomutex); @@ -103,12 +491,12 @@ struct LP_transaction *LP_transactionadd(struct iguana_info *coin,bits256 txid,i uint64_t LP_txinterestvalue(uint64_t *interestp,char *destaddr,struct iguana_info *coin,bits256 txid,int32_t vout) { - uint64_t interest,value = 0; cJSON *txobj,*sobj,*array; int32_t n=0; + uint64_t interest,value = 0; cJSON *txobj; *interestp = 0; destaddr[0] = 0; - if ( (txobj= LP_gettxout(coin->symbol,txid,vout)) != 0 ) + if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid,vout)) != 0 ) { - if ( (value= LP_value_extract(txobj)) == 0 ) + if ( (value= LP_value_extract(txobj,0)) == 0 ) { char str[65]; printf("%s LP_txvalue.%s strange utxo.(%s) vout.%d\n",coin->symbol,bits256_str(str,txid),jprint(txobj,0),vout); } @@ -120,54 +508,34 @@ uint64_t LP_txinterestvalue(uint64_t *interestp,char *destaddr,struct iguana_inf *interestp = SATOSHIDEN * interest; } } - if ( (sobj= jobj(txobj,"scriptPubKey")) != 0 && (array= jarray(&n,sobj,"addresses")) != 0 ) - { - strcpy(destaddr,jstri(array,0)); - //printf("set destaddr.(%s)\n",destaddr); - if ( n > 1 ) - printf("LP_txinterestvalue warning: violation of 1 output assumption n.%d\n",n); - } else printf("LP_txinterestvalue no addresses found?\n"); + LP_destaddr(destaddr,txobj); //char str[65]; printf("dest.(%s) %.8f <- %s.(%s) txobj.(%s)\n",destaddr,dstr(value),coin->symbol,bits256_str(str,txid),jprint(txobj,0)); free_json(txobj); } //else { char str[65]; printf("null gettxout return %s/v%d\n",bits256_str(str,txid),vout); } return(value); } -int32_t LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter) +cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJSON *txobj) { - struct LP_transaction *tx; char *address; int32_t i,n,height,numvouts,numvins,spentvout; cJSON *txobj,*vins,*vouts,*vout,*vin,*sobj,*addresses; bits256 spenttxid; char str[65]; - if ( (txobj= LP_gettx(coin->symbol,txid)) != 0 ) + struct LP_transaction *tx; int32_t i,height,numvouts,numvins,spentvout; cJSON *vins,*vouts,*vout,*vin; bits256 spenttxid; char str[65]; + if ( txobj != 0 || (txobj= LP_gettx(coin->symbol,txid)) != 0 ) { - //printf("TX.(%s)\n",jprint(txobj,0)); if ( coin->electrum == 0 ) height = LP_txheight(coin,txid); else height = -1; vins = jarray(&numvins,txobj,"vin"); vouts = jarray(&numvouts,txobj,"vout"); + // maybe filter so only addresses we care about are using RAM if ( iter == 0 && vouts != 0 && (tx= LP_transactionadd(coin,txid,height,numvouts,numvins)) != 0 ) { - //printf("create txid numvouts.%d numvins.%d\n",numvouts,numvins); + //printf("create txid %s numvouts.%d numvins.%d\n",bits256_str(str,txid),numvouts,numvins); for (i=0; ioutpoints[i].value = LP_value_extract(vout); + tx->outpoints[i].value = LP_value_extract(vout,0); tx->outpoints[i].interest = SATOSHIDEN * jdouble(vout,"interest"); - if ( (sobj= jobj(vout,"scriptPubKey")) != 0 ) - { - if ( (addresses= jarray(&n,sobj,"addresses")) != 0 && n > 0 ) - { - if ( n > 1 ) - printf("LP_transactioninit: txid.(%s) multiple addresses.[%s]\n",bits256_str(str,txid),jprint(addresses,0)); - if ( (address= jstri(addresses,0)) != 0 && strlen(address) < sizeof(tx->outpoints[i].coinaddr) ) - { - strcpy(tx->outpoints[i].coinaddr,address); - //printf("(%s %.8f) ",address,dstr(tx->outpoints[i].value)); - } else if ( tx->outpoints[i].value != 0 ) - printf("LP_transactioninit: unexpected address.(%s)\n",jprint(addresses,0)); - } - //else if ( tx->outpoints[i].value != 0 ) - // printf("LP_transactioninit: pax tx ht.%d i.%d (%s) n.%d\n",height,i,jprint(vout,0),n); - } + LP_destaddr(tx->outpoints[i].coinaddr,vout); + LP_address_utxoadd(coin,tx->outpoints[i].coinaddr,txid,i,tx->outpoints[i].value,height,-1); } //printf("numvouts.%d\n",numvouts); } @@ -184,20 +552,24 @@ int32_t LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter) { if ( spentvout < tx->numvouts ) { - tx->outpoints[spentvout].spendtxid = txid; - tx->outpoints[spentvout].spendvini = i; - tx->outpoints[spentvout].spendheight = height; - //printf("spend %s %s/v%d at ht.%d\n",coin->symbol,bits256_str(str,tx->txid),spentvout,height); - } else printf("LP_transactioninit: %s spentvout.%d < numvouts.%d\n",bits256_str(str,spenttxid),spentvout,tx->numvouts); + if ( tx->outpoints[spentvout].spendheight <= 0 ) + { + tx->outpoints[spentvout].spendtxid = txid; + tx->outpoints[spentvout].spendvini = i; + tx->outpoints[spentvout].spendheight = height > 0 ? height : 1; + LP_address_utxoadd(coin,tx->outpoints[spentvout].coinaddr,spenttxid,spentvout,tx->outpoints[spentvout].value,-1,height>0?height:1); + if ( 0 && strcmp(coin->symbol,"BTC") != 0 ) + printf("spend %s %s/v%d at ht.%d\n",coin->symbol,bits256_str(str,tx->txid),spentvout,height); + } + } else printf("LP_transactioninit: %s spentvout.%d < numvouts.%d spendheight.%d\n",bits256_str(str,spenttxid),spentvout,tx->numvouts,tx->outpoints[spentvout].spendheight); } //else printf("LP_transactioninit: couldnt find (%s) ht.%d %s\n",bits256_str(str,spenttxid),height,jprint(vin,0)); if ( bits256_cmp(spenttxid,txid) == 0 ) printf("spending same tx's %p vout ht.%d %s.[%d] s%d\n",tx,height,bits256_str(str,txid),tx!=0?tx->numvouts:0,spentvout); } } - free_json(txobj); - return(0); + return(txobj); } //else printf("LP_transactioninit error for %s %s\n",coin->symbol,bits256_str(str,txid)); - return(-1); + return(0); } int32_t LP_txheight(struct iguana_info *coin,bits256 txid) @@ -229,21 +601,18 @@ int32_t LP_txheight(struct iguana_info *coin,bits256 txid) return(height); } -int32_t LP_numconfirms(char *symbol,char *coinaddr,bits256 txid,int32_t mempool) +int32_t LP_numconfirms(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t mempool) { struct iguana_info *coin; int32_t ht,numconfirms = 100; - //#ifndef BASILISK_DISABLEWAITTX cJSON *txobj; if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) return(-1); if ( coin->electrum == 0 ) { numconfirms = -1; - if ( (txobj= LP_gettx(symbol,txid)) != 0 ) + if ( (txobj= LP_gettxout(symbol,coinaddr,txid,vout)) != 0 ) { - if ( coin->electrum == 0 ) - numconfirms = jint(txobj,"confirmations"); - else numconfirms = coin->height - jint(txobj,"height"); + numconfirms = jint(txobj,"confirmations"); free_json(txobj); } else if ( mempool != 0 && LP_mempoolscan(symbol,txid) >= 0 ) @@ -251,12 +620,15 @@ int32_t LP_numconfirms(char *symbol,char *coinaddr,bits256 txid,int32_t mempool) } else { + LP_listunspent_issue(symbol,coinaddr); if ( (ht= LP_txheight(coin,txid)) > 0 && ht <= coin->height ) - numconfirms = (coin->height - ht); - else if ( mempool != 0 && LP_waitmempool(symbol,coinaddr,txid,-1) >= 0 ) - numconfirms = 0; + numconfirms = (LP_getheight(coin) - ht + 1); + else if ( mempool != 0 ) + { + if ( LP_waitmempool(symbol,coinaddr,txid,vout,30) >= 0 ) + numconfirms = 0; + } } - //#endif return(numconfirms); } @@ -272,7 +644,7 @@ int64_t basilisk_txvalue(char *symbol,bits256 txid,int32_t vout) uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout) { - struct LP_transaction *tx; cJSON *txobj; uint64_t value; struct iguana_info *coin; char str[65],str2[65]; + struct LP_transaction *tx; cJSON *txobj=0; uint64_t value; struct iguana_info *coin; char str[65],_coinaddr[65]; if ( bits256_nonz(txid) == 0 ) return(0); if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) @@ -281,8 +653,10 @@ uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout) coinaddr[0] = 0; if ( (tx= LP_transactionfind(coin,txid)) == 0 ) { - LP_transactioninit(coin,txid,0); - LP_transactioninit(coin,txid,1); + txobj = LP_transactioninit(coin,txid,0,0); + txobj = LP_transactioninit(coin,txid,1,txobj); + if ( txobj != 0 ) + free_json(txobj); tx = LP_transactionfind(coin,txid); } if ( tx != 0 ) @@ -291,7 +665,7 @@ uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout) { if ( bits256_nonz(tx->outpoints[vout].spendtxid) != 0 ) { - printf("LP_txvalue %s/v%d is spent at %s\n",bits256_str(str,txid),vout,bits256_str(str2,tx->outpoints[vout].spendtxid)); + //printf("LP_txvalue %s/v%d is spent at %s\n",bits256_str(str,txid),vout,bits256_str(str2,tx->outpoints[vout].spendtxid)); return(0); } else @@ -303,20 +677,28 @@ uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout) strcpy(coinaddr,tx->outpoints[vout].coinaddr); //printf("(%s) return value %.8f + interest %.8f\n",coinaddr,dstr(tx->outpoints[vout].value),dstr(tx->outpoints[vout].interest)); } - return(tx->outpoints[vout].value + tx->outpoints[vout].interest); + return(tx->outpoints[vout].value + 0*tx->outpoints[vout].interest); } } else printf("LP_txvalue vout.%d >= tx->numvouts.%d\n",vout,tx->numvouts); } else { - if ( (txobj= LP_gettxout(coin->symbol,txid,vout)) != 0 ) + if ( (txobj= LP_gettxout(coin->symbol,coinaddr,txid,vout)) != 0 ) { - value = SATOSHIDEN * jdouble(txobj,"value"); - free_json(txobj); - printf("pruned node? LP_txvalue couldnt find %s tx %s, but gettxout %.8f\n",coin->symbol,bits256_str(str,txid),dstr(value)); - return(value); + value = LP_value_extract(txobj,0);//SATOSHIDEN * (jdouble(txobj,"value") + jdouble(txobj,"interest")); + if ( coinaddr == 0 ) + coinaddr = _coinaddr; + LP_destaddr(coinaddr,txobj); + //printf("pruned node? LP_txvalue couldnt find %s tx %s, but gettxout %.8f\n",coin->symbol,bits256_str(str,txid),dstr(value)); + if ( value != 0 ) + { + free_json(txobj); + return(value); + } } - printf("pruned node? LP_txvalue couldnt find %s tx %s\n",coin->symbol,bits256_str(str,txid)); + printf("pruned node? LP_txvalue couldnt find %s tx %s/v%d (%s)\n",coin->symbol,bits256_str(str,txid),vout,txobj!=0?jprint(txobj,0):""); + if ( txobj != 0 ) + free_json(txobj); } return(0); } @@ -324,7 +706,7 @@ uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout) int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2) { //struct LP_utxoinfo *utxo; - uint64_t val,val2=0,txfee,threshold=0; int32_t bypass = 0; char destaddr[64],destaddr2[64]; struct iguana_info *coin = LP_coinfind(symbol); + struct LP_address_utxo *up; uint64_t val,val2=0,txfee,threshold=0; int32_t bypass = 0; char destaddr[64],destaddr2[64]; struct iguana_info *coin = LP_coinfind(symbol); if ( bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 ) { printf("null txid not eligible\n"); @@ -336,6 +718,10 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol if ( bypass != 0 ) val = satoshis; else val = LP_txvalue(destaddr,symbol,txid,vout); + if ( (up= LP_address_utxofind(coin,destaddr,txid,vout)) != 0 && up->spendheight > 0 ) + return(-2); + if ( (up= LP_address_utxofind(coin,destaddr,txid2,vout2)) != 0 && up->spendheight > 0 ) + return(-3); txfee = LP_txfeecalc(LP_coinfind(symbol),0); if ( val >= satoshis && val > (1+LP_MINSIZE_TXFEEMULT)*txfee ) { @@ -357,7 +743,13 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol } } // else printf("no val2\n"); } - char str[65],str2[65]; printf("spent.%d %s txid or value %.8f < %.8f or val2 %.8f < %.8f, %s/v%d %s/v%d or < 10x txfee %.8f\n",iambob,symbol,dstr(val),dstr(satoshis),dstr(val2),dstr(threshold),bits256_str(str,txid),vout,bits256_str(str2,txid2),vout2,dstr(txfee)); + char str[65],str2[65]; + if ( val != 0 && val2 != 0 ) + printf("spent.%d %s txid or value %.8f < %.8f or val2 %.8f < %.8f, %s/v%d %s/v%d or < 10x txfee %.8f\n",iambob,symbol,dstr(val),dstr(satoshis),dstr(val2),dstr(threshold),bits256_str(str,txid),vout,bits256_str(str2,txid2),vout2,dstr(txfee)); + if ( val == 0 ) + LP_address_utxoadd(coin,destaddr,txid,vout,satoshis,-1,1); + if ( val2 == 0 ) + LP_address_utxoadd(coin,destaddr,txid2,vout2,threshold,-1,1); /*for (iter=0; iter<2; iter++) { if ( (utxo= LP_utxofind(iter,txid,vout)) != 0 ) @@ -403,7 +795,7 @@ int32_t LP_inventory_prevent(int32_t iambob,char *symbol,bits256 txid,int32_t vo } if ( utxo->T.spentflag != 0 ) { - char str[65]; printf("prevent adding iambob.%d %s/v%d to inventory\n",iambob,bits256_str(str,txid),vout); + //char str[65]; printf("prevent adding iambob.%d %s/v%d to inventory\n",iambob,bits256_str(str,txid),vout); return(1); } } diff --git a/iguana/exchanges/LP_utxos.c b/iguana/exchanges/LP_utxos.c index 1ddbf750f..33d13d1c4 100644 --- a/iguana/exchanges/LP_utxos.c +++ b/iguana/exchanges/LP_utxos.c @@ -20,7 +20,7 @@ int32_t LP_ismine(struct LP_utxoinfo *utxo) { - if ( utxo != 0 && bits256_cmp(utxo->pubkey,LP_mypub25519) == 0 ) + if ( utxo != 0 && bits256_cmp(utxo->pubkey,G.LP_mypub25519) == 0 ) return(1); else return(0); } @@ -154,46 +154,10 @@ void LP_availableset(struct LP_utxoinfo *utxo) } } -int32_t LP_utxopurge(int32_t allutxos) -{ - char str[65]; struct LP_utxoinfo *utxo,*tmp; int32_t iambob,n = 0; - printf("LP_utxopurge mypub.(%s)\n",bits256_str(str,LP_mypub25519)); - portable_mutex_lock(&LP_utxomutex); - for (iambob=0; iambob<=1; iambob++) - { - HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) - { - if ( LP_isavailable(utxo) > 0 ) - { - if ( allutxos != 0 || LP_ismine(utxo) > 0 ) - { - printf("iambob.%d delete.(%s)\n",iambob,bits256_str(str,utxo->payment.txid)); - HASH_DELETE(hh,LP_utxoinfos[iambob],utxo); - //free(utxo); let the LP_utxoinfos2 free the utxo, should be 1:1 - } else n++; - } else n++; - } - HASH_ITER(hh,LP_utxoinfos2[iambob],utxo,tmp) - { - if ( LP_isavailable(utxo) > 0 ) - { - if ( allutxos != 0 || LP_ismine(utxo) > 0 ) - { - printf("iambob.%d delete2.(%s)\n",iambob,bits256_str(str,utxo->payment.txid)); - HASH_DELETE(hh2,LP_utxoinfos2[iambob],utxo); - free(utxo); - } else n++; - } else n++; - } - } - portable_mutex_unlock(&LP_utxomutex); - return(n); -} - cJSON *LP_inventoryjson(cJSON *item,struct LP_utxoinfo *utxo) { struct _LP_utxoinfo u; - jaddstr(item,"method","utxo"); + //jaddstr(item,"method","oldutxo"); if ( utxo == 0 ) return(item); if ( utxo->gui[0] != 0 ) @@ -242,54 +206,27 @@ cJSON *LP_utxojson(struct LP_utxoinfo *utxo) jaddbits256(item,"pubkey",utxo->pubkey); //jaddnum(item,"profit",utxo->S.profitmargin); jaddstr(item,"base",utxo->coin); - jaddstr(item,"script",utxo->spendscript); + //jaddstr(item,"script",utxo->spendscript); return(item); } -char *LP_utxos(int32_t iambob,struct LP_peerinfo *mypeer,char *symbol,int32_t lastn) -{ - int32_t i,n,m; uint64_t val,val2; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo,*tmp; cJSON *utxosjson = cJSON_CreateArray(); - //n = mypeer != 0 ? mypeer->numutxos : 0; - if ( lastn <= 0 ) - lastn = LP_PROPAGATION_SLACK * 2; - HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) - { - //char str[65]; printf("check %s.%s\n",utxo->coin,bits256_str(str,utxo->payment.txid)); - if ( (symbol == 0 || symbol[0] == 0 || strcmp(symbol,utxo->coin) == 0) && utxo->T.spentflag == 0 ) - { - u = (iambob != 0) ? utxo->deposit : utxo->fee; - if ( LP_iseligible(&val,&val2,utxo->iambob,utxo->coin,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,u.txid,u.vout) == 0 ) - { - char str[65]; printf("iambob.%d not eligible (%.8f %.8f) %s %s/v%d\n",iambob,dstr(val),dstr(val2),utxo->coin,bits256_str(str,utxo->payment.txid),utxo->payment.vout); - continue; - } else jaddi(utxosjson,LP_utxojson(utxo)); - } - } - if ( (n= cJSON_GetArraySize(utxosjson)) > lastn ) - { - m = n - lastn; - for (i=0; i= %d\n",utxo->T.spentflag,LP_iseligible(&srcvalue,&srcvalue2,utxo->iambob,symbol,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,utxo->fee.txid,utxo->fee.vout),dstr(destsatoshis),dstr(utxo->S.satoshis),utxo->coin,bits256_str(str,utxo->payment.txid),LP_isavailable(utxo) > 0,LP_ismine(utxo) > 0,utxo->S.satoshis >= destsatoshis); if ( strcmp(symbol,utxo->coin) != 0 ) continue; if ( LP_isavailable(utxo) > 0 && LP_ismine(utxo) > 0 ) { - if ( utxo->S.satoshis >= destsatoshis/2 && (bestutxo == 0 || (bestutxo->S.satoshis < destsatoshis && utxo->S.satoshis >= destsatoshis) || (bestutxo->S.satoshis >= destsatoshis && utxo->S.satoshis < bestutxo->S.satoshis)) ) + if ( utxo->S.satoshis >= destsatoshis && (bestutxo == 0 || (bestutxo->S.satoshis < destsatoshis && utxo->S.satoshis >= destsatoshis) || (bestutxo->S.satoshis >= destsatoshis && utxo->S.satoshis < bestutxo->S.satoshis)) ) { if ( LP_iseligible(&srcvalue,&srcvalue2,utxo->iambob,symbol,utxo->payment.txid,utxo->payment.vout,utxo->S.satoshis,utxo->fee.txid,utxo->fee.vout) == 0 ) { @@ -306,29 +243,9 @@ struct LP_utxoinfo *LP_utxo_bestfit(char *symbol,uint64_t destsatoshis) void LP_spentnotify(struct LP_utxoinfo *utxo,int32_t selector) { - //cJSON *argjson; struct _LP_utxoinfo u; char *msg; if ( utxo == 0 ) return; utxo->T.spentflag = (uint32_t)time(NULL); - if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 ) - LP_mypeer->numutxos--; - /*if ( LP_mypubsock >= 0 ) - { - argjson = cJSON_CreateObject(); - jaddstr(argjson,"method","checktxid"); - jaddbits256(argjson,"txid",utxo->payment.txid); - jaddnum(argjson,"vout",utxo->payment.vout); - if ( selector != 0 ) - { - if ( bits256_nonz(utxo->deposit.txid) != 0 ) - u = utxo->deposit; - else u = utxo->fee; - jaddbits256(argjson,"checktxid",u.txid); - jaddnum(argjson,"checkvout",u.vout); - } - msg = jprint(argjson,1); - /LP_send(LP_mypubsock,msg,(int32_t)strlen(msg)+1,1); - }*/ } char *LP_spentcheck(cJSON *argjson) @@ -349,8 +266,8 @@ char *LP_spentcheck(cJSON *argjson) } if ( LP_txvalue(0,utxo->coin,checktxid,checkvout) == 0 ) { - if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 ) - LP_mypeer->numutxos--; + //if ( LP_mypeer != 0 && LP_mypeer->numutxos > 0 ) + // LP_mypeer->numutxos--; utxo->T.spentflag = (uint32_t)time(NULL); retval++; printf("indeed txid was spent\n"); @@ -362,45 +279,20 @@ char *LP_spentcheck(cJSON *argjson) return(clonestr("{\"error\":\"cant find txid to check spent status\"}")); } -void LP_utxo_clientpublish(struct LP_utxoinfo *utxo) -{ - bits256 zero; char *msg; - if ( LP_isunspent(utxo) > 0 ) - { - memset(zero.bytes,0,sizeof(zero)); - msg = jprint(LP_utxojson(utxo),1); - LP_broadcast_message(LP_mypubsock,utxo->coin,"",zero,msg); - } - /*struct LP_peerinfo *peer,*tmp; cJSON *retjson; char *retstr; int32_t n = 0; - HASH_ITER(hh,LP_peerinfos,peer,tmp) - { - if ( (retstr= issue_LP_notifyutxo(peer->ipaddr,peer->port,utxo)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( jobj(retjson,"error") == 0 ) - { - utxo->T.lasttime = (uint32_t)time(NULL); - n++; - } - free_json(retjson); - } - free(retstr); - } - //if ( utxo->T.lasttime != 0 ) - // return(0); - } - return(n);*/ -} - -struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bits256 txid,int32_t vout,int64_t value,bits256 txid2,int32_t vout2,int64_t value2,char *spendscript,char *coinaddr,bits256 pubkey,char *gui,uint32_t sessionid) +struct LP_utxoinfo *LP_utxoadd(int32_t iambob,char *symbol,bits256 txid,int32_t vout,int64_t value,bits256 txid2,int32_t vout2,int64_t value2,char *coinaddr,bits256 pubkey,char *gui,uint32_t sessionid) { uint64_t val,val2=0,tmpsatoshis,txfee; int32_t spendvini,numconfirms,selector; bits256 spendtxid; struct iguana_info *coin; struct _LP_utxoinfo u; struct LP_utxoinfo *utxo = 0; - if ( symbol == 0 || symbol[0] == 0 || spendscript == 0 || spendscript[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 || vout < 0 || vout2 < 0 || value <= 0 || value2 <= 0 || sessionid == 0 ) + if ( symbol == 0 || symbol[0] == 0 || coinaddr == 0 || coinaddr[0] == 0 || bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 || vout < 0 || vout2 < 0 || value <= 0 || value2 <= 0 )//|| sessionid == 0 ) { - printf("session.%u malformed addutxo %d %d %d %d %d %d %d %d %d\n",sessionid,symbol == 0,spendscript == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(txid2) == 0,vout < 0,vout2 < 0,value <= 0,value2 <= 0); + char str[65],str2[65]; printf("REJECT %s iambob.%d %s utxoadd.(%.8f %.8f) %s %s\n",coinaddr,iambob,symbol,dstr(value),dstr(value2),bits256_str(str,txid),bits256_str(str2,txid2)); + printf("session.%u addutxo %d %d %d %d %d %d %d %d\n",sessionid,symbol == 0,coinaddr == 0,bits256_nonz(txid) == 0,bits256_nonz(txid2) == 0,vout < 0,vout2 < 0,value <= 0,value2 <= 0); return(0); } + /*if ( iambob != 0 ) + { + printf("deprecated bob utxos\n"); + return(0); + }*/ if ( (coin= LP_coinfind(symbol)) == 0 || (IAMLP == 0 && coin->inactive != 0) ) { //printf("LP_utxoadd reject inactive %s\n",symbol); @@ -411,48 +303,33 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit { if ( value2 > 2*txfee ) tmpsatoshis = (((value2 - 2*txfee) / 9) << 3); - else return(0); + else + { + printf("value2 %.8f <= 2 * %.8f\n",dstr(value2),dstr(txfee)); + return(0); + } } else tmpsatoshis = (value - txfee); - char str[65],str2[65],dispflag = (iambob == 0); - if ( iambob == 0 && bits256_cmp(pubkey,LP_mypub25519) != 0 ) + char str[65],str2[65],dispflag = 0;//(iambob == 0); + if ( iambob == 0 && bits256_cmp(pubkey,G.LP_mypub25519) != 0 ) { printf("trying to add Alice utxo when not mine? %s/v%d\n",bits256_str(str,txid),vout); return(0); } - /*numconfirms = -1; - if ( (txobj= LP_gettx(symbol,txid)) != 0 ) - { - if ( coin->electrum == 0 ) - numconfirms = jint(txobj,"confirmations"); - else numconfirms = coin->height - jint(txobj,"height"); - free_json(txobj); - } - numconfirms = -1; - if ( (txobj= LP_gettx(symbol,txid2)) != 0 ) - { - if ( coin->electrum == 0 ) - numconfirms = jint(txobj,"confirmations"); - else numconfirms = coin->height - jint(txobj,"height"); - free_json(txobj); - } - if ( numconfirms <= 0 ) - { - printf("LP_utxoadd reject2 numconfirms.%d\n",numconfirms); - return(0); - }*/ if ( coin->inactive == 0 ) { if ( LP_iseligible(&val,&val2,iambob,symbol,txid,vout,tmpsatoshis,txid2,vout2) <= 0 ) { - printf("iambob.%d utxoadd %s inactive.%u got ineligible txid value %.8f:%.8f, value2 %.8f:%.8f, tmpsatoshis %.8f\n",iambob,symbol,coin->inactive,dstr(value),dstr(val),dstr(value2),dstr(val2),dstr(tmpsatoshis)); + static uint32_t counter; + if ( counter++ < 3 ) + printf("iambob.%d utxoadd %s inactive.%u got ineligible txid value %.8f:%.8f, value2 %.8f:%.8f, tmpsatoshis %.8f\n",iambob,symbol,coin->inactive,dstr(value),dstr(val),dstr(value2),dstr(val2),dstr(tmpsatoshis)); return(0); } - if ( (numconfirms= LP_numconfirms(symbol,coinaddr,txid,0)) <= 0 ) + if ( (numconfirms= LP_numconfirms(symbol,coinaddr,txid,vout,0)) <= 0 ) { printf("LP_utxoadd reject numconfirms.%d %s.%s\n",numconfirms,symbol,bits256_str(str,txid)); return(0); } - if ( (numconfirms= LP_numconfirms(symbol,coinaddr,txid2,0)) <= 0 ) + if ( (numconfirms= LP_numconfirms(symbol,coinaddr,txid2,vout2,0)) <= 0 ) { printf("LP_utxoadd reject2 numconfirms.%d\n",numconfirms); return(0); @@ -463,6 +340,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit val = value; val2 = value2; } + dispflag = 0; if ( dispflag != 0 ) printf("%.8f %.8f %s iambob.%d %s utxoadd.(%.8f %.8f) %s %s\n",dstr(val),dstr(val2),coinaddr,iambob,symbol,dstr(value),dstr(value2),bits256_str(str,txid),bits256_str(str2,txid2)); dispflag = 1; @@ -474,7 +352,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit printf("duplicate %.8f %.8f %.8f vs utxo.(%.8f %.8f %.8f)\n",dstr(value),dstr(value2),dstr(tmpsatoshis),dstr(utxo->payment.value),dstr(utxo->deposit.value),dstr(utxo->S.satoshis)); } u = (utxo->iambob != 0) ? utxo->deposit : utxo->fee; - if ( bits256_cmp(txid,utxo->payment.txid) != 0 || bits256_cmp(txid2,u.txid) != 0 || vout != utxo->payment.vout || value != utxo->payment.value || tmpsatoshis != utxo->S.satoshis || vout2 != u.vout || value2 != u.value || strcmp(symbol,utxo->coin) != 0 || strcmp(spendscript,utxo->spendscript) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || bits256_cmp(pubkey,utxo->pubkey) != 0 ) + if ( bits256_cmp(txid,utxo->payment.txid) != 0 || bits256_cmp(txid2,u.txid) != 0 || vout != utxo->payment.vout || value != utxo->payment.value || tmpsatoshis != utxo->S.satoshis || vout2 != u.vout || value2 != u.value || strcmp(symbol,utxo->coin) != 0 || strcmp(coinaddr,utxo->coinaddr) != 0 || bits256_cmp(pubkey,utxo->pubkey) != 0 ) { utxo->T.errors++; char str[65],str2[65],str3[65],str4[65],str5[65],str6[65]; @@ -484,7 +362,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit // utxo->T.spentflag = (uint32_t)time(NULL); printf("original utxo pair not valid\n"); if ( dispflag != 0 ) - printf("error on subsequent utxo iambob.%d %.8f %.8f add.(%s %s) when.(%s %s) %d %d %d %d %d %d %d %d %d %d %d pubkeys.(%s vs %s)\n",iambob,dstr(val),dstr(val2),bits256_str(str,txid),bits256_str(str2,txid2),bits256_str(str3,utxo->payment.txid),bits256_str(str4,utxo->deposit.txid),bits256_cmp(txid,utxo->payment.txid) != 0,bits256_cmp(txid2,u.txid) != 0,vout != utxo->payment.vout,tmpsatoshis != utxo->S.satoshis,vout2 != u.vout,value2 != u.value,strcmp(symbol,utxo->coin) != 0,strcmp(spendscript,utxo->spendscript) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,bits256_cmp(pubkey,utxo->pubkey) != 0,value != utxo->payment.value,bits256_str(str5,pubkey),bits256_str(str6,utxo->pubkey)); + printf("error on subsequent utxo iambob.%d %.8f %.8f add.(%s %s) when.(%s %s) %d %d %d %d %d %d %d %d %d %d pubkeys.(%s vs %s)\n",iambob,dstr(val),dstr(val2),bits256_str(str,txid),bits256_str(str2,txid2),bits256_str(str3,utxo->payment.txid),bits256_str(str4,utxo->deposit.txid),bits256_cmp(txid,utxo->payment.txid) != 0,bits256_cmp(txid2,u.txid) != 0,vout != utxo->payment.vout,tmpsatoshis != utxo->S.satoshis,vout2 != u.vout,value2 != u.value,strcmp(symbol,utxo->coin) != 0,strcmp(coinaddr,utxo->coinaddr) != 0,bits256_cmp(pubkey,utxo->pubkey) != 0,value != utxo->payment.value,bits256_str(str5,pubkey),bits256_str(str6,utxo->pubkey)); utxo = 0; } } @@ -495,6 +373,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit //else if ( profitmargin > SMALLVAL ) // utxo->S.profitmargin = profitmargin; utxo->T.lasttime = (uint32_t)time(NULL); + //printf("return existing utxo[%d] %s %s\n",iambob,bits256_str(str,utxo->payment.txid),bits256_str(str2,iambob != 0 ? utxo->deposit.txid : utxo->fee.txid)); return(utxo); } } @@ -504,7 +383,7 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit safecopy(utxo->gui,gui,sizeof(utxo->gui)); safecopy(utxo->coin,symbol,sizeof(utxo->coin)); safecopy(utxo->coinaddr,coinaddr,sizeof(utxo->coinaddr)); - safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript)); + //safecopy(utxo->spendscript,spendscript,sizeof(utxo->spendscript)); utxo->payment.txid = txid; utxo->payment.vout = vout; utxo->payment.value = value; @@ -524,31 +403,24 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit LP_utxosetkey(utxo->key,txid,vout); LP_utxosetkey(utxo->key2,txid2,vout2); if ( LP_ismine(utxo) > 0 ) - utxo->T.sessionid = LP_sessionid; + utxo->T.sessionid = G.LP_sessionid; else utxo->T.sessionid = sessionid; if ( coin->inactive == 0 && (selector= LP_mempool_vinscan(&spendtxid,&spendvini,symbol,coinaddr,txid,vout,txid2,vout2)) >= 0 ) { printf("utxoadd selector.%d spent in mempool %s vini.%d",selector,bits256_str(str,spendtxid),spendvini); utxo->T.spentflag = (uint32_t)time(NULL); } - printf("U.%d %s %.8f %.8f addutxo.%d pubkey.%s session.%u\n",LP_mypeer!=0?LP_mypeer->numutxos:-1,symbol,dstr(value),dstr(value2),LP_ismine(utxo) > 0,bits256_str(str,utxo->pubkey),utxo->T.sessionid); + //printf(" %s %.8f %.8f %p addutxo.%d (%s %s) session.%u iambob.%d <<<<<<<<<<<<<<<\n",symbol,dstr(value),dstr(value2),utxo,LP_ismine(utxo) > 0,bits256_str(str,utxo->payment.txid),bits256_str(str2,iambob != 0 ? utxo->deposit.txid : utxo->fee.txid),utxo->T.sessionid,iambob); portable_mutex_lock(&LP_utxomutex); - HASH_ADD_KEYPTR(hh,LP_utxoinfos[iambob],utxo->key,sizeof(utxo->key),utxo); + HASH_ADD_KEYPTR(hh,G.LP_utxoinfos[iambob],utxo->key,sizeof(utxo->key),utxo); if ( _LP_utxo2find(iambob,txid2,vout2) == 0 ) - HASH_ADD_KEYPTR(hh2,LP_utxoinfos2[iambob],utxo->key2,sizeof(utxo->key2),utxo); + HASH_ADD_KEYPTR(hh2,G.LP_utxoinfos2[iambob],utxo->key2,sizeof(utxo->key2),utxo); portable_mutex_unlock(&LP_utxomutex); - /*if ( 0 && coin->electrum == 0 ) - { - LP_address_utxoadd(coin,coinaddr,txid,vout,value); - LP_address_utxoadd(coin,coinaddr,txid2,vout2,value2); - }*/ if ( iambob != 0 ) { - if ( LP_mypeer != 0 ) - LP_mypeer->numutxos++; if ( LP_ismine(utxo) > 0 ) { - LP_utxo_clientpublish(utxo); + //LP_utxo_clientpublish(utxo); if ( LP_mypeer != 0 ) utxo->T.lasttime = (uint32_t)time(NULL); } @@ -556,110 +428,16 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit return(utxo); } -struct LP_utxoinfo *LP_utxoaddjson(int32_t iambob,int32_t pubsock,cJSON *argjson) -{ - struct LP_utxoinfo *utxo; - if ( jobj(argjson,"iambob") == 0 || iambob != jint(argjson,"iambob") ) - { - printf("LP_utxoaddjson: iambob.%d != arg.%d obj.%p (%s)\n",iambob,jint(argjson,"iambob"),jobj(argjson,"iambob"),jprint(argjson,0)); - return(0); - } - portable_mutex_lock(&LP_UTXOmutex); - utxo = LP_utxoadd(iambob,pubsock,jstr(argjson,"coin"),jbits256(argjson,"txid"),jint(argjson,"vout"),j64bits(argjson,"value"),jbits256(argjson,"txid2"),jint(argjson,"vout2"),j64bits(argjson,"value2"),jstr(argjson,"script"),jstr(argjson,"address"),jbits256(argjson,"pubkey"),jstr(argjson,"gui"),juint(argjson,"session")); - if ( LP_ismine(utxo) > 0 && utxo->T.lasttime == 0 ) - { - utxo->T.lasttime = (uint32_t)time(NULL); - printf("set lasttime!\n"); - } - portable_mutex_unlock(&LP_UTXOmutex); - return(utxo); -} - -int32_t LP_utxosparse(char *destipaddr,uint16_t destport,char *retstr,uint32_t now) +cJSON *LP_inventory(char *symbol) { - struct LP_peerinfo *destpeer,*peer; uint32_t argipbits; char *argipaddr; uint16_t argport,pushport,subport; cJSON *array,*item; int32_t i,n=0; bits256 txid; struct LP_utxoinfo *utxo; - //printf("parse.(%s)\n",retstr); - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - if ( (n= cJSON_GetArraySize(array)) > 0 ) - { - for (i=0; iT.lasttime = now; - } - } - if ( (destpeer= LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport)) != 0 ) - { - destpeer->numutxos = n; - } - } - free_json(array); - } - return(n); -} - -int32_t LP_utxosquery(struct LP_peerinfo *mypeer,int32_t mypubsock,char *destipaddr,uint16_t destport,char *coin,int32_t lastn,char *myipaddr,uint16_t myport,int32_t maxentries) -{ - char *retstr; struct LP_peerinfo *peer; uint32_t now; int32_t retval = -1; - peer = LP_peerfind((uint32_t)calc_ipbits(destipaddr),destport); - if ( coin == 0 ) - coin = ""; - //printf("utxo query.(%s)\n",destipaddr); - if ( IAMLP != 0 ) - retstr = issue_LP_getutxos(destipaddr,destport,coin,lastn,myipaddr,myport,mypeer != 0 ? mypeer->numpeers : 0,maxentries); - else retstr = issue_LP_clientgetutxos(destipaddr,destport,coin,maxentries); - if ( retstr != 0 ) - { - now = (uint32_t)time(NULL); - retval = LP_utxosparse(destipaddr,destport,retstr,now); - //printf("got.(%s)\n",retstr); - free(retstr); - /*i = 0; - if ( lastn >= mypeer->numutxos ) - firsti = -1; - else firsti = (mypeer->numutxos - lastn); - HASH_ITER(hh,LP_utxoinfos,utxo,tmp) - { - if ( i++ < firsti ) - continue; - if ( utxo->lasttime != now && strcmp(utxo->ipaddr,"127.0.0.1") != 0 ) - { - char str[65]; printf("{%s:%u %s} ",utxo->ipaddr,utxo->port,bits256_str(str,utxo->txid)); - flag++; - if ( (retstr= issue_LP_notifyutxo(destipaddr,destport,utxo)) != 0 ) - free(retstr); - } - } - if ( flag != 0 ) - printf(" <- missing utxos\n");*/ - } - return(retval); -} - -cJSON *LP_inventory(char *symbol,int32_t iambob) -{ - struct LP_utxoinfo *utxo,*tmp; struct _LP_utxoinfo u; char *myipaddr; cJSON *array; uint64_t val,val2; + struct LP_utxoinfo *utxo,*tmp; struct _LP_utxoinfo u; char *myipaddr; cJSON *array; uint64_t val,val2; int32_t iambob = 0; struct iguana_info *coin; array = cJSON_CreateArray(); if ( LP_mypeer != 0 ) myipaddr = LP_mypeer->ipaddr; else myipaddr = "127.0.0.1"; - HASH_ITER(hh,LP_utxoinfos[iambob],utxo,tmp) + if ( (coin= LP_coinfind(symbol)) != 0 ) + LP_listunspent_both(symbol,coin->smartaddr); + HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,tmp) { char str[65]; //printf("iambob.%d iterate %s\n",iambob,bits256_str(str,LP_mypub25519)); @@ -673,8 +451,8 @@ cJSON *LP_inventory(char *symbol,int32_t iambob) printf("%s %s ineligible %.8f %.8f\n",utxo->coin,bits256_str(str,u.txid),dstr(val),dstr(val2)); continue; } - if ( iambob != 0 ) - LP_utxo_clientpublish(utxo); + //if ( iambob != 0 ) + // LP_utxo_clientpublish(utxo); jaddi(array,LP_inventoryjson(cJSON_CreateObject(),utxo)); } else if ( LP_ismine(utxo) > 0 && strcmp(symbol,utxo->coin) == 0 ) @@ -713,67 +491,63 @@ int32_t LP_nearestvalue(int32_t iambob,uint64_t *values,int32_t n,uint64_t targe return(mini); } -uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 myprivkey,bits256 mypub) +int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 myprivkey,bits256 mypub) { - char *script,destaddr[64]; struct LP_utxoinfo *utxo; cJSON *array,*item; bits256 txid,deposittxid; int32_t used,i,n,cmpflag,iambob,vout,depositvout; uint64_t *values=0,satoshis,txfee,depositval,value,total = 0; int64_t targetval; - if ( coin == 0 ) + int32_t enable_utxos = 0; + char *script,destaddr[64]; struct LP_utxoinfo *utxo; cJSON *array,*item; bits256 txid,deposittxid; int32_t used,i,flag=0,height,n,cmpflag,iambob,vout,depositvout; uint64_t *values=0,satoshis,txfee,depositval,value,total = 0; int64_t targetval; + if ( coin == 0 || coin->inactive != 0 ) { printf("coin not active\n"); return(0); } //printf("privkey init.(%s) %s\n",coin->symbol,coin->smartaddr); + if ( coin->inactive == 0 ) + LP_listunspent_issue(coin->symbol,coin->smartaddr); if ( coin->inactive == 0 && (array= LP_listunspent(coin->symbol,coin->smartaddr)) != 0 ) { txfee = LP_txfeecalc(coin,0); if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) { + //printf("LP_privkey_init %s %s\n",coin->symbol,jprint(array,0)); for (iambob=0; iambob<=1; iambob++) { if ( iambob == 0 ) values = calloc(n,sizeof(*values)); else memset(values,0,n * sizeof(*values)); - //if ( iambob == 0 && IAMLP != 0 ) - // continue; used = 0; for (i=0; ielectrum == 0 ) { - //satoshis = SATOSHIDEN * jdouble(item,"amount"); - //if ( satoshis == 0 ) - // satoshis = SATOSHIDEN * jdouble(item,"value"); - satoshis = LP_txvalue(destaddr,coin->symbol,jbits256(item,"txid"),juint(item,"vout")); - if ( LP_inventory_prevent(iambob,coin->symbol,jbits256(item,"txid"),juint(item,"vout")) == 0 && jint(item,"confirmations") > 0 ) - { - //printf("%s\n",jprint(item,0)); - values[i] = satoshis; - } else used++; + txid = jbits256(item,"txid"); + vout = juint(item,"vout"); + value = LP_value_extract(item,0); + height = LP_getheight(coin) - jint(item,"confirmations"); } else { - //{"value":1000000,"tx_hash":"4e4f818c53486c0576693b4cd379849e5ff95538b38e4100f48884073a4e7636","tx_pos":0,"height":484877} - satoshis = j64bits(item,"value"); - satoshis = LP_txvalue(destaddr,coin->symbol,jbits256(item,"tx_hash"),juint(item,"tx_pos")); - if ( LP_inventory_prevent(iambob,coin->symbol,jbits256(item,"tx_hash"),juint(item,"tx_pos")) == 0 && jint(item,"height") < coin->height ) - { - //printf("%s\n",jprint(item,0)); - values[i] = satoshis; - } - else - { - printf("skip.(%s) coinht.%d\n",jprint(item,0),coin->height); - used++; - } + txid = jbits256(item,"tx_hash"); + vout = juint(item,"tx_pos"); + value = j64bits(item,"value"); + height = jint(item,"height"); } - //printf("%.8f ",dstr(satoshis)); + satoshis = LP_txvalue(destaddr,coin->symbol,txid,vout); + if ( satoshis != 0 && satoshis != value ) + printf("unexpected privkey_init value mismatch %.8f vs %.8f (%s) %.8f %.8f\n",dstr(satoshis),dstr(value),jprint(item,0),jdouble(item,"amount"),jdouble(item,"interest")); + if ( LP_inventory_prevent(iambob,coin->symbol,txid,vout) == 0 && height > 0 ) + { + //printf("%s\n",jprint(item,0)); + values[i] = satoshis; + flag += LP_address_utxoadd(coin,destaddr,txid,vout,satoshis,height,-1); + } else used++; } //printf("array.%d\n",n); while ( used < n-1 ) { - for (i=0; i= 0 ) { item = jitem(array,i); @@ -796,7 +570,7 @@ uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypr else targetval = (depositval / 9) * 8 + 2*txfee; if ( targetval < txfee*2 ) targetval = txfee*2; - printf("iambob.%d i.%d deposit %.8f min %.8f target %.8f\n",iambob,i,dstr(depositval),dstr((1+LP_MINSIZE_TXFEEMULT)*txfee),dstr(targetval)); + //printf("iambob.%d i.%d deposit %.8f min %.8f target %.8f\n",iambob,i,dstr(depositval),dstr((1+LP_MINSIZE_TXFEEMULT)*txfee),dstr(targetval)); if ( depositval < (1+LP_MINSIZE_TXFEEMULT)*txfee ) continue; i = -1; @@ -832,14 +606,14 @@ uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypr portable_mutex_lock(&LP_UTXOmutex); if ( iambob != 0 ) { - if ( (utxo= LP_utxoadd(1,mypubsock,coin->symbol,txid,vout,value,deposittxid,depositvout,depositval,script,coin->smartaddr,mypub,LP_gui,LP_sessionid)) != 0 ) + if ( (utxo= LP_utxoadd(1,coin->symbol,txid,vout,value,deposittxid,depositvout,depositval,coin->smartaddr,mypub,LP_gui,G.LP_sessionid)) != 0 ) { } } else { //printf("call utxoadd\n"); - if ( (utxo= LP_utxoadd(0,mypubsock,coin->symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coin->smartaddr,mypub,LP_gui,LP_sessionid)) != 0 ) + if ( (utxo= LP_utxoadd(0,coin->symbol,deposittxid,depositvout,depositval,txid,vout,value,coin->smartaddr,mypub,LP_gui,G.LP_sessionid)) != 0 ) { } } @@ -849,14 +623,18 @@ uint64_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypr } //else printf("nothing near i.%d\n",i); } else break; } - if ( iambob == 1 ) - free(values); + if ( enable_utxos == 0 ) + break; } } free_json(array); + if ( flag != 0 ) + LP_postutxos(coin->symbol,coin->smartaddr); } + if ( values != 0 ) + free(values); //printf("privkey.%s %.8f\n",symbol,dstr(total)); - return(total); + return(flag); } char *LP_secretaddresses(void *ctx,char *passphrase,int32_t n,uint8_t taddr,uint8_t pubtype) @@ -903,7 +681,7 @@ char *LP_secretaddresses(void *ctx,char *passphrase,int32_t n,uint8_t taddr,uint bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguana_info *coin,char *passphrase,char *wifstr) { - static uint32_t counter; + //static uint32_t counter; bits256 privkey,userpub,userpass,checkkey; char tmpstr[128]; cJSON *retjson; uint8_t tmptype; if ( passphrase != 0 && passphrase[0] != 0 ) { @@ -927,53 +705,110 @@ bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguan if ( coin->counter == 0 ) { coin->counter++; + memcpy(G.LP_pubsecp,coin->pubkey33,33); bitcoin_priv2wif(coin->wiftaddr,tmpstr,privkey,coin->wiftype); - bitcoin_addr2rmd160(coin->taddr,&tmptype,LP_myrmd160,coin->smartaddr); - LP_privkeyadd(privkey,LP_myrmd160); + bitcoin_addr2rmd160(coin->taddr,&tmptype,G.LP_myrmd160,coin->smartaddr); + LP_privkeyadd(privkey,G.LP_myrmd160); if ( 0 && (coin->pubtype != 60 || strcmp(coin->symbol,"KMD") == 0) ) printf("%s (%s) %d wif.(%s) (%s)\n",coin->symbol,coin->smartaddr,coin->pubtype,tmpstr,passphrase); - if ( counter++ == 0 ) + if ( G.counter++ == 0 ) { - bitcoin_priv2wif(coin->wiftaddr,USERPASS_WIFSTR,privkey,188); - bitcoin_wif2priv(coin->wiftaddr,&tmptype,&checkkey,USERPASS_WIFSTR); + bitcoin_priv2wif(coin->wiftaddr,G.USERPASS_WIFSTR,privkey,188); + bitcoin_wif2priv(coin->wiftaddr,&tmptype,&checkkey,G.USERPASS_WIFSTR); if ( bits256_cmp(checkkey,privkey) != 0 ) { char str[65],str2[65]; - printf("FATAL ERROR converting USERPASS_WIFSTR %s -> %s != %s\n",USERPASS_WIFSTR,bits256_str(str,checkkey),bits256_str(str2,privkey)); + printf("FATAL ERROR converting USERPASS_WIFSTR %s -> %s != %s\n",G.USERPASS_WIFSTR,bits256_str(str,checkkey),bits256_str(str2,privkey)); exit(-1); } - conv_NXTpassword(userpass.bytes,pubkeyp->bytes,(uint8_t *)USERPASS_WIFSTR,(int32_t)strlen(USERPASS_WIFSTR)); + conv_NXTpassword(userpass.bytes,pubkeyp->bytes,(uint8_t *)G.USERPASS_WIFSTR,(int32_t)strlen(G.USERPASS_WIFSTR)); userpub = curve25519(userpass,curve25519_basepoint9()); - printf("userpass.(%s)\n",bits256_str(USERPASS,userpub)); + printf("userpass.(%s)\n",bits256_str(G.USERPASS,userpub)); } - if ( coin->electrum == 0 && (retjson= LP_importprivkey(coin->symbol,tmpstr,coin->smartaddr,-1)) != 0 ) + if ( coin->electrum == 0 ) { - if ( jobj(retjson,"error") != 0 ) + LP_listunspent_issue(coin->symbol,coin->smartaddr); + if ( (retjson= LP_importprivkey(coin->symbol,tmpstr,coin->smartaddr,-1)) != 0 ) { - printf("cant importprivkey.%s -> (%s), abort session\n",coin->symbol,jprint(retjson,1)); - exit(-1); - } + if ( jobj(retjson,"error") != 0 ) + { + printf("cant importprivkey.%s -> (%s), abort session\n",coin->symbol,jprint(retjson,1)); + exit(-1); + } + } else free_json(retjson); } } - LP_mypub25519 = *pubkeyp = curve25519(privkey,curve25519_basepoint9()); - LP_mypriv25519 = privkey; - //printf("privkey.(%s) -> LP_mypub25519.(%s)\n",bits256_str(str,privkey),bits256_str(str2,LP_mypub25519)); + vcalc_sha256(0,checkkey.bytes,privkey.bytes,sizeof(privkey)); + checkkey.bytes[0] &= 248, checkkey.bytes[31] &= 127, checkkey.bytes[31] |= 64; + G.LP_mypub25519 = *pubkeyp = curve25519(checkkey,curve25519_basepoint9()); + G.LP_mypriv25519 = checkkey; return(privkey); } -void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase,int32_t initonly) +void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase) { - struct iguana_info *coin,*tmp; bits256 pubkey,privkey; uint8_t pubkey33[33]; + struct iguana_info *coin,*tmp; bits256 pubkey,privkey; uint8_t pubkey33[33]; int32_t initonly; + initonly = (passphrase != 0); memset(privkey.bytes,0,sizeof(privkey)); - pubkey = privkey; + memset(pubkey.bytes,0,sizeof(pubkey)); HASH_ITER(hh,LP_coins,coin,tmp) { + if ( initonly != 0 ) + { + coin->counter = 0; + memset(coin->smartaddr,0,sizeof(coin->smartaddr)); + if ( bits256_nonz(privkey) == 0 || coin->smartaddr[0] == 0 ) + privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,coin,passphrase,""); + } //printf("i.%d of %d\n",i,LP_numcoins); - if ( bits256_nonz(privkey) == 0 || coin->smartaddr[0] == 0 ) - privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,coin,passphrase,""); - if ( coin->inactive == 0 && initonly == 0 ) - LP_privkey_init(pubsock,coin,privkey,pubkey); + else if ( coin->inactive == 0 ) + { + if ( LP_privkey_init(pubsock,coin,G.LP_mypriv25519,G.LP_mypub25519) == 0 && (rand() % 10) == 0 ) + LP_postutxos(coin->symbol,coin->smartaddr); + } + } +} + +int32_t LP_passphrase_init(char *passphrase,char *gui) +{ + static void *ctx; int32_t iambob; struct LP_utxoinfo *utxo,*tmp; + if ( ctx == 0 ) + ctx = bitcoin_ctx(); + if ( G.LP_pendingswaps != 0 ) + return(-1); + G.initializing = 1; + if ( gui == 0 ) + gui = "cli"; + while ( G.waiting == 0 ) + { + printf("waiting for G.waiting\n"); + sleep(5); + } + for (iambob=0; iambob<2; iambob++) + { + if ( G.LP_utxoinfos[iambob] != 0 ) + { + HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,tmp) + { + HASH_DELETE(hh,G.LP_utxoinfos[iambob],utxo); + free(utxo); + } + } + if ( G.LP_utxoinfos2[iambob] != 0 ) + { + HASH_ITER(hh,G.LP_utxoinfos2[iambob],utxo,tmp) + { + HASH_DELETE(hh,G.LP_utxoinfos2[iambob],utxo); + free(utxo); + } + } } + memset(&G,0,sizeof(G)); + LP_privkey_updates(ctx,LP_mypubsock,passphrase); + init_hexbytes_noT(G.LP_myrmd160str,G.LP_myrmd160,20); + G.LP_sessionid = (uint32_t)time(NULL); + safecopy(G.gui,gui,sizeof(G.gui)); + return(0); } diff --git a/iguana/exchanges/autofill b/iguana/exchanges/autofill index f05962ea7..b0724a9db 100755 --- a/iguana/exchanges/autofill +++ b/iguana/exchanges/autofill @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autofill\",\"base\":\"KMD\",\"rel\":\"BTC\",\"price\":0.0005,\"relvolume\":0.1}" diff --git a/iguana/exchanges/autoprice b/iguana/exchanges/autoprice index b709aa0e4..a95a3f5e3 100755 --- a/iguana/exchanges/autoprice +++ b/iguana/exchanges/autoprice @@ -1,3 +1,4 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"BTC\",\"margin\":0.0001}" curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"BTC\",\"rel\":\"KMD\",\"margin\":0.0001}" diff --git a/iguana/exchanges/autotrade b/iguana/exchanges/autotrade index 0ea5e5f11..72e14f84a 100755 --- a/iguana/exchanges/autotrade +++ b/iguana/exchanges/autotrade @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autotrade\",\"base\":\"REVS\",\"rel\":\"KMD\",\"relvolume\":1.01,\"price\":1.234}" diff --git a/iguana/exchanges/balance b/iguana/exchanges/balance new file mode 100755 index 000000000..22f84cdee --- /dev/null +++ b/iguana/exchanges/balance @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"balance\",\"coin\":\"KMD\",\"address\":\"RHV2As4rox97BuE3LK96vMeNY8VsGRTmBj\"}" diff --git a/iguana/exchanges/balance_loop b/iguana/exchanges/balance_loop index 8a75e0e22..ad28ac741 100755 --- a/iguana/exchanges/balance_loop +++ b/iguana/exchanges/balance_loop @@ -1,3 +1,4 @@ +#!/bin/bash source userpass ht=$1 while true diff --git a/iguana/exchanges/bestfit b/iguana/exchanges/bestfit index c926713ff..bae6a79ac 100755 --- a/iguana/exchanges/bestfit +++ b/iguana/exchanges/bestfit @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"bestfit\",\"rel\":\"KMD\",\"relvolume\":1.01}" diff --git a/iguana/exchanges/buy b/iguana/exchanges/buy new file mode 100755 index 000000000..cf83a91df --- /dev/null +++ b/iguana/exchanges/buy @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"buy\",\"base\":\"KMD\",\"rel\":\"BTC\",\"relvolume\":0.005,\"price\":0.0005}" diff --git a/iguana/exchanges/cancelorder b/iguana/exchanges/cancelorder index 78394c4c7..31fe7ea8c 100755 --- a/iguana/exchanges/cancelorder +++ b/iguana/exchanges/cancelorder @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"setprice\",\"base\":\"REVS\",\"rel\":\"KMD\",\"price\":9999999.99}" diff --git a/iguana/exchanges/client b/iguana/exchanges/client index 8b3f8a7ba..a36758376 100755 --- a/iguana/exchanges/client +++ b/iguana/exchanges/client @@ -1,3 +1,4 @@ +#!/bin/bash source passphrase source coins pkill -15 marketmaker; diff --git a/iguana/exchanges/client_osx b/iguana/exchanges/client_osx index 9e1cada67..463a08eb4 100755 --- a/iguana/exchanges/client_osx +++ b/iguana/exchanges/client_osx @@ -1,3 +1,4 @@ +#!/bin/bash source passphrase source coins pkill -15 marketmaker; diff --git a/iguana/exchanges/coins b/iguana/exchanges/coins index 0a7680a30..25af22269 100644 --- a/iguana/exchanges/coins +++ b/iguana/exchanges/coins @@ -1,2 +1,2 @@ -export coins="[{\"coin\":\"BSD\",\"name\":\"bitsend\",\"rpcport\":8800,\"pubtype\":102,\"p2shtype\":5,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"IOP\",\"name\":\"IoP\",\"rpcport\":8337,\"pubtype\":117,\"p2shtype\":174,\"wiftype\":49,\"txfee\":10000}, {\"coin\":\"BLOCK\",\"name\":\"blocknetdx\",\"rpcport\":41414,\"pubtype\":26,\"p2shtype\":28,\"wiftype\":154,\"txfee\":10000}, {\"coin\":\"CHIPS\", \"name\": \"chips\", \"rpcport\":57776,\"pubtype\":60, \"p2shtype\":85, \"wiftype\":188, \"txfee\":10000}, {\"coin\":\"888\",\"name\":\"octocoin\",\"rpcport\":22888,\"pubtype\":18,\"p2shtype\":5,\"wiftype\":176,\"txfee\":2000000}, {\"coin\":\"ARG\",\"name\":\"argentum\",\"rpcport\":13581,\"pubtype\":23,\"p2shtype\":5,\"wiftype\":151,\"txfee\":50000}, {\"coin\":\"GLT\",\"name\":\"globaltoken\",\"rpcport\":9320,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":166,\"txfee\":10000}, {\"coin\":\"ZER\",\"name\":\"zero\",\"rpcport\":23801,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"HODLC\",\"name\":\"hodlcoin\",\"rpcport\":11989,\"pubtype\":40,\"p2shtype\":5,\"wiftype\":168,\"txfee\":5000}, {\"coin\":\"UIS\",\"name\":\"unitus\",\"rpcport\":50604,\"pubtype\":68,\"p2shtype\":10,\"wiftype\":132,\"txfee\":1000000}, {\"coin\":\"CRW\",\"name\":\"crown\",\"rpcport\":9341,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"HUC\",\"name\":\"huntercoin\",\"rpcport\":8399,\"pubtype\":40,\"p2shtype\":13,\"wiftype\":168,\"txfee\":100000}, {\"coin\":\"PIVX\",\"name\":\"pivx\",\"rpcport\":51473,\"pubtype\":30,\"p2shtype\":13,\"wiftype\":212,\"txfee\":10000}, {\"coin\":\"BDL\",\"name\":\"bitdeal\",\"rpcport\":9332,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"ARC\",\"name\":\"arcticcoin\",\"confpath\":\"${HOME#}/.arcticcore/arcticcoin.conf\",\"rpcport\":7208,\"pubtype\":23,\"p2shtype\":8,\"wiftype\":176,\"txfee\":10000}, {\"coin\":\"ZCL\",\"name\":\"zclassic\",\"rpcport\":8023,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"VIA\",\"name\":\"viacoin\",\"rpcport\":5222,\"pubtype\":71,\"p2shtype\":33,\"wiftype\":199,\"txfee\":100000}, {\"coin\":\"ERC\",\"name\":\"europecoin\",\"rpcport\":11989,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":168,\"txfee\":10000},{\"coin\":\"FAIR\",\"name\":\"faircoin\",\"confpath\":\"${HOME#}/.faircoin2/faircoin.conf\",\"rpcport\":40405,\"pubtype\":95,\"p2shtype\":36,\"wiftype\":223,\"txfee\":1000000}, {\"coin\":\"FLO\",\"name\":\"florincoin\",\"rpcport\":7313,\"pubtype\":35,\"p2shtype\":8,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"SXC\",\"name\":\"sexcoin\",\"rpcport\":9561,\"pubtype\":62,\"p2shtype\":5,\"wiftype\":190,\"txfee\":100000}, {\"coin\":\"CREA\",\"name\":\"creativecoin\",\"rpcport\":17711,\"pubtype\":28,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"TRC\",\"name\":\"terracoin\",\"rpcport\":13332,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"BTA\",\"name\":\"bata\",\"rpcport\":5493,\"pubtype\":25,\"p2shtype\":5,\"wiftype\":188,\"txfee\":100000}, {\"coin\":\"SMC\",\"name\":\"smartcoin\",\"rpcport\":58583,\"pubtype\":63,\"p2shtype\":5,\"wiftype\":191,\"txfee\":1000000}, {\"coin\":\"NMC\",\"name\":\"namecoin\",\"rpcport\":8336,\"pubtype\":52,\"p2shtype\":13,\"wiftype\":180,\"txfee\":100000}, {\"coin\":\"NAV\",\"name\":\"navcoin\",\"isPoS\":1,\"confpath\":\"${HOME#}/.navcoin4/navcoin.conf\",\"rpcport\":44444,\"pubtype\":53,\"p2shtype\":85,\"wiftype\":150,\"txfee\":10000}, {\"coin\":\"MOON\",\"name\":\"Mooncoin\",\"rpcport\":44663,\"pubtype\":3,\"p2shtype\":22,\"wiftype\":131,\"txfee\":100000}, {\"coin\":\"EMC2\",\"name\":\"einsteinium\",\"rpcport\":41879,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"SYS\",\"name\":\"syscoin\",\"rpcport\":8370,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"I0C\",\"name\":\"i0coin\",\"rpcport\":7332,\"pubtype\":105,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"DASH\",\"confpath\":\"${HOME#}/.dashcore/dash.conf\",\"name\":\"dashcore\",\"rpcport\":9998,\"pubtype\":76,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"STRAT\", \"name\": \"stratis\", \"active\":0, \"rpcport\":16174,\"pubtype\":63, \"p2shtype\":125, \"wiftype\":191, \"txfee\":10000}, {\"confpath\":\"${HOME#}/.muecore/mue.conf\",\"coin\":\"MUE\",\"name\":\"muecore\",\"rpcport\":29683,\"pubtype\":16,\"p2shtype\":76,\"wiftype\":126,\"txfee\":10000}, {\"coin\":\"MONA\",\"name\":\"monacoin\",\"rpcport\":9402,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"XMY\",\"name\":\"myriadcoin\",\"rpcport\":10889,\"pubtype\":50,\"p2shtype\":9,\"wiftype\":178,\"txfee\":5000}, {\"coin\":\"MAC\",\"name\":\"machinecoin\",\"rpcport\":40332,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":178,\"txfee\":50000}, {\"coin\":\"BTX\",\"name\":\"bitcore\",\"rpcport\":8556,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":50000}, {\"coin\":\"XRE\",\"name\":\"revolvercoin\",\"rpcport\":8775,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"LBC\",\"name\":\"lbrycrd\",\"rpcport\":9245,\"pubtype\":85,\"p2shtype\":122,\"wiftype\":28,\"txfee\":1000}, {\"coin\":\"SIB\",\"name\":\"sibcoin\",\"rpcport\":1944,\"pubtype\":63,\"p2shtype\":40,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"VTC\", \"name\":\"vertcoin\", \"rpcport\":5888, \"pubtype\":71, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000 }, {\"coin\":\"REVS\",\"active\":0, \"asset\":\"REVS\",\"rpcport\":10196}, {\"coin\":\"JUMBLR\",\"active\":0, \"asset\":\"JUMBLR\",\"rpcport\":15106}, {\"coin\":\"DOGE\",\"name\":\"dogecoin\",\"rpcport\":22555,\"pubtype\":30,\"p2shtype\":22,\"wiftype\":158,\"txfee\":100000000}, {\"coin\":\"HUSH\",\"name\":\"hush\",\"rpcport\":8822,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000 }, {\"active\":0,\"coin\":\"ZEC\",\"name\":\"zcash\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000 }, {\"coin\":\"DGB\",\"name\":\"digibyte\",\"rpcport\":14022,\"pubtype\":30,\"p2shtype\":5,\"wiftype\":128,\"txfee\":100000}, {\"coin\":\"ZET\", \"name\":\"zetacoin\", \"pubtype\":80, \"p2shtype\":9,\"rpcport\":8332, \"wiftype\":224, \"txfee\":10000}, {\"coin\":\"GAME\", \"rpcport\":40001, \"name\":\"gamecredits\", \"pubtype\":38, \"p2shtype\":5, \"wiftype\":166, \"txfee\":100000}, {\"coin\":\"LTC\", \"name\":\"litecoin\", \"rpcport\":9332, \"pubtype\":48, \"p2shtype\":5, \"wiftype\":176, \"txfee\":100000 }, {\"coin\":\"SUPERNET\",\"asset\":\"SUPERNET\",\"rpcport\":11341}, {\"coin\":\"WLC\",\"asset\":\"WLC\",\"rpcport\":12167}, {\"coin\":\"PANGEA\",\"asset\":\"PANGEA\",\"rpcport\":14068}, {\"coin\":\"DEX\",\"asset\":\"DEX\",\"rpcport\":11890}, {\"coin\":\"BET\",\"asset\":\"BET\",\"rpcport\":14250}, {\"coin\":\"CRYPTO\",\"asset\":\"CRYPTO\",\"rpcport\":8516}, {\"coin\":\"HODL\",\"asset\":\"HODL\",\"rpcport\":14431}, {\"coin\":\"SHARK\",\"asset\":\"SHARK\",\"rpcport\":10114}, {\"coin\":\"BOTS\",\"asset\":\"BOTS\",\"rpcport\":11964}, {\"coin\":\"MGW\",\"asset\":\"MGW\",\"rpcport\":12386}, {\"coin\":\"COQUI\",\"asset\":\"COQUI\",\"rpcport\":14276}, {\"coin\":\"KV\",\"asset\":\"KV\",\"rpcport\":8299}, {\"coin\":\"CEAL\",\"asset\":\"CEAL\",\"rpcport\":11116}, {\"coin\":\"MESH\",\"asset\":\"MESH\",\"rpcport\":9455}, {\"coin\":\"AUD\",\"asset\":\"AUD\",\"rpcport\":8045}, {\"coin\":\"BGN\",\"asset\":\"BGN\",\"rpcport\":9110}, {\"coin\":\"CAD\",\"asset\":\"CAD\",\"rpcport\":8720}, {\"coin\":\"CHF\",\"asset\":\"CHF\",\"rpcport\":15312}, {\"coin\":\"CNY\",\"asset\":\"CNY\",\"rpcport\":10384}, {\"coin\":\"CZK\",\"asset\":\"CZK\",\"rpcport\":9482}, {\"coin\":\"DKK\",\"asset\":\"DKK\",\"rpcport\":13830}, {\"coin\":\"EUR\",\"asset\":\"EUR\",\"rpcport\":8065}, {\"coin\":\"GBP\",\"asset\":\"GBP\",\"rpcport\":11505}, {\"coin\":\"HKD\",\"asset\":\"HKD\",\"rpcport\":15409}, {\"coin\":\"HRK\",\"asset\":\"HRK\",\"rpcport\":12617}, {\"coin\":\"HUF\",\"asset\":\"HUF\",\"rpcport\":13699}, {\"coin\":\"IDR\",\"asset\":\"IDR\",\"rpcport\":14459}, {\"coin\":\"ILS\",\"asset\":\"ILS\",\"rpcport\":14638}, {\"coin\":\"INR\",\"asset\":\"INR\",\"rpcport\":10536}, {\"coin\":\"JPY\",\"asset\":\"JPY\",\"rpcport\":13145}, {\"coin\":\"KRW\",\"asset\":\"KRW\",\"rpcport\":14020}, {\"coin\":\"MXN\",\"asset\":\"MXN\",\"rpcport\":13970}, {\"coin\":\"MYR\",\"asset\":\"MYR\",\"rpcport\":10688}, {\"coin\":\"NOK\",\"asset\":\"NOK\",\"rpcport\":11588}, {\"coin\":\"NZD\",\"asset\":\"NZD\",\"rpcport\":10915}, {\"coin\":\"PHP\",\"asset\":\"PHP\",\"rpcport\":11181}, {\"coin\":\"PLN\",\"asset\":\"PLN\",\"rpcport\":13493}, {\"coin\":\"BRL\",\"asset\":\"BRL\",\"rpcport\":9914}, {\"coin\":\"RON\",\"asset\":\"RON\",\"rpcport\":8675}, {\"coin\":\"RUB\",\"asset\":\"RUB\",\"rpcport\":8199}, {\"coin\":\"SEK\",\"asset\":\"SEK\",\"rpcport\":11447}, {\"coin\":\"SGD\",\"asset\":\"SGD\",\"rpcport\":14475}, {\"coin\":\"THB\",\"asset\":\"THB\",\"rpcport\":11847}, {\"coin\":\"TRY\",\"asset\":\"TRY\",\"rpcport\":13924}, {\"coin\":\"USD\",\"asset\":\"USD\",\"rpcport\":13967}, {\"coin\":\"ZAR\",\"asset\":\"ZAR\",\"rpcport\":15160}]" +export coins="[{\"coin\":\"BTCZ\",\"name\":\"bitcoinz\",\"rpcport\":1979,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"MAGA\",\"name\":\"magacoin\",\"rpcport\":5332,\"pubtype\":23,\"p2shtype\":50,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"BLK\",\"name\":\"blackcoin\",\"rpcport\":15715,\"pubtype\":25,\"p2shtype\":85,\"wiftype\":153,\"txfee\":10000}, {\"coin\":\"ZEN\",\"name\":\"zen\",\"rpcport\":8231,\"pubtype\":137,\"taddr\":32,\"p2shtype\":150,\"wiftype\":128,\"txfee\":10000},{\"coin\":\"BSD\",\"name\":\"bitsend\",\"rpcport\":8800,\"pubtype\":102,\"p2shtype\":5,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"IOP\",\"name\":\"IoP\",\"rpcport\":8337,\"pubtype\":117,\"p2shtype\":174,\"wiftype\":49,\"txfee\":10000}, {\"coin\":\"BLOCK\",\"name\":\"blocknetdx\",\"rpcport\":41414,\"pubtype\":26,\"p2shtype\":28,\"wiftype\":154,\"txfee\":10000}, {\"coin\":\"CHIPS\", \"name\": \"chips\", \"rpcport\":57776,\"pubtype\":60, \"p2shtype\":85, \"wiftype\":188, \"txfee\":10000}, {\"coin\":\"888\",\"name\":\"octocoin\",\"rpcport\":22888,\"pubtype\":18,\"p2shtype\":5,\"wiftype\":176,\"txfee\":2000000}, {\"coin\":\"ARG\",\"name\":\"argentum\",\"rpcport\":13581,\"pubtype\":23,\"p2shtype\":5,\"wiftype\":151,\"txfee\":50000}, {\"coin\":\"GLT\",\"name\":\"globaltoken\",\"rpcport\":9320,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":166,\"txfee\":10000}, {\"coin\":\"ZER\",\"name\":\"zero\",\"rpcport\":23801,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"HODLC\",\"name\":\"hodlcoin\",\"rpcport\":11989,\"pubtype\":40,\"p2shtype\":5,\"wiftype\":168,\"txfee\":5000}, {\"coin\":\"UIS\",\"name\":\"unitus\",\"rpcport\":50604,\"pubtype\":68,\"p2shtype\":10,\"wiftype\":132,\"txfee\":2000000}, {\"coin\":\"CRW\",\"name\":\"crown\",\"rpcport\":9341,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"HUC\",\"name\":\"huntercoin\",\"rpcport\":8399,\"pubtype\":40,\"p2shtype\":13,\"wiftype\":168,\"txfee\":100000}, {\"coin\":\"PIVX\",\"name\":\"pivx\",\"rpcport\":51473,\"pubtype\":30,\"p2shtype\":13,\"wiftype\":212,\"txfee\":10000}, {\"coin\":\"BDL\",\"name\":\"bitdeal\",\"rpcport\":9332,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"ARC\",\"name\":\"arcticcoin\",\"confpath\":\"${HOME#}/.arcticcore/arcticcoin.conf\",\"rpcport\":7208,\"pubtype\":23,\"p2shtype\":8,\"wiftype\":176,\"txfee\":10000}, {\"coin\":\"ZCL\",\"name\":\"zclassic\",\"rpcport\":8023,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"VIA\",\"name\":\"viacoin\",\"rpcport\":5222,\"pubtype\":71,\"p2shtype\":33,\"wiftype\":199,\"txfee\":100000}, {\"coin\":\"ERC\",\"name\":\"europecoin\",\"rpcport\":11989,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":168,\"txfee\":10000},{\"coin\":\"FAIR\",\"name\":\"faircoin\",\"confpath\":\"${HOME#}/.faircoin2/faircoin.conf\",\"rpcport\":40405,\"pubtype\":95,\"p2shtype\":36,\"wiftype\":223,\"txfee\":1000000}, {\"coin\":\"FLO\",\"name\":\"florincoin\",\"rpcport\":7313,\"pubtype\":35,\"p2shtype\":8,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"SXC\",\"name\":\"sexcoin\",\"rpcport\":9561,\"pubtype\":62,\"p2shtype\":5,\"wiftype\":190,\"txfee\":100000}, {\"coin\":\"CREA\",\"name\":\"creativecoin\",\"rpcport\":17711,\"pubtype\":28,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"TRC\",\"name\":\"terracoin\",\"confpath\":\"${HOME#}/.terracoincore/terracoin.conf\",\"rpcport\":13332,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"BTA\",\"name\":\"bata\",\"rpcport\":5493,\"pubtype\":25,\"p2shtype\":5,\"wiftype\":188,\"txfee\":100000}, {\"coin\":\"SMC\",\"name\":\"smartcoin\",\"rpcport\":58583,\"pubtype\":63,\"p2shtype\":5,\"wiftype\":191,\"txfee\":1000000}, {\"coin\":\"NMC\",\"name\":\"namecoin\",\"rpcport\":8336,\"pubtype\":52,\"p2shtype\":13,\"wiftype\":180,\"txfee\":100000}, {\"coin\":\"NAV\",\"name\":\"navcoin\",\"isPoS\":1,\"confpath\":\"${HOME#}/.navcoin4/navcoin.conf\",\"rpcport\":44444,\"pubtype\":53,\"p2shtype\":85,\"wiftype\":150,\"txfee\":10000}, {\"coin\":\"MOON\",\"name\":\"Mooncoin\",\"rpcport\":44663,\"pubtype\":3,\"p2shtype\":22,\"wiftype\":131,\"txfee\":100000}, {\"coin\":\"EMC2\",\"name\":\"einsteinium\",\"rpcport\":41879,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"SYS\",\"name\":\"syscoin\",\"rpcport\":8370,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"I0C\",\"name\":\"i0coin\",\"rpcport\":7332,\"pubtype\":105,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"DASH\",\"confpath\":\"${HOME#}/.dashcore/dash.conf\",\"name\":\"dashcore\",\"rpcport\":9998,\"pubtype\":76,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"STRAT\", \"name\": \"stratis\", \"active\":0, \"rpcport\":16174,\"pubtype\":63, \"p2shtype\":125, \"wiftype\":191, \"txfee\":10000}, {\"confpath\":\"${HOME#}/.muecore/mue.conf\",\"coin\":\"MUE\",\"name\":\"muecore\",\"rpcport\":29683,\"pubtype\":16,\"p2shtype\":76,\"wiftype\":126,\"txfee\":10000}, {\"coin\":\"MONA\",\"name\":\"monacoin\",\"rpcport\":9402,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"XMY\",\"name\":\"myriadcoin\",\"rpcport\":10889,\"pubtype\":50,\"p2shtype\":9,\"wiftype\":178,\"txfee\":5000}, {\"coin\":\"MAC\",\"name\":\"machinecoin\",\"rpcport\":40332,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":178,\"txfee\":50000}, {\"coin\":\"BTX\",\"name\":\"bitcore\",\"rpcport\":8556,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":50000}, {\"coin\":\"XRE\",\"name\":\"revolvercoin\",\"rpcport\":8775,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"LBC\",\"name\":\"lbrycrd\",\"rpcport\":9245,\"pubtype\":85,\"p2shtype\":122,\"wiftype\":28,\"txfee\":1000}, {\"coin\":\"SIB\",\"name\":\"sibcoin\",\"rpcport\":1944,\"pubtype\":63,\"p2shtype\":40,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"VTC\", \"name\":\"vertcoin\", \"rpcport\":5888, \"pubtype\":71, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000 }, {\"coin\":\"REVS\",\"active\":0, \"asset\":\"REVS\",\"rpcport\":10196}, {\"coin\":\"JUMBLR\",\"active\":0, \"asset\":\"JUMBLR\",\"rpcport\":15106}, {\"coin\":\"DOGE\",\"name\":\"dogecoin\",\"rpcport\":22555,\"pubtype\":30,\"p2shtype\":22,\"wiftype\":158,\"txfee\":100000000}, {\"coin\":\"HUSH\",\"name\":\"hush\",\"rpcport\":8822,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000 }, {\"active\":0,\"coin\":\"ZEC\",\"name\":\"zcash\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000 }, {\"coin\":\"DGB\",\"name\":\"digibyte\",\"rpcport\":14022,\"pubtype\":30,\"p2shtype\":5,\"wiftype\":128,\"txfee\":100000}, {\"coin\":\"ZET\", \"name\":\"zetacoin\", \"pubtype\":80, \"p2shtype\":9,\"rpcport\":8332, \"wiftype\":224, \"txfee\":10000}, {\"coin\":\"GAME\", \"rpcport\":40001, \"name\":\"gamecredits\", \"pubtype\":38, \"p2shtype\":5, \"wiftype\":166, \"txfee\":100000}, {\"coin\":\"LTC\", \"name\":\"litecoin\", \"rpcport\":9332, \"pubtype\":48, \"p2shtype\":5, \"wiftype\":176, \"txfee\":100000 }, {\"coin\":\"SUPERNET\",\"asset\":\"SUPERNET\",\"rpcport\":11341}, {\"coin\":\"WLC\",\"asset\":\"WLC\",\"rpcport\":12167}, {\"coin\":\"PANGEA\",\"asset\":\"PANGEA\",\"rpcport\":14068}, {\"coin\":\"DEX\",\"asset\":\"DEX\",\"rpcport\":11890}, {\"coin\":\"BET\",\"asset\":\"BET\",\"rpcport\":14250}, {\"coin\":\"CRYPTO\",\"asset\":\"CRYPTO\",\"rpcport\":8516}, {\"coin\":\"HODL\",\"asset\":\"HODL\",\"rpcport\":14431}, {\"coin\":\"SHARK\",\"asset\":\"SHARK\",\"rpcport\":10114}, {\"coin\":\"BOTS\",\"asset\":\"BOTS\",\"rpcport\":11964}, {\"coin\":\"MGW\",\"asset\":\"MGW\",\"rpcport\":12386}, {\"coin\":\"COQUI\",\"asset\":\"COQUI\",\"rpcport\":14276}, {\"coin\":\"KV\",\"asset\":\"KV\",\"rpcport\":8299}, {\"coin\":\"CEAL\",\"asset\":\"CEAL\",\"rpcport\":11116}, {\"coin\":\"MESH\",\"asset\":\"MESH\",\"rpcport\":9455}, {\"coin\":\"AUD\",\"asset\":\"AUD\",\"rpcport\":8045}, {\"coin\":\"BGN\",\"asset\":\"BGN\",\"rpcport\":9110}, {\"coin\":\"CAD\",\"asset\":\"CAD\",\"rpcport\":8720}, {\"coin\":\"CHF\",\"asset\":\"CHF\",\"rpcport\":15312}, {\"coin\":\"CNY\",\"asset\":\"CNY\",\"rpcport\":10384}, {\"coin\":\"CZK\",\"asset\":\"CZK\",\"rpcport\":9482}, {\"coin\":\"DKK\",\"asset\":\"DKK\",\"rpcport\":13830}, {\"coin\":\"EUR\",\"asset\":\"EUR\",\"rpcport\":8065}, {\"coin\":\"GBP\",\"asset\":\"GBP\",\"rpcport\":11505}, {\"coin\":\"HKD\",\"asset\":\"HKD\",\"rpcport\":15409}, {\"coin\":\"HRK\",\"asset\":\"HRK\",\"rpcport\":12617}, {\"coin\":\"HUF\",\"asset\":\"HUF\",\"rpcport\":13699}, {\"coin\":\"IDR\",\"asset\":\"IDR\",\"rpcport\":14459}, {\"coin\":\"ILS\",\"asset\":\"ILS\",\"rpcport\":14638}, {\"coin\":\"INR\",\"asset\":\"INR\",\"rpcport\":10536}, {\"coin\":\"JPY\",\"asset\":\"JPY\",\"rpcport\":13145}, {\"coin\":\"KRW\",\"asset\":\"KRW\",\"rpcport\":14020}, {\"coin\":\"MXN\",\"asset\":\"MXN\",\"rpcport\":13970}, {\"coin\":\"MYR\",\"asset\":\"MYR\",\"rpcport\":10688}, {\"coin\":\"NOK\",\"asset\":\"NOK\",\"rpcport\":11588}, {\"coin\":\"NZD\",\"asset\":\"NZD\",\"rpcport\":10915}, {\"coin\":\"PHP\",\"asset\":\"PHP\",\"rpcport\":11181}, {\"coin\":\"PLN\",\"asset\":\"PLN\",\"rpcport\":13493}, {\"coin\":\"BRL\",\"asset\":\"BRL\",\"rpcport\":9914}, {\"coin\":\"RON\",\"asset\":\"RON\",\"rpcport\":8675}, {\"coin\":\"RUB\",\"asset\":\"RUB\",\"rpcport\":8199}, {\"coin\":\"SEK\",\"asset\":\"SEK\",\"rpcport\":11447}, {\"coin\":\"SGD\",\"asset\":\"SGD\",\"rpcport\":14475}, {\"coin\":\"THB\",\"asset\":\"THB\",\"rpcport\":11847}, {\"coin\":\"TRY\",\"asset\":\"TRY\",\"rpcport\":13924}, {\"coin\":\"USD\",\"asset\":\"USD\",\"rpcport\":13967}, {\"coin\":\"ZAR\",\"asset\":\"ZAR\",\"rpcport\":15160}]" diff --git a/iguana/exchanges/debug b/iguana/exchanges/debug index 02017001a..a4f2297a3 100755 --- a/iguana/exchanges/debug +++ b/iguana/exchanges/debug @@ -1,3 +1,4 @@ +#!/bin/bash source passphrase source coins pkill -15 marketmaker; diff --git a/iguana/exchanges/deletemessages b/iguana/exchanges/deletemessages index a65985a7e..5aba784a4 100755 --- a/iguana/exchanges/deletemessages +++ b/iguana/exchanges/deletemessages @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"deletemessages\",\"firsti\":0,\"num\":10}" diff --git a/iguana/exchanges/disable b/iguana/exchanges/disable index e32c24a6f..636fc952f 100755 --- a/iguana/exchanges/disable +++ b/iguana/exchanges/disable @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"disable\",\"coin\":\"REVS\"}" diff --git a/iguana/exchanges/dividends b/iguana/exchanges/dividends index c5b2ac714..5385b9454 100755 --- a/iguana/exchanges/dividends +++ b/iguana/exchanges/dividends @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"dividends\",\"coin\":\"KMD\",\"height\":$1,\"prefix\":\"fiat/jumblr sendtoaddress\",\"suffix\":\"\",\"dividend\":50000,\"dust\":1}" diff --git a/iguana/exchanges/electrum b/iguana/exchanges/electrum index 8bf0eb38a..375d3d8f4 100755 --- a/iguana/exchanges/electrum +++ b/iguana/exchanges/electrum @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"BTC\",\"ipaddr\":\"46.4.125.2\",\"port\":50001}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"BTC\",\"ipaddr\":\"173.212.225.176\",\"port\":50001}" diff --git a/iguana/exchanges/electrum.chips b/iguana/exchanges/electrum.chips new file mode 100755 index 000000000..f5cd61e8c --- /dev/null +++ b/iguana/exchanges/electrum.chips @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"CHIPS\",\"ipaddr\":\"173.212.225.176\",\"port\":50076}" diff --git a/iguana/exchanges/electrum.chips2 b/iguana/exchanges/electrum.chips2 new file mode 100755 index 000000000..2be709e78 --- /dev/null +++ b/iguana/exchanges/electrum.chips2 @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"CHIPS\",\"ipaddr\":\"136.243.45.140\",\"port\":50076}" diff --git a/iguana/exchanges/electrum.kmd b/iguana/exchanges/electrum.kmd new file mode 100755 index 000000000..865205062 --- /dev/null +++ b/iguana/exchanges/electrum.kmd @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"KMD\",\"ipaddr\":\"96.44.166.176\",\"port\":8777}" diff --git a/iguana/exchanges/electrum.kmd2 b/iguana/exchanges/electrum.kmd2 new file mode 100755 index 000000000..40bd30c93 --- /dev/null +++ b/iguana/exchanges/electrum.kmd2 @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"KMD\",\"ipaddr\":\"173.212.225.176\",\"port\":50011}" diff --git a/iguana/exchanges/electrum.kmd3 b/iguana/exchanges/electrum.kmd3 new file mode 100755 index 000000000..4bf1a6c10 --- /dev/null +++ b/iguana/exchanges/electrum.kmd3 @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"KMD\",\"ipaddr\":\"136.243.45.140\",\"port\":50011}" diff --git a/iguana/exchanges/electrums b/iguana/exchanges/electrums new file mode 100755 index 000000000..a4cabe5e3 --- /dev/null +++ b/iguana/exchanges/electrums @@ -0,0 +1,39 @@ +#!/bin/bash +source userpass + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"REVS\",\"ipaddr\":\"173.212.225.176\",\"port\":50050}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"CHIPS\",\"ipaddr\":\"173.212.225.176\",\"port\":50076}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"ARG\",\"ipaddr\":\"173.212.225.176\",\"port\":50081}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"BTC\",\"ipaddr\":\"136.243.45.140\",\"port\":50001}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"BTC\",\"ipaddr\":\"173.212.225.176\",\"port\":50001}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"CRW\",\"ipaddr\":\"173.212.225.176\",\"port\":50041}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"DASH\",\"ipaddr\":\"173.212.225.176\",\"port\":50098}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"DGB\",\"ipaddr\":\"136.243.45.140\",\"port\":50022}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"DGB\",\"ipaddr\":\"173.212.225.176\",\"port\":50022}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"DOGE\",\"ipaddr\":\"173.212.225.176\",\"port\":50015}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"FAIR\",\"ipaddr\":\"173.212.225.176\",\"port\":50005}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"HUSH\",\"ipaddr\":\"173.212.225.176\",\"port\":50013}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"KMD\",\"ipaddr\":\"136.243.45.140\",\"port\":50011}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"KMD\",\"ipaddr\":\"173.212.225.176\",\"port\":50011}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"LTC\",\"ipaddr\":\"173.212.225.176\",\"port\":50012}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"MONA\",\"ipaddr\":\"173.212.225.176\",\"port\":50002}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"NMC\",\"ipaddr\":\"173.212.225.176\",\"port\":50036}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"VTC\",\"ipaddr\":\"173.212.225.176\",\"port\":50088}" + +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"ZEC\",\"ipaddr\":\"173.212.225.176\",\"port\":50032}" + diff --git a/iguana/exchanges/enable b/iguana/exchanges/enable index bb2b70d30..d6a287b3a 100755 --- a/iguana/exchanges/enable +++ b/iguana/exchanges/enable @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"BTC\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"REVS\"}" diff --git a/iguana/exchanges/getcoin b/iguana/exchanges/getcoin index 063185f57..b37ccc666 100755 --- a/iguana/exchanges/getcoin +++ b/iguana/exchanges/getcoin @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getcoin\",\"coin\":\"LTC\"}" diff --git a/iguana/exchanges/getcoins b/iguana/exchanges/getcoins index 71778acfb..64b1d7461 100755 --- a/iguana/exchanges/getcoins +++ b/iguana/exchanges/getcoins @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getcoins\"}" diff --git a/iguana/exchanges/getmessages b/iguana/exchanges/getmessages index 0bfadf518..121e8ec0b 100755 --- a/iguana/exchanges/getmessages +++ b/iguana/exchanges/getmessages @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getmessages\",\"firsti\":0,\"num\":10}" diff --git a/iguana/exchanges/getpeers b/iguana/exchanges/getpeers index ea91cb791..9ed1daf77 100755 --- a/iguana/exchanges/getpeers +++ b/iguana/exchanges/getpeers @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getpeers\"}" diff --git a/iguana/exchanges/getpeersIP b/iguana/exchanges/getpeersIP index c5a7fdd74..7c532e609 100755 --- a/iguana/exchanges/getpeersIP +++ b/iguana/exchanges/getpeersIP @@ -1,3 +1,4 @@ +#!/bin/bash curl --url "http://5.9.253.195:7783" --data "{\"method\":\"getpeers\"}" curl --url "http://5.9.253.196:7783" --data "{\"method\":\"getpeers\"}" curl --url "http://5.9.253.197:7783" --data "{\"method\":\"getpeers\"}" diff --git a/iguana/exchanges/getprices b/iguana/exchanges/getprices index 2a0428d1c..57031035c 100755 --- a/iguana/exchanges/getprices +++ b/iguana/exchanges/getprices @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprices\",\"coin\":\"REVS\"}" diff --git a/iguana/exchanges/getutxos b/iguana/exchanges/getutxos index 38f26f654..4782c9a0a 100755 --- a/iguana/exchanges/getutxos +++ b/iguana/exchanges/getutxos @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getutxos\",\"coin\":\"REVS\"}" diff --git a/iguana/exchanges/goal b/iguana/exchanges/goal index ecfd491e6..74fd1fcda 100755 --- a/iguana/exchanges/goal +++ b/iguana/exchanges/goal @@ -1,3 +1,4 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"goal\",\"coin\":\"KMD\",\"val\":99}" curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"goal\",\"coin\":\"BTC\",\"val\":10}" diff --git a/iguana/exchanges/goals b/iguana/exchanges/goals index b29e0f49f..22f31bab8 100755 --- a/iguana/exchanges/goals +++ b/iguana/exchanges/goals @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"goal\"}" diff --git a/iguana/exchanges/help b/iguana/exchanges/help index f51f15b8d..a16fa1181 100755 --- a/iguana/exchanges/help +++ b/iguana/exchanges/help @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"help\"}" diff --git a/iguana/exchanges/install b/iguana/exchanges/install index 1b7a629d9..3f64033f1 100755 --- a/iguana/exchanges/install +++ b/iguana/exchanges/install @@ -1,4 +1,5 @@ -cp electrum snapshot_balance snapshot_loop secretaddresses dividends snapshot goals goal portfolio autoprice deletemessages getmessages debug register registerall trade ordermatch bestfit orderbook autotrade client run_osx client_osx run coins disable enable myprice myprices getcoins getpeers getpeersIP getprices getutxos help inv setprice status utxos ../dexscripts +#!/bin/bash +cp balance listunspent electrum snapshot_balance snapshot_loop secretaddresses dividends snapshot goals goal portfolio autoprice deletemessages getmessages debug register registerall buy sell bestfit orderbook client run_osx client_osx run coins disable enable myprice myprices getcoins getpeers getpeersIP getprices getutxos help inv setprice status utxos ../dexscripts cd ../dexscripts #cp ../exchanges/passphrase ../exchanges/userpass . -echo you will need to have a passphrase file with your passphrase and userpass file with userpass value in dexscripts dir +#echo you will need to have a passphrase file with your passphrase and userpass file with userpass value in dexscripts dir diff --git a/iguana/exchanges/inv b/iguana/exchanges/inv index 1a86e88f4..a42ac5d51 100755 --- a/iguana/exchanges/inv +++ b/iguana/exchanges/inv @@ -1,2 +1,3 @@ +#!/bin/bash source userpass -curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"inventory\",\"coin\":\"KMD\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"inventory\",\"coin\":\"REVS\"}" diff --git a/iguana/exchanges/listunspent b/iguana/exchanges/listunspent new file mode 100755 index 000000000..aa7ca4963 --- /dev/null +++ b/iguana/exchanges/listunspent @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"listunspent\",\"coin\":\"BTC\",\"address\":\"1DPDsPCNNCF5SHhPPrddXcJe78rM6CBcH3\"}" diff --git a/iguana/exchanges/loop b/iguana/exchanges/loop index 43228b96e..2ad08f45b 100755 --- a/iguana/exchanges/loop +++ b/iguana/exchanges/loop @@ -1,3 +1,4 @@ +#!/bin/bash while true do source userpass diff --git a/iguana/exchanges/message b/iguana/exchanges/message index 0182aa093..f36c45c81 100755 --- a/iguana/exchanges/message +++ b/iguana/exchanges/message @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"$1\",\"method\":\"sendmessage\",\"message\":\"some sort of message\"}" diff --git a/iguana/exchanges/myprice b/iguana/exchanges/myprice index 8080023ed..6dfac2dbb 100755 --- a/iguana/exchanges/myprice +++ b/iguana/exchanges/myprice @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"myprice\",\"base\":\"REVS\",\"rel\":\"KMD\"}" diff --git a/iguana/exchanges/myprices b/iguana/exchanges/myprices index 3fef298b2..1c82512c0 100755 --- a/iguana/exchanges/myprices +++ b/iguana/exchanges/myprices @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"myprices\"}" diff --git a/iguana/exchanges/numutxos b/iguana/exchanges/numutxos index f8d921078..9455dd239 100755 --- a/iguana/exchanges/numutxos +++ b/iguana/exchanges/numutxos @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"numutxos\"}" diff --git a/iguana/exchanges/orderbook b/iguana/exchanges/orderbook index 8ca15bc87..0f6e553b4 100755 --- a/iguana/exchanges/orderbook +++ b/iguana/exchanges/orderbook @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"orderbook\",\"base\":\"JUMBLR\",\"rel\":\"KMD\"}" diff --git a/iguana/exchanges/ordermatch b/iguana/exchanges/ordermatch index 85c74cfea..f4b2ca61c 100755 --- a/iguana/exchanges/ordermatch +++ b/iguana/exchanges/ordermatch @@ -1,3 +1,4 @@ +#!/bin/bash source userpass #ordermatch(base, txfee=0, rel, desttxfee=0, price, txid, vout, feetxid, feevout, duration=3600)\n\ curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"ordermatch\",\"base\":\"REVS\",\"rel\":\"KMD\",\"price\":1.234,\"duration\":600,\"txfee\":0,\"desttxfee\":0,\"txid\":\"$1\",\"vout\":$2,\"feetxid\":\"$3\",\"feevout\":$4}" diff --git a/iguana/exchanges/portfolio b/iguana/exchanges/portfolio index 92bd9f236..b22adbc06 100755 --- a/iguana/exchanges/portfolio +++ b/iguana/exchanges/portfolio @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"portfolio\"}" diff --git a/iguana/exchanges/pricearray b/iguana/exchanges/pricearray index f39ab51ae..dc812dba6 100755 --- a/iguana/exchanges/pricearray +++ b/iguana/exchanges/pricearray @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"pricearray\",\"base\":\"KMD\",\"rel\":\"BTC\",\"timescale\":60}" diff --git a/iguana/exchanges/pub b/iguana/exchanges/pub index 8d9712607..2e3241fee 100755 --- a/iguana/exchanges/pub +++ b/iguana/exchanges/pub @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"pubkey\":\"6578099f6474d9b8bd66a7a136b922029a989818ec0309aee962dd6ac1862b74\",\"method\":\"forward\",\"method2\":\"publish\",\"data\":\"nonsense\"}" diff --git a/iguana/exchanges/register b/iguana/exchanges/register index ca64e4ace..d00160beb 100755 --- a/iguana/exchanges/register +++ b/iguana/exchanges/register @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://5.9.253.195:7783" --data "{\"userpass\":\"9bb4846d24136fc7c33515e45bccbab5c8fb7b57b411aa20057b371da9358255\",\"agent\":\"stats\",\"method\":\"register\",\"client\":\"6d3332be4904feafd326609bd76b66528dc7b2e2d75a7bd110c6bf8d19c4cf58\",\"pushaddr\":\"5.9.253.195\",\"pushport\":\"10000\"}" diff --git a/iguana/exchanges/registerall b/iguana/exchanges/registerall index b3cfe5f06..927f0b2f9 100755 --- a/iguana/exchanges/registerall +++ b/iguana/exchanges/registerall @@ -1,3 +1,4 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"registerall\",\"numnodes\":10}" diff --git a/iguana/exchanges/run b/iguana/exchanges/run index 59e4ec2e4..ec549c0c7 100755 --- a/iguana/exchanges/run +++ b/iguana/exchanges/run @@ -1,3 +1,4 @@ +#!/bin/bash source passphrase source coins pkill -15 marketmaker; diff --git a/iguana/exchanges/run_osx b/iguana/exchanges/run_osx index c8924d6f4..970217843 100755 --- a/iguana/exchanges/run_osx +++ b/iguana/exchanges/run_osx @@ -1,3 +1,4 @@ +#!/bin/bash source passphrase source coins pkill -15 marketmaker; diff --git a/iguana/exchanges/secretaddresses b/iguana/exchanges/secretaddresses index a2d6ba2d2..29ebd0041 100755 --- a/iguana/exchanges/secretaddresses +++ b/iguana/exchanges/secretaddresses @@ -1,3 +1,4 @@ +#!/bin/bash source userpass echo "usage: ./secretaddresses 'passphrase'" diff --git a/iguana/exchanges/sell b/iguana/exchanges/sell new file mode 100755 index 000000000..6410148c8 --- /dev/null +++ b/iguana/exchanges/sell @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"sell\",\"base\":\"KMD\",\"rel\":\"BTC\",\"basevolume\":10.0\"price\":0.0005}" diff --git a/iguana/exchanges/setprice b/iguana/exchanges/setprice index 0909118fb..40b88e0a5 100755 --- a/iguana/exchanges/setprice +++ b/iguana/exchanges/setprice @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"setprice\",\"base\":\"REVS\",\"rel\":\"KMD\",\"price\":1.234}" diff --git a/iguana/exchanges/snapshot b/iguana/exchanges/snapshot index e9056f1cf..75a0a60aa 100755 --- a/iguana/exchanges/snapshot +++ b/iguana/exchanges/snapshot @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"snapshot\",\"coin\":\"KMD\",\"height\":$1}" diff --git a/iguana/exchanges/snapshot_balance b/iguana/exchanges/snapshot_balance index 88b0f9823..b66f1a9e4 100644 --- a/iguana/exchanges/snapshot_balance +++ b/iguana/exchanges/snapshot_balance @@ -1,3 +1,4 @@ +#!/bin/bash source userpass ht=$1 curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"snapshot_balance\",\"coin\":\"KMD\",\"height\":$ht,\"addresses\":[\"RSAzPFzgTZHNcxLNLdGyVPbjbMA8PRY7Ss\", \"RBgD5eMGwZppid4x7PTEC2Wg1AzvxbsQqB\"]}" diff --git a/iguana/exchanges/snapshot_loop b/iguana/exchanges/snapshot_loop index 38a0c3156..05bedaa82 100755 --- a/iguana/exchanges/snapshot_loop +++ b/iguana/exchanges/snapshot_loop @@ -1,3 +1,4 @@ +#!/bin/bash source userpass ht=$1 while true diff --git a/iguana/exchanges/status b/iguana/exchanges/status index a05aa72ee..0499bba6b 100755 --- a/iguana/exchanges/status +++ b/iguana/exchanges/status @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"swapstatus\"}" diff --git a/iguana/exchanges/swapstatus b/iguana/exchanges/swapstatus index ce9dbbed0..abc6dbb64 100755 --- a/iguana/exchanges/swapstatus +++ b/iguana/exchanges/swapstatus @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"swapstatus\",\"requestid\":2291973695,\"quoteid\":3387529385}" diff --git a/iguana/exchanges/trade b/iguana/exchanges/trade index 155de037a..1bad74aa9 100755 --- a/iguana/exchanges/trade +++ b/iguana/exchanges/trade @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"trade\",\"price\":1.234,\"base\":\"REVS\",\"rel\":\"KMD\",\"quote\":{}}" diff --git a/iguana/exchanges/utxos b/iguana/exchanges/utxos index 38f26f654..4782c9a0a 100755 --- a/iguana/exchanges/utxos +++ b/iguana/exchanges/utxos @@ -1,2 +1,3 @@ +#!/bin/bash source userpass curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getutxos\",\"coin\":\"REVS\"}" diff --git a/iguana/iguana_notary.c b/iguana/iguana_notary.c index a8518be7b..b04431d4d 100755 --- a/iguana/iguana_notary.c +++ b/iguana/iguana_notary.c @@ -435,7 +435,7 @@ STRING_ARG(iguana,addnotary,ipaddr) char NOTARY_CURRENCIES[][16] = { "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", "CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", - "REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "SHARK", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "LTC" }; + "REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "SHARK", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "LTC", "MNZ" }; ZERO_ARGS(dpow,notarychains) { diff --git a/iguana/m_notary b/iguana/m_notary index d2c82c7c0..d514d2680 100755 --- a/iguana/m_notary +++ b/iguana/m_notary @@ -41,6 +41,7 @@ coins/wlc_7776 coins/kv_7776 coins/ceal_7776 coins/mesh_7776 +coins/mnz_7776 curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"passthru\",\"method\":\"paxfiats\",\"timeout\":900000}" #curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"$myip\"}"