diff --git a/basilisk/basilisk.c b/basilisk/basilisk.c index 0b5e607b4..ba9ab65ba 100755 --- a/basilisk/basilisk.c +++ b/basilisk/basilisk.c @@ -935,23 +935,33 @@ HASH_ARRAY_STRING(basilisk,history,hash,vals,hexstr) return(clonestr("{\"error\":\"couldnt find coin\"}")); unspents = cJSON_CreateArray(); spends = cJSON_CreateArray(); + portable_mutex_lock(&myinfo->bu_mutex); HASH_ITER(hh,myinfo->wallet,wacct,tmp) { HASH_ITER(hh,wacct->waddr,waddr,tmp2) { - if ( waddr->Cunspents != 0 && (array= jobj(waddr->Cunspents,coin->symbol)) != 0 ) + if ( waddr->Cunspents != 0 ) { - if ( (n= cJSON_GetArraySize(array)) > 0 ) + //printf("Cunspents.(%s)\n",jprint(waddr->Cunspents,0)); + if ( (array= jobj(waddr->Cunspents,coin->symbol)) != 0 ) { - for (i=0; i 0 ) + { + for (i=0; iCspends != 0 && (array= jobj(waddr->Cspends,coin->symbol)) != 0 ) - jaddi(spends,jduplicate(array)); + if ( waddr->Cspends != 0 ) + { + //printf("Cspends.(%s)\n",jprint(waddr->Cspends,0)); + if ( (array= jobj(waddr->Cspends,coin->symbol)) != 0 ) + jaddi(spends,jduplicate(array)); + } } } + portable_mutex_unlock(&myinfo->bu_mutex); retjson = cJSON_CreateObject(); jaddstr(retjson,"result","success"); jadd(retjson,"unspents",unspents); diff --git a/basilisk/basilisk_bitcoin.c b/basilisk/basilisk_bitcoin.c index 1c760c09f..ec9af88b0 100755 --- a/basilisk/basilisk_bitcoin.c +++ b/basilisk/basilisk_bitcoin.c @@ -299,7 +299,7 @@ int32_t basilisk_bitcoinavail(struct iguana_info *coin) void *basilisk_bitcoinbalances(struct basilisk_item *Lptr,struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,cJSON *vals) { - int64_t balance,total = 0; int32_t i,n,hist; char *str; cJSON *spends,*unspents,*retjson,*item,*addresses,*array = cJSON_CreateArray(); + int64_t balance,total = 0; int32_t i,j,n,hist; char *str; cJSON *spends,*unspents,*retjson,*item,*addresses,*array = cJSON_CreateArray(); spends = unspents = 0; if ( (hist= juint(vals,"history")) != 0 ) { @@ -315,10 +315,15 @@ void *basilisk_bitcoinbalances(struct basilisk_item *Lptr,struct supernet_info * { if ( (str= jstri(addresses,i)) != 0 ) { + for (j=0; jRTheight); jaddnum(retjson,"longest",coin->longestchain); jaddnum(retjson,"lag",coin->longestchain- coin->RTheight); +//printf("RETSTR.(%s)\n",jprint(retjson,0)); Lptr->retstr = jprint(retjson,1); return(Lptr); } @@ -526,7 +532,10 @@ char *basilisk_bitcoinrawtx(struct supernet_info *myinfo,struct iguana_info *coi decode_hex(&buf[sizeof(buf) - oplen],oplen,opreturn); spendlen = datachain_datascript(coin,buf,&buf[sizeof(buf) - oplen],oplen); if ( (burnamount= SATOSHIDEN * jdouble(valsobj,"burn")) < 10000 ) - burnamount = 10000; + { + //burnamount = 10000; + printf("low burnamount %.8f\n",dstr(burnamount)); + } bitcoin_txoutput(txobj,buf,spendlen,burnamount); oplen = 0; } else oplen = datachain_opreturnscript(coin,buf,opreturn,oplen); @@ -823,8 +832,8 @@ HASH_ARRAY_STRING(basilisk,rawtx,hash,vals,hexstr) jaddnum(vals,"fanout",(int32_t)sqrt(NUMRELAYS)); if ( coin != 0 ) { - if ( juint(vals,"burn") == 0 ) - jaddnum(vals,"burn",0.0001); + //if ( juint(vals,"burn") == 0 ) + // jaddnum(vals,"burn",0.0001); if ( (basilisktag= juint(vals,"basilisktag")) == 0 ) basilisktag = rand(); if ( (timeoutmillis= juint(vals,"timeout")) <= 0 ) @@ -883,6 +892,29 @@ int32_t basilisk_unspentfind(struct supernet_info *myinfo,struct iguana_info *co return(-1); } +void basilisk_jsonmerge(cJSON *json,char *symbol,cJSON *array) +{ + int32_t i,j,n,m; cJSON *jobj,*iobj,*dest; + if ( (dest= jarray(&m,json,symbol)) == 0 ) + dest = cJSON_CreateArray(); + if ( dest != 0 && (n= cJSON_GetArraySize(array)) > 0 ) + { + m = cJSON_GetArraySize(dest); + for (i=0; iCspends == 0 ) + { waddr->Cspends = cJSON_CreateObject(); - if ( jobj(waddr->Cspends,coin->symbol) != 0 ) - jdelete(waddr->Cspends,coin->symbol); // better merge and error check if basilisk - jadd(waddr->Cspends,coin->symbol,jduplicate(spends)); + jadd(waddr->Cspends,coin->symbol,jduplicate(spends)); + } else basilisk_jsonmerge(waddr->Cspends,coin->symbol,spends); } + //printf("merge spends.(%s)\n",jprint(spends,0)); } if ( (unspents= jarray(&n,json,"unspents")) != 0 ) { @@ -904,11 +937,12 @@ void basilisk_unspent_update(struct supernet_info *myinfo,struct iguana_info *co if ( (address= jstr(item,"address")) != 0 && (waddr= iguana_waddresssearch(myinfo,&wacct,address)) != 0 ) { if ( waddr->Cunspents == 0 ) + { waddr->Cunspents = cJSON_CreateObject(); - if ( jobj(waddr->Cunspents,coin->symbol) != 0 ) - jdelete(waddr->Cunspents,coin->symbol); // better merge and error check if basilisk - jadd(waddr->Cunspents,coin->symbol,jduplicate(unspents)); + jadd(waddr->Cunspents,coin->symbol,jduplicate(unspents)); + } else basilisk_jsonmerge(waddr->Cunspents,coin->symbol,unspents); } + //printf("merge unspents.(%s)\n",jprint(unspents,0)); } } @@ -924,14 +958,18 @@ void basilisk_unspents_update(struct supernet_info *myinfo,struct iguana_info *c jaddstr(vals,"coin",coin->symbol); if ( (retstr= basilisk_balances(myinfo,coin,0,0,GENESIS_PUBKEY,vals,"")) != 0 ) { + //printf("basilisk_balances.(%s)\n",retstr); if ( (retarray= cJSON_Parse(retstr)) != 0 ) { + portable_mutex_lock(&myinfo->bu_mutex); + iguana_wallet_Cclear(myinfo,coin->symbol); if ( is_cJSON_Array(retarray) != 0 ) { for (i=0; ibu_mutex); } free(retstr); } diff --git a/iguana/iguana_payments.c b/iguana/iguana_payments.c index 49f9c21e7..07b7ea747 100755 --- a/iguana/iguana_payments.c +++ b/iguana/iguana_payments.c @@ -218,7 +218,7 @@ cJSON *iguana_inputjson(bits256 txid,int32_t vout,uint8_t *spendscript,int32_t s cJSON *iguana_RTinputsjson(struct supernet_info *myinfo,struct iguana_info *coin,uint64_t *totalp,uint64_t amount,struct iguana_outpoint *unspents,int32_t num) { - cJSON *vins; uint8_t spendscript[IGUANA_MAXSCRIPTSIZE]; struct iguana_txid *T; struct iguana_unspent *U,*u; struct iguana_bundle *bp; struct iguana_ramchain *ramchain; char coinaddr[64]; int32_t vout,height,abovei,belowi,i,spendlen,ind; uint32_t txidind; struct iguana_ramchaindata *rdata; bits256 txid; int64_t above,below,total = 0,remains = amount; struct iguana_outpoint outpt; uint64_t RTspent; + cJSON *vins; uint8_t spendscript[IGUANA_MAXSCRIPTSIZE]; struct iguana_txid *T; struct iguana_unspent *U,*u; struct iguana_bundle *bp; struct iguana_ramchain *ramchain; char coinaddr[64]; int32_t vout,height,abovei,belowi,i,spendlen,ind; uint32_t txidind; struct iguana_ramchaindata *rdata; bits256 txid; int64_t above,below,total = 0,remains = amount; struct iguana_outpoint outpt,outpt2; //uint64_t RTspent; *totalp = 0; vins = cJSON_CreateArray(); for (i=0; itxidind) > 0 && txidind < rdata->numtxids ) { - if ( iguana_unspentindfind(myinfo,coin,&RTspent,coinaddr,spendscript,&spendlen,&amount,&height,T[txidind].txid,u->vout,coin->bundlescount-1,0) == outpt.unspentind && spendlen > 0 ) + if ( iguana_RTunspentindfind(myinfo,coin,&outpt2,coinaddr,spendscript,&spendlen,&amount,&height,T[txidind].txid,u->vout,coin->bundlescount-1,0) == 0 && spendlen > 0 ) { jaddi(vins,iguana_inputjson(T[txidind].txid,u->vout,spendscript,spendlen)); total += outpt.value; @@ -374,6 +374,7 @@ char *iguana_calcrawtx(struct supernet_info *myinfo,struct iguana_info *coin,cJS free(unspents); return(0); } + printf("avail %.8f satoshis %.8f, txfee %.8f burnamount %.8f\n",dstr(avail),dstr(satoshis),dstr(txfee),dstr(burnamount)); if ( txobj != 0 && avail >= satoshis+txfee ) { if ( (vins= iguana_RTinputsjson(myinfo,coin,&total,satoshis + txfee,unspents,num)) != 0 ) diff --git a/iguana/iguana_sign.c b/iguana/iguana_sign.c index fb0cec705..45460ce25 100755 --- a/iguana/iguana_sign.c +++ b/iguana/iguana_sign.c @@ -154,7 +154,10 @@ int32_t iguana_parsehexstr(uint8_t **destp,uint16_t *lenp,uint8_t *dest2,int32_t n = (int32_t)strlen(hexstr) >> 1; //printf("addhex.(%s) %d\n",hexstr,n); if ( serialized == 0 ) - serialized = *destp; + { + if ( (serialized= *destp) == 0 ) + printf("iguana_parsehexstr null serialized and destp\n"); + } if ( serialized != 0 ) { decode_hex(serialized,n,hexstr); @@ -323,7 +326,9 @@ int32_t iguana_parsevinobj(struct supernet_info *myinfo,struct iguana_info *coin len += iguana_rwnum(rwflag,&serialized[len],sizeof(vin->sequence),&vin->sequence); if ( spendstr != 0 ) { - n = iguana_parsehexstr(&vin->spendscript,&vin->spendlen,V!=0?V->spendscript:0,V!=0?&V->spendlen:0,0,spendstr); + //printf("serialized.%p len.%d\n",serialized,len); + n = iguana_parsehexstr(&vin->spendscript,&vin->spendlen,V!=0?V->spendscript:0,V!=0?&V->spendlen:0,&serialized[len],spendstr); + len += n; } return(len); } @@ -603,6 +608,7 @@ bits256 iguana_parsetxobj(struct supernet_info *myinfo,struct iguana_info *coin, return(txid); maxsize -= (sizeof(struct iguana_msgvin) * msg->tx_in); msg->vins = (struct iguana_msgvin *)&serialized[maxsize]; + memset(msg->vins,0,sizeof(struct iguana_msgvin) * msg->tx_in); if ( msg->tx_in > 0 && msg->tx_in*sizeof(struct iguana_msgvin) < maxsize ) { for (i=0; itx_in; i++) @@ -620,6 +626,7 @@ bits256 iguana_parsetxobj(struct supernet_info *myinfo,struct iguana_info *coin, return(txid); maxsize -= (sizeof(struct iguana_msgvout) * msg->tx_out); msg->vouts = (struct iguana_msgvout *)&serialized[maxsize]; + memset(msg->vouts,0,sizeof(struct iguana_msgvout) * msg->tx_out); if ( msg->tx_out > 0 && msg->tx_out*sizeof(struct iguana_msgvout) < maxsize ) { for (i=0; itx_out; i++) diff --git a/iguana/iguana_unspents.c b/iguana/iguana_unspents.c index 18cbc0703..38dc804eb 100755 --- a/iguana/iguana_unspents.c +++ b/iguana/iguana_unspents.c @@ -435,6 +435,7 @@ int32_t iguana_RTscanunspents(struct supernet_info *myinfo,struct iguana_info *c else printf("unspent has no parent?\n"); outpt.isptr = 1; outpt.ptr = unspent; + outpt.value = unspent->value; outpt.hdrsi = unspent->height / coin->chain->bundlesize; if ( array != 0 ) jaddi(array,iguana_RTunspentjson(myinfo,coin,outpt,txid,unspent->vout,unspent->value,0,rmd160,coinaddr,pubkey33,spentheight,remoteaddr)); @@ -555,7 +556,7 @@ int32_t iguana_RTpkhasharray(struct supernet_info *myinfo,struct iguana_info *co if ( max > coin->bundlescount ) max = coin->bundlescount; //printf("minconf.%d maxconf.%d max.%d addr.%s last.%d maxunspents.%d\n",minconf,maxconf,max,coinaddr,lastheight,maxunspents); - for (total=n=i=0; i=coin->RTheight); i++) + for (total=n=i=0; i=coin->firstRTheight); i++) { if ( i != max && (bp= coin->bundles[i]) == 0 ) continue; @@ -635,7 +636,7 @@ int64_t iguana_RTunspents(struct supernet_info *myinfo,struct iguana_info *coin, continue; bitcoin_address(coinaddr,addrtypes[i],&rmdarray[i * 20],20); *numunspentsp = 0; - iguana_RTpkhasharray(myinfo,coin,array,minconf,maxconf,&total,P,coin->bundlescount,&rmdarray[i * 20],coinaddr,&pubkeys[33*i],lastheight,&unspents[numunspents],numunspentsp,maxunspents,remoteaddr,includespent); + iguana_RTpkhasharray(myinfo,coin,array,minconf,maxconf,&total,P,coin->bundlescount,&rmdarray[i * 20],coinaddr,&pubkeys[33*i],lastheight,unspents != 0 ? &unspents[numunspents] : 0,numunspentsp,maxunspents,remoteaddr,includespent); //printf("iguana_unspents: i.%d of %d: %s %.8f numunspents.%d\n",i,numrmds,coinaddr,dstr(total),*numunspentsp); maxunspents -= *numunspentsp; numunspents += *numunspentsp; @@ -789,7 +790,7 @@ int32_t iguana_RTunspent_check(struct supernet_info *myinfo,struct iguana_info * { bits256 txid; int32_t vout,spentheight; memset(&txid,0,sizeof(txid)); - printf("RTunspent_check needs to be ported\n"); + printf("RTunspent_check needs to be ported to prevent reusing utxo, but should work if one spend per block\n"); return(0); if ( iguana_RTunspentind2txid(myinfo,coin,&spentheight,&txid,&vout,outpt) == 0 ) { @@ -846,10 +847,11 @@ int32_t iguana_RTunspentslists(struct supernet_info *myinfo,struct iguana_info * continue; if ( coin->FULLNODE != 0 || coin->VALIDATENODE != 0 ) { - numunspents += iguana_RTaddr_unspents(myinfo,coin,&sum,&unspents[numunspents],max-numunspents,coinaddr,remoteaddr,coin->blocks.hwmchain.height - minconf,0); + numunspents += iguana_RTaddr_unspents(myinfo,coin,&sum,&unspents[numunspents],max-numunspents,coinaddr,remoteaddr,1<<30,0); } else { + portable_mutex_lock(&myinfo->bu_mutex); if ( (waddr= iguana_waddresssearch(myinfo,&wacct,coinaddr)) != 0 ) { if ( waddr->Cunspents != 0 && (array= jobj(waddr->Cunspents,coin->symbol)) != 0 ) @@ -868,6 +870,7 @@ int32_t iguana_RTunspentslists(struct supernet_info *myinfo,struct iguana_info * } } } + portable_mutex_unlock(&myinfo->bu_mutex); } if ( numunspents > max || sum > required ) break; @@ -875,6 +878,7 @@ int32_t iguana_RTunspentslists(struct supernet_info *myinfo,struct iguana_info * } } *totalp = sum; + printf("numunspents.%d sum %.8f\n",numunspents,dstr(sum)); return(numunspents); } diff --git a/iguana/iguana_wallet.c b/iguana/iguana_wallet.c index a12b2d9c1..9cc62be75 100755 --- a/iguana/iguana_wallet.c +++ b/iguana/iguana_wallet.c @@ -330,6 +330,21 @@ cJSON *iguana_getaddressesbyaccount(struct supernet_info *myinfo,struct iguana_i return(array); } +void iguana_wallet_Cclear(struct supernet_info *myinfo,char *symbol) +{ + struct iguana_waccount *subset,*tmp; struct iguana_waddress *waddr,*tmp2; + HASH_ITER(hh,myinfo->wallet,subset,tmp) + { + HASH_ITER(hh,subset->waddr,waddr,tmp2) + { + if ( waddr->Cspends != 0 ) + free_json(waddr->Cspends), waddr->Cspends = 0; + if ( waddr->Cunspents != 0 ) + free_json(waddr->Cunspents), waddr->Cunspents = 0; + } + } +} + struct iguana_waddress *iguana_ismine(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr,uint8_t addrtype,uint8_t pubkey[65],uint8_t rmd160[20]) { struct iguana_waccount *wacct; struct iguana_waddress *waddr = 0; @@ -986,9 +1001,9 @@ int64_t iguana_addressreceived(struct supernet_info *myinfo,struct iguana_info * jaddibits256(txids,jbits256(item,"txid")); if ( vouts != 0 ) jaddinum(vouts,jint(item,"vout")); - if ( unspents != 0 && jobj(item,"unspent") != 0 ) + if ( unspents != 0 && (jobj(item,"spent") == 0 || jobj(item,"dest") == 0) ) jaddi(unspents,jduplicate(item)); - if ( spends != 0 && jobj(item,"spent") != 0 ) + if ( spends != 0 && jobj(item,"spent") != 0 && jobj(item,"dest") != 0 ) jaddi(spends,jduplicate(item)); } } @@ -997,6 +1012,10 @@ int64_t iguana_addressreceived(struct supernet_info *myinfo,struct iguana_info * } free(balancestr); } + //if ( spends != 0 ) + // printf("SPENDS.(%s)\n",jprint(spends,0)); + //if ( unspents != 0 ) + // printf("UNSPENTS.(%s)\n",jprint(unspents,0)); return(balance); } diff --git a/iguana/tests/balance2 b/iguana/tests/balance2 new file mode 100755 index 000000000..53cd0bfd5 --- /dev/null +++ b/iguana/tests/balance2 @@ -0,0 +1 @@ +curl --url "http://127.0.0.1:7778" --data "{\"activecoin\":\"BTCD\",\"timeout\":20000,\"agent\":\"iguana\",\"method\":\"balance\",\"address\":\"RFMEYcxuBL8S7UPdUbzXunPtS4p82HRcKs\"}" diff --git a/iguana/tests/history b/iguana/tests/history index 7b63b6ee7..0546e0f11 100755 --- a/iguana/tests/history +++ b/iguana/tests/history @@ -1 +1 @@ -curl --url "http://127.0.0.1:7778" --data "{\"timeout\":20000,\"agent\":\"basilisk\",\"method\":\"history\",\"vals\":{\"coin\":\"BTC\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"timeout\":20000,\"agent\":\"basilisk\",\"method\":\"history\",\"vals\":{\"coin\":\"BTCD\"}}" diff --git a/includes/iguana_funcs.h b/includes/iguana_funcs.h index a12110ae7..164aa5795 100755 --- a/includes/iguana_funcs.h +++ b/includes/iguana_funcs.h @@ -426,6 +426,7 @@ struct iguana_waddress *iguana_waddresssearch(struct supernet_info *myinfo,struc cJSON *iguana_RTlistunspent(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *argarray,int32_t minconf,int32_t maxconf,char *remoteaddr,int32_t includespends); void calc_shares(struct supernet_info *myinfo,uint8_t *shares,uint8_t *secret,int32_t size,int32_t width,int32_t M,int32_t N,uint8_t *sharenrs,uint8_t *space,int32_t spacesize); //struct basilisk_spend *basilisk_addspend(struct supernet_info *myinfo,char *symbol,bits256 txid,uint16_t vout,int32_t addflag); +void iguana_wallet_Cclear(struct supernet_info *myinfo,char *symbol); int64_t _RTgettxout(struct iguana_info *coin,struct iguana_RTtxid **ptrp,int32_t *heightp,int32_t *scriptlenp,uint8_t *script,uint8_t *rmd160,char *coinaddr,bits256 txid,int32_t vout,int32_t mempool); int32_t _iguana_RTunspentfind(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *txidp,int32_t *voutp,uint8_t *spendscript,struct iguana_outpoint outpt,int64_t value); int32_t basilisk_unspentfind(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *txidp,int32_t *voutp,uint8_t *spendscript,struct iguana_outpoint outpt,int64_t value);