diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index 9a095a3e6..15296bcd6 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -85,6 +85,7 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_ #include "LP_coins.c" #include "LP_rpc.c" #include "LP_prices.c" +#include "LP_utxo.c" #include "LP_scan.c" #include "LP_transaction.c" #include "LP_remember.c" diff --git a/iguana/exchanges/LP_portfolio.c b/iguana/exchanges/LP_portfolio.c index a5982444d..a3e656e70 100644 --- a/iguana/exchanges/LP_portfolio.c +++ b/iguana/exchanges/LP_portfolio.c @@ -57,9 +57,7 @@ uint64_t LP_balance(uint64_t *valuep,int32_t iambob,char *symbol,char *coinaddr) for (i=0; i>= 1; decode_hex(Dredeemscript,Dredeemlen,rstr); } - if ( (value= jdouble(txobj,"amount") * SATOSHIDEN) == 0 ) - value = jdouble(txobj,"value") * SATOSHIDEN; - values[i] = value; + values[i] = value = LP_value_extract(txobj); 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 ) diff --git a/iguana/exchanges/LP_scan.c b/iguana/exchanges/LP_scan.c index d5ae10c80..ddd95f458 100644 --- a/iguana/exchanges/LP_scan.c +++ b/iguana/exchanges/LP_scan.c @@ -19,290 +19,6 @@ // -struct LP_transaction *LP_transactionfind(struct iguana_info *coin,bits256 txid) -{ - struct LP_transaction *tx; - portable_mutex_lock(&coin->txmutex); - HASH_FIND(hh,coin->transactions,txid.bytes,sizeof(txid),tx); - portable_mutex_unlock(&coin->txmutex); - return(tx); -} - -struct LP_transaction *LP_transactionadd(struct iguana_info *coin,bits256 txid,int32_t height,int32_t numvouts,int32_t numvins) -{ - struct LP_transaction *tx; int32_t i; - if ( (tx= LP_transactionfind(coin,txid)) == 0 ) - { - //char str[65]; printf("%s ht.%d u.%u NEW TXID.(%s) vouts.[%d]\n",coin->symbol,height,timestamp,bits256_str(str,txid),numvouts); - //if ( bits256_nonz(txid) == 0 && tx->height == 0 ) - // getchar(); - tx = calloc(1,sizeof(*tx) + (sizeof(*tx->outpoints) * numvouts)); - for (i=0; ioutpoints[i].spendvini = -1; - tx->height = height; - tx->numvouts = numvouts; - tx->numvins = numvins; - //tx->timestamp = timestamp; - tx->txid = txid; - portable_mutex_lock(&coin->txmutex); - HASH_ADD_KEYPTR(hh,coin->transactions,tx->txid.bytes,sizeof(tx->txid),tx); - portable_mutex_unlock(&coin->txmutex); - } // else printf("warning adding already existing txid %s\n",bits256_str(str,tx->txid)); - return(tx); -} - -uint64_t LP_txinterestvalue(uint64_t *interestp,char *destaddr,struct iguana_info *coin,bits256 txid,int32_t vout) -{ - uint64_t interest,value = 0; double val; cJSON *txobj,*sobj,*array; int32_t n=0; - *interestp = 0; - destaddr[0] = 0; - if ( (txobj= LP_gettxout(coin->symbol,txid,vout)) != 0 ) - { - // GETTXOUT.({"value":0.01200000,"txid":"6f5adfefad102e39f62a6bacb222ebace6ce5c084116c08a62cac1182729dd46","vout":1,"scriptPubkey":{"reqSigs":1,"type":"pubkey","addresses":["19Cq6MBaD8LY7trqs99ypqKAms3GcLs6J9"]}}) - if ( (val= jdouble(txobj,"amount")) < SMALLVAL ) - val = jdouble(txobj,"value"); - if ( val > SMALLVAL ) - value = (val * SATOSHIDEN + 0.0000000049); - else value = 0; - if ( value == 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); - } - else if ( strcmp(coin->symbol,"KMD") == 0 ) - { - if ( (interest= jdouble(txobj,"interest")) != 0. ) - { - //printf("add interest of %.8f to %.8f\n",interest,dstr(value)); - *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"); - //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) -{ - 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 ) - { - //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"); - if ( iter == 0 && vouts != 0 && (tx= LP_transactionadd(coin,txid,height,numvouts,numvins)) != 0 ) - { - //printf("create txid numvouts.%d numvins.%d\n",numvouts,numvins); - for (i=0; ioutpoints[i].value= SATOSHIDEN * jdouble(vout,"value")) == 0 ) - tx->outpoints[i].value = SATOSHIDEN * jdouble(vout,"amount"); - tx->outpoints[i].interest = SATOSHIDEN * jdouble(vout,"interest"); - if ( (sobj= jobj(vout,"scriptPubKey")) != 0 ) - { - if ( (addresses= jarray(&n,sobj,"addresses")) != 0 && n > 0 ) - { - 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); - } - } - //printf("numvouts.%d\n",numvouts); - } - if ( iter == 1 && vins != 0 ) - { - for (i=0; inumvouts ) - { - 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); - } //else printf("LP_transactioninit: couldnt find (%s) ht.%d %s\n",bits256_str(str,spenttxid),height,jprint(vin,0)); - if ( bits256_cmp(spenttxid,txid) == 0 ) - printf("spending same tx's %p vout ht.%d %s.[%d] s%d\n",tx,height,bits256_str(str,txid),tx!=0?tx->numvouts:0,spentvout); - } - } - free_json(txobj); - return(0); - } //else printf("LP_transactioninit error for %s %s\n",coin->symbol,bits256_str(str,txid)); - return(-1); -} - -int32_t LP_txheight(struct iguana_info *coin,bits256 txid) -{ - bits256 blockhash; struct LP_transaction *tx; cJSON *blockobj,*txobj; int32_t height = 0; - if ( coin == 0 ) - return(-1); - if ( coin->electrum == 0 ) - { - if ( (txobj= LP_gettx(coin->symbol,txid)) != 0 ) - { - //*timestampp = juint(txobj,"locktime"); - //*blocktimep = juint(txobj,"blocktime"); - blockhash = jbits256(txobj,"blockhash"); - if ( bits256_nonz(blockhash) != 0 && (blockobj= LP_getblock(coin->symbol,blockhash)) != 0 ) - { - height = jint(blockobj,"height"); - //printf("%s LP_txheight.%d\n",coin->symbol,height); - free_json(blockobj); - } //else printf("%s LP_txheight error (%s)\n",coin->symbol,jprint(txobj,0)); - free_json(txobj); - } - } - else - { - if ( (tx= LP_transactionfind(coin,txid)) != 0 ) - height = tx->height; - } - return(height); -} - -int32_t LP_numconfirms(char *symbol,char *coinaddr,bits256 txid,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 ( coin->electrum == 0 ) - numconfirms = jint(txobj,"confirmations"); - else numconfirms = coin->height - jint(txobj,"height"); - free_json(txobj); - } - else if ( mempool != 0 && LP_mempoolscan(symbol,txid) >= 0 ) - numconfirms = 0; - } - else - { - 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; - } - //#endif - return(numconfirms); -} - -int64_t basilisk_txvalue(char *symbol,bits256 txid,int32_t vout) -{ - char destaddr[64]; uint64_t value,interest = 0; struct iguana_info *coin; - if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) - return(0); - //char str[65]; printf("%s txvalue.(%s)\n",symbol,bits256_str(str,txid)); - value = LP_txinterestvalue(&interest,destaddr,coin,txid,vout); - return(value + interest); -} - -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]; - if ( bits256_nonz(txid) == 0 ) - return(0); - if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) - return(0); - if ( coinaddr != 0 ) - coinaddr[0] = 0; - if ( (tx= LP_transactionfind(coin,txid)) == 0 ) - { - LP_transactioninit(coin,txid,0); - LP_transactioninit(coin,txid,1); - tx = LP_transactionfind(coin,txid); - } - if ( tx != 0 ) - { - if ( vout < tx->numvouts ) - { - 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)); - return(0); - } - else - { - if ( coinaddr != 0 ) - { - //if ( tx->outpoints[vout].coinaddr[0] == 0 ) - // tx->outpoints[vout].value = LP_txinterestvalue(&tx->outpoints[vout].interest,tx->outpoints[vout].coinaddr,coin,txid,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); - } - } else printf("LP_txvalue vout.%d >= tx->numvouts.%d\n",vout,tx->numvouts); - } - else - { - if ( (txobj= LP_gettxout(coin->symbol,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); - } - printf("pruned node? LP_txvalue couldnt find %s tx %s\n",coin->symbol,bits256_str(str,txid)); - } - return(0); -} - -int32_t LP_undospends(struct iguana_info *coin,int32_t lastheight) -{ - int32_t i,ht,num = 0; struct LP_transaction *tx,*tmp; - HASH_ITER(hh,coin->transactions,tx,tmp) - { - for (i=0; inumvouts; i++) - { - if ( bits256_nonz(tx->outpoints[i].spendtxid) == 0 ) - continue; - if ( (ht= tx->outpoints[i].spendheight) == 0 ) - { - tx->outpoints[i].spendheight = LP_txheight(coin,tx->outpoints[i].spendtxid); - } - if ( (ht= tx->outpoints[i].spendheight) != 0 && ht > lastheight ) - { - char str[65]; printf("clear spend %s/v%d at ht.%d > lastheight.%d\n",bits256_str(str,tx->txid),i,ht,lastheight); - tx->outpoints[i].spendheight = 0; - tx->outpoints[i].spendvini = -1; - memset(tx->outpoints[i].spendtxid.bytes,0,sizeof(bits256)); - } - } - } - return(num); -} - 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; diff --git a/iguana/exchanges/LP_socket.c b/iguana/exchanges/LP_socket.c index cbc6821d7..2866205a8 100644 --- a/iguana/exchanges/LP_socket.c +++ b/iguana/exchanges/LP_socket.c @@ -329,7 +329,7 @@ void electrum_process_array(struct iguana_info *coin,cJSON *array) if ( jobj(item,"tx_pos") != 0 && jobj(item,"value") != 0 && (v= jint(item,"tx_pos")) >= 0 && v < tx->numvouts ) { value = j64bits(item,"value"); - if ( value != tx->outpoints[v].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)); tx->outpoints[v].value = value; diff --git a/iguana/exchanges/LP_transaction.c b/iguana/exchanges/LP_transaction.c index 3cdafe59b..71bde88e4 100644 --- a/iguana/exchanges/LP_transaction.c +++ b/iguana/exchanges/LP_transaction.c @@ -1073,7 +1073,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; double val; int32_t n,m,suppress_pubkeys = 0; + 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; 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,13 +1083,7 @@ void LP_swap_coinaddr(struct iguana_info *coin,char *coinaddr,uint64_t *valuep,u { vout = jitem(vouts,v); if ( valuep != 0 ) - { - *valuep = 0; - if ( (val= jdouble(vout,"value")) < SMALLVAL ) - val = jdouble(vout,"amount"); - if ( val > SMALLVAL ) - *valuep = (val * SATOSHIDEN + 0.0000000049); - } + *valuep = LP_value_extract(vout); //printf("VOUT.(%s)\n",jprint(vout,0)); if ( (skey= jobj(vout,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 ) { diff --git a/iguana/exchanges/LP_utxo.c b/iguana/exchanges/LP_utxo.c new file mode 100644 index 000000000..5c327dc99 --- /dev/null +++ b/iguana/exchanges/LP_utxo.c @@ -0,0 +1,436 @@ + +/****************************************************************************** + * Copyright © 2014-2017 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ +// +// LP_utxo.c +// marketmaker +// + +uint64_t LP_value_extract(cJSON *obj) +{ + double val = 0.; uint64_t value; + if ( (val= jdouble(obj,"amount")) < SMALLVAL ) + val = jdouble(obj,"value"); + if ( val > SMALLVAL ) + value = (val * SATOSHIDEN + 0.0000000049); + else value = 0; + return(value); +} + +void LP_utxosetkey(uint8_t *key,bits256 txid,int32_t vout) +{ + memcpy(key,txid.bytes,sizeof(txid)); + memcpy(&key[sizeof(txid)],&vout,sizeof(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)]; + LP_utxosetkey(key,txid,vout); + HASH_FIND(hh,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)]; + LP_utxosetkey(key2,txid2,vout2); + HASH_FIND(hh2,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; + portable_mutex_lock(&LP_utxomutex); + utxo = _LP_utxofind(iambob,txid,vout); + portable_mutex_unlock(&LP_utxomutex); + return(utxo); +} + +struct LP_utxoinfo *LP_utxo2find(int32_t iambob,bits256 txid2,int32_t vout2) +{ + struct LP_utxoinfo *utxo=0; + portable_mutex_lock(&LP_utxomutex); + utxo = _LP_utxo2find(iambob,txid2,vout2); + portable_mutex_unlock(&LP_utxomutex); + return(utxo); +} + +struct LP_transaction *LP_transactionfind(struct iguana_info *coin,bits256 txid) +{ + struct LP_transaction *tx; + portable_mutex_lock(&coin->txmutex); + HASH_FIND(hh,coin->transactions,txid.bytes,sizeof(txid),tx); + portable_mutex_unlock(&coin->txmutex); + return(tx); +} + +struct LP_transaction *LP_transactionadd(struct iguana_info *coin,bits256 txid,int32_t height,int32_t numvouts,int32_t numvins) +{ + struct LP_transaction *tx; int32_t i; + if ( (tx= LP_transactionfind(coin,txid)) == 0 ) + { + //char str[65]; printf("%s ht.%d u.%u NEW TXID.(%s) vouts.[%d]\n",coin->symbol,height,timestamp,bits256_str(str,txid),numvouts); + //if ( bits256_nonz(txid) == 0 && tx->height == 0 ) + // getchar(); + tx = calloc(1,sizeof(*tx) + (sizeof(*tx->outpoints) * numvouts)); + for (i=0; ioutpoints[i].spendvini = -1; + tx->height = height; + tx->numvouts = numvouts; + tx->numvins = numvins; + //tx->timestamp = timestamp; + tx->txid = txid; + portable_mutex_lock(&coin->txmutex); + HASH_ADD_KEYPTR(hh,coin->transactions,tx->txid.bytes,sizeof(tx->txid),tx); + portable_mutex_unlock(&coin->txmutex); + } // else printf("warning adding already existing txid %s\n",bits256_str(str,tx->txid)); + return(tx); +} + +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; + *interestp = 0; + destaddr[0] = 0; + if ( (txobj= LP_gettxout(coin->symbol,txid,vout)) != 0 ) + { + if ( (value= LP_value_extract(txobj)) == 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); + } + else if ( strcmp(coin->symbol,"KMD") == 0 ) + { + if ( (interest= jdouble(txobj,"interest")) != 0. ) + { + //printf("add interest of %.8f to %.8f\n",interest,dstr(value)); + *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"); + //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) +{ + 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 ) + { + //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"); + if ( iter == 0 && vouts != 0 && (tx= LP_transactionadd(coin,txid,height,numvouts,numvins)) != 0 ) + { + //printf("create txid numvouts.%d numvins.%d\n",numvouts,numvins); + for (i=0; ioutpoints[i].value = LP_value_extract(vout); + 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); + } + } + //printf("numvouts.%d\n",numvouts); + } + if ( iter == 1 && vins != 0 ) + { + for (i=0; inumvouts ) + { + 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); + } //else printf("LP_transactioninit: couldnt find (%s) ht.%d %s\n",bits256_str(str,spenttxid),height,jprint(vin,0)); + if ( bits256_cmp(spenttxid,txid) == 0 ) + printf("spending same tx's %p vout ht.%d %s.[%d] s%d\n",tx,height,bits256_str(str,txid),tx!=0?tx->numvouts:0,spentvout); + } + } + free_json(txobj); + return(0); + } //else printf("LP_transactioninit error for %s %s\n",coin->symbol,bits256_str(str,txid)); + return(-1); +} + +int32_t LP_txheight(struct iguana_info *coin,bits256 txid) +{ + bits256 blockhash; struct LP_transaction *tx; cJSON *blockobj,*txobj; int32_t height = 0; + if ( coin == 0 ) + return(-1); + if ( coin->electrum == 0 ) + { + if ( (txobj= LP_gettx(coin->symbol,txid)) != 0 ) + { + //*timestampp = juint(txobj,"locktime"); + //*blocktimep = juint(txobj,"blocktime"); + blockhash = jbits256(txobj,"blockhash"); + if ( bits256_nonz(blockhash) != 0 && (blockobj= LP_getblock(coin->symbol,blockhash)) != 0 ) + { + height = jint(blockobj,"height"); + //printf("%s LP_txheight.%d\n",coin->symbol,height); + free_json(blockobj); + } //else printf("%s LP_txheight error (%s)\n",coin->symbol,jprint(txobj,0)); + free_json(txobj); + } + } + else + { + if ( (tx= LP_transactionfind(coin,txid)) != 0 ) + height = tx->height; + } + return(height); +} + +int32_t LP_numconfirms(char *symbol,char *coinaddr,bits256 txid,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 ( coin->electrum == 0 ) + numconfirms = jint(txobj,"confirmations"); + else numconfirms = coin->height - jint(txobj,"height"); + free_json(txobj); + } + else if ( mempool != 0 && LP_mempoolscan(symbol,txid) >= 0 ) + numconfirms = 0; + } + else + { + 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; + } + //#endif + return(numconfirms); +} + +int64_t basilisk_txvalue(char *symbol,bits256 txid,int32_t vout) +{ + char destaddr[64]; uint64_t value,interest = 0; struct iguana_info *coin; + if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) + return(0); + //char str[65]; printf("%s txvalue.(%s)\n",symbol,bits256_str(str,txid)); + value = LP_txinterestvalue(&interest,destaddr,coin,txid,vout); + return(value + interest); +} + +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]; + if ( bits256_nonz(txid) == 0 ) + return(0); + if ( (coin= LP_coinfind(symbol)) == 0 || coin->inactive != 0 ) + return(0); + if ( coinaddr != 0 ) + coinaddr[0] = 0; + if ( (tx= LP_transactionfind(coin,txid)) == 0 ) + { + LP_transactioninit(coin,txid,0); + LP_transactioninit(coin,txid,1); + tx = LP_transactionfind(coin,txid); + } + if ( tx != 0 ) + { + if ( vout < tx->numvouts ) + { + 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)); + return(0); + } + else + { + if ( coinaddr != 0 ) + { + //if ( tx->outpoints[vout].coinaddr[0] == 0 ) + // tx->outpoints[vout].value = LP_txinterestvalue(&tx->outpoints[vout].interest,tx->outpoints[vout].coinaddr,coin,txid,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); + } + } else printf("LP_txvalue vout.%d >= tx->numvouts.%d\n",vout,tx->numvouts); + } + else + { + if ( (txobj= LP_gettxout(coin->symbol,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); + } + printf("pruned node? LP_txvalue couldnt find %s tx %s\n",coin->symbol,bits256_str(str,txid)); + } + return(0); +} + +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); + if ( bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 ) + { + printf("null txid not eligible\n"); + return(-1); + } + destaddr[0] = destaddr2[0] = 0; + if ( coin != 0 && IAMLP != 0 && coin->inactive != 0 ) + bypass = 1; + if ( bypass != 0 ) + val = satoshis; + else val = LP_txvalue(destaddr,symbol,txid,vout); + txfee = LP_txfeecalc(LP_coinfind(symbol),0); + if ( val >= satoshis && val > (1+LP_MINSIZE_TXFEEMULT)*txfee ) + { + threshold = (iambob != 0) ? LP_DEPOSITSATOSHIS(satoshis) : (LP_DEXFEE(satoshis) + txfee); + if ( bypass != 0 ) + val2 = threshold; + else val2 = LP_txvalue(destaddr2,symbol,txid2,vout2); + if ( val2 >= threshold ) + { + if ( bypass == 0 && strcmp(destaddr,destaddr2) != 0 ) + printf("mismatched %s destaddr (%s) vs (%s)\n",symbol,destaddr,destaddr2); + else if ( bypass == 0 && ((iambob == 0 && val2 > val) || (iambob != 0 && val2 <= satoshis)) ) + printf("iambob.%d ineligible due to offsides: val %.8f and val2 %.8f vs %.8f diff %lld\n",iambob,dstr(val),dstr(val2),dstr(satoshis),(long long)(val2 - val)); + else + { + *valp = val; + *val2p = val2; + return(1); + } + } // else printf("no val2\n"); + } + char str[65],str2[65]; printf("spent.%d %s txid or value %.8f < %.8f or val2 %.8f < %.8f, %s/v%d %s/v%d or < 10x txfee %.8f\n",iambob,symbol,dstr(val),dstr(satoshis),dstr(val2),dstr(threshold),bits256_str(str,txid),vout,bits256_str(str2,txid2),vout2,dstr(txfee)); + /*for (iter=0; iter<2; iter++) + { + if ( (utxo= LP_utxofind(iter,txid,vout)) != 0 ) + { + //printf("iambob.%d case 00\n",iter); + if ( utxo->T.spentflag == 0 ) + utxo->T.spentflag = (uint32_t)time(NULL); + } + if ( (utxo= LP_utxo2find(iter,txid,vout)) != 0 ) + { + //printf("iambob.%d case 01\n",iter); + if ( utxo->T.spentflag == 0 ) + utxo->T.spentflag = (uint32_t)time(NULL); + } + if ( (utxo= LP_utxofind(iter,txid2,vout2)) != 0 ) + { + //printf("iambob.%d case 10\n",iter); + if ( utxo->T.spentflag == 0 ) + utxo->T.spentflag = (uint32_t)time(NULL); + } + if ( (utxo= LP_utxo2find(iter,txid2,vout2)) != 0 ) + { + //printf("iambob.%d case 11\n",iter); + if ( utxo->T.spentflag == 0 ) + utxo->T.spentflag = (uint32_t)time(NULL); + } + }*/ + *valp = val; + *val2p = val2; + return(0); +} + +int32_t LP_inventory_prevent(int32_t iambob,char *symbol,bits256 txid,int32_t vout) +{ + struct LP_utxoinfo *utxo; struct LP_transaction *tx; struct iguana_info *coin; + if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 || (utxo= LP_utxo2find(iambob,txid,vout)) != 0 ) + { + if ( (coin= LP_coinfind(symbol)) != 0 && (tx= LP_transactionfind(coin,txid)) != 0 ) + { + if ( tx->outpoints[vout].spendheight > 0 ) + utxo->T.spentflag = tx->outpoints[vout].spendheight; + else utxo->T.spentflag = 0; + } + 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); + return(1); + } + } + return(0); +} + +int32_t LP_undospends(struct iguana_info *coin,int32_t lastheight) +{ + int32_t i,ht,num = 0; struct LP_transaction *tx,*tmp; + HASH_ITER(hh,coin->transactions,tx,tmp) + { + for (i=0; inumvouts; i++) + { + if ( bits256_nonz(tx->outpoints[i].spendtxid) == 0 ) + continue; + if ( (ht= tx->outpoints[i].spendheight) == 0 ) + { + tx->outpoints[i].spendheight = LP_txheight(coin,tx->outpoints[i].spendtxid); + } + if ( (ht= tx->outpoints[i].spendheight) != 0 && ht > lastheight ) + { + char str[65]; printf("clear spend %s/v%d at ht.%d > lastheight.%d\n",bits256_str(str,tx->txid),i,ht,lastheight); + tx->outpoints[i].spendheight = 0; + tx->outpoints[i].spendvini = -1; + memset(tx->outpoints[i].spendtxid.bytes,0,sizeof(bits256)); + } + } + } + return(num); +} diff --git a/iguana/exchanges/LP_utxos.c b/iguana/exchanges/LP_utxos.c index ecdbb9bf8..bf985cae1 100644 --- a/iguana/exchanges/LP_utxos.c +++ b/iguana/exchanges/LP_utxos.c @@ -41,37 +41,6 @@ int32_t LP_isunspent(struct LP_utxoinfo *utxo) else return(0); } -void LP_utxosetkey(uint8_t *key,bits256 txid,int32_t vout) -{ - memcpy(key,txid.bytes,sizeof(txid)); - memcpy(&key[sizeof(txid)],&vout,sizeof(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)]; - LP_utxosetkey(key,txid,vout); - HASH_FIND(hh,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)]; - LP_utxosetkey(key2,txid2,vout2); - HASH_FIND(hh2,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; - portable_mutex_lock(&LP_utxomutex); - utxo = _LP_utxofind(iambob,txid,vout); - portable_mutex_unlock(&LP_utxomutex); - return(utxo); -} - struct LP_utxoinfo *LP_utxopairfind(int32_t iambob,bits256 txid,int32_t vout,bits256 txid2,int32_t vout2) { struct LP_utxoinfo *utxo=0; struct _LP_utxoinfo u; @@ -84,15 +53,6 @@ struct LP_utxoinfo *LP_utxopairfind(int32_t iambob,bits256 txid,int32_t vout,bit return(0); } -struct LP_utxoinfo *LP_utxo2find(int32_t iambob,bits256 txid2,int32_t vout2) -{ - struct LP_utxoinfo *utxo=0; - portable_mutex_lock(&LP_utxomutex); - utxo = _LP_utxo2find(iambob,txid2,vout2); - portable_mutex_unlock(&LP_utxomutex); - return(utxo); -} - struct LP_utxoinfo *LP_utxofinds(int32_t iambob,bits256 txid,int32_t vout,bits256 txid2,int32_t vout2) { struct LP_utxoinfo *utxo; @@ -286,75 +246,6 @@ cJSON *LP_utxojson(struct LP_utxoinfo *utxo) return(item); } -int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol,bits256 txid,int32_t vout,uint64_t satoshis,bits256 txid2,int32_t vout2) -{ - //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); - if ( bits256_nonz(txid) == 0 || bits256_nonz(txid2) == 0 ) - { - printf("null txid not eligible\n"); - return(-1); - } - destaddr[0] = destaddr2[0] = 0; - if ( coin != 0 && IAMLP != 0 && coin->inactive != 0 ) - bypass = 1; - if ( bypass != 0 ) - val = satoshis; - else val = LP_txvalue(destaddr,symbol,txid,vout); - txfee = LP_txfeecalc(LP_coinfind(symbol),0); - if ( val >= satoshis && val > (1+LP_MINSIZE_TXFEEMULT)*txfee ) - { - threshold = (iambob != 0) ? LP_DEPOSITSATOSHIS(satoshis) : (LP_DEXFEE(satoshis) + txfee); - if ( bypass != 0 ) - val2 = threshold; - else val2 = LP_txvalue(destaddr2,symbol,txid2,vout2); - if ( val2 >= threshold ) - { - if ( bypass == 0 && strcmp(destaddr,destaddr2) != 0 ) - printf("mismatched %s destaddr (%s) vs (%s)\n",symbol,destaddr,destaddr2); - else if ( bypass == 0 && ((iambob == 0 && val2 > val) || (iambob != 0 && val2 <= satoshis)) ) - printf("iambob.%d ineligible due to offsides: val %.8f and val2 %.8f vs %.8f diff %lld\n",iambob,dstr(val),dstr(val2),dstr(satoshis),(long long)(val2 - val)); - else - { - *valp = val; - *val2p = val2; - return(1); - } - } // else printf("no val2\n"); - } - char str[65],str2[65]; printf("spent.%d %s txid or value %.8f < %.8f or val2 %.8f < %.8f, %s/v%d %s/v%d or < 10x txfee %.8f\n",iambob,symbol,dstr(val),dstr(satoshis),dstr(val2),dstr(threshold),bits256_str(str,txid),vout,bits256_str(str2,txid2),vout2,dstr(txfee)); - /*for (iter=0; iter<2; iter++) - { - if ( (utxo= LP_utxofind(iter,txid,vout)) != 0 ) - { - //printf("iambob.%d case 00\n",iter); - if ( utxo->T.spentflag == 0 ) - utxo->T.spentflag = (uint32_t)time(NULL); - } - if ( (utxo= LP_utxo2find(iter,txid,vout)) != 0 ) - { - //printf("iambob.%d case 01\n",iter); - if ( utxo->T.spentflag == 0 ) - utxo->T.spentflag = (uint32_t)time(NULL); - } - if ( (utxo= LP_utxofind(iter,txid2,vout2)) != 0 ) - { - //printf("iambob.%d case 10\n",iter); - if ( utxo->T.spentflag == 0 ) - utxo->T.spentflag = (uint32_t)time(NULL); - } - if ( (utxo= LP_utxo2find(iter,txid2,vout2)) != 0 ) - { - //printf("iambob.%d case 11\n",iter); - if ( utxo->T.spentflag == 0 ) - utxo->T.spentflag = (uint32_t)time(NULL); - } - }*/ - *valp = val; - *val2p = val2; - return(0); -} - 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(); @@ -383,26 +274,6 @@ char *LP_utxos(int32_t iambob,struct LP_peerinfo *mypeer,char *symbol,int32_t la return(jprint(utxosjson,1)); } -int32_t LP_inventory_prevent(int32_t iambob,char *symbol,bits256 txid,int32_t vout) -{ - struct LP_utxoinfo *utxo; struct LP_transaction *tx; struct iguana_info *coin; - if ( (utxo= LP_utxofind(iambob,txid,vout)) != 0 || (utxo= LP_utxo2find(iambob,txid,vout)) != 0 ) - { - if ( (coin= LP_coinfind(symbol)) != 0 && (tx= LP_transactionfind(coin,txid)) != 0 ) - { - if ( tx->outpoints[vout].spendheight > 0 ) - utxo->T.spentflag = tx->outpoints[vout].spendheight; - else utxo->T.spentflag = 0; - } - 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); - return(1); - } - } - return(0); -} - struct LP_utxoinfo *LP_utxo_bestfit(char *symbol,uint64_t destsatoshis) { uint64_t srcvalue,srcvalue2; struct LP_utxoinfo *utxo,*tmp,*bestutxo = 0; @@ -666,11 +537,11 @@ struct LP_utxoinfo *LP_utxoadd(int32_t iambob,int32_t mypubsock,char *symbol,bit if ( _LP_utxo2find(iambob,txid2,vout2) == 0 ) HASH_ADD_KEYPTR(hh2,LP_utxoinfos2[iambob],utxo->key2,sizeof(utxo->key2),utxo); portable_mutex_unlock(&LP_utxomutex); - if ( 0 && coin->electrum == 0 ) + /*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 )