diff --git a/basilisk/basilisk.c b/basilisk/basilisk.c index 1fa867886..80dac4853 100755 --- a/basilisk/basilisk.c +++ b/basilisk/basilisk.c @@ -308,9 +308,11 @@ struct basilisk_item *basilisk_issueremote(struct supernet_info *myinfo,struct i strcpy(pending->CMD,CMD); while ( OS_milliseconds() < pending->expiration ) { - //if ( (retstr= basilisk_iscomplete(ptr)) != 0 ) - if ( pending->numresults >= pending->numrequired || (retstr= pending->retstr) != 0 ) + if ( pending->numresults >= pending->numrequired )//|| (retstr= pending->retstr) != 0 ) + { + //printf("numresults.%d vs numrequired.%d\n",pending->numresults,pending->numrequired); break; + } usleep(10000); } if ( (retarray= pending->retarray) != 0 ) @@ -329,7 +331,8 @@ struct basilisk_item *basilisk_issueremote(struct supernet_info *myinfo,struct i struct basilisk_item *basilisk_requestservice(struct supernet_info *myinfo,struct iguana_peer *addr,char *CMD,int32_t blockflag,cJSON *valsobj,bits256 hash,uint8_t *data,int32_t datalen,uint32_t nBits) { - int32_t minresults,timeoutmillis,numsent,delaymillis,encryptflag,fanout; struct basilisk_item *ptr; char buf[4096],*symbol,*str = 0; struct iguana_info *virt; + int32_t numrequired,timeoutmillis,numsent,delaymillis,encryptflag,fanout; struct basilisk_item *ptr; char buf[4096],*symbol,*str = 0; struct iguana_info *virt; + //printf("request.(%s)\n",jprint(valsobj,0)); basilisk_addhexstr(&str,valsobj,buf,sizeof(buf),data,datalen); if ( bits256_cmp(hash,GENESIS_PUBKEY) != 0 && bits256_nonz(hash) != 0 ) { @@ -337,8 +340,8 @@ struct basilisk_item *basilisk_requestservice(struct supernet_info *myinfo,struc jdelete(valsobj,"hash"); jaddbits256(valsobj,"hash",hash); } - if ( (minresults= jint(valsobj,"minresults")) <= 0 ) - minresults = 1; + if ( (numrequired= jint(valsobj,"numrequired")) <= 0 ) + numrequired = 1; if ( (timeoutmillis= jint(valsobj,"timeout")) == 0 ) timeoutmillis = BASILISK_TIMEOUT; if ( jobj(valsobj,"fanout") == 0 ) @@ -357,7 +360,7 @@ struct basilisk_item *basilisk_requestservice(struct supernet_info *myinfo,struc symbol = "BTCD"; encryptflag = jint(valsobj,"encrypt"); delaymillis = jint(valsobj,"delay"); - ptr = basilisk_issueremote(myinfo,addr,&numsent,CMD,symbol,blockflag,valsobj,fanout,minresults,0,timeoutmillis,0,0,encryptflag,delaymillis,nBits); + ptr = basilisk_issueremote(myinfo,addr,&numsent,CMD,symbol,blockflag,valsobj,fanout,numrequired,0,timeoutmillis,0,0,encryptflag,delaymillis,nBits); return(ptr); } @@ -863,7 +866,7 @@ void basilisk_requests_poll(struct supernet_info *myinfo) void basilisks_loop(void *arg) { - struct iguana_info *virt,*tmpcoin,*btcd; struct basilisk_message *msg,*tmpmsg; struct basilisk_item *tmp,*pending; uint32_t now; int32_t iter,maxmillis,flag=0; struct supernet_info *myinfo = arg; + struct iguana_info *virt,*tmpcoin,*coin,*btcd; struct basilisk_message *msg,*tmpmsg; struct basilisk_item *tmp,*pending; uint32_t now; int32_t i,iter,maxmillis,flag=0; struct supernet_info *myinfo = arg; iter = 0; while ( 1 ) { @@ -896,10 +899,17 @@ void basilisks_loop(void *arg) if ( (rand() % 100) == 0 && myinfo->RELAYID >= 0 ) basilisk_ping_send(myinfo,btcd); } - //fprintf(stderr,"i "); - //for (i=0; iRELAYNODE == 0 && coin->VALIDATENODE == 0 && coin->active != 0 && coin->chain->userpass[0] != 0 && coin->MAXPEERS == 1 ) - // basilisk_bitcoinscan(coin,blockspace,&RAWMEM); + HASH_ITER(hh,myinfo->allcoins,coin,tmpcoin) + { + if ( coin->RELAYNODE == 0 && coin->VALIDATENODE == 0 ) + { + for (i=0; irelay_RTheights[i] != 0 ) + break; + if ( i == BASILISK_MAXRELAYS || (time(NULL) % 60) == 0 ) + basilisk_unspents_update(myinfo,coin); + } + } if ( (myinfo->RELAYID >= 0 || time(NULL) < myinfo->DEXactive) ) basilisk_requests_poll(myinfo); now = (uint32_t)time(NULL); @@ -923,6 +933,7 @@ void basilisks_loop(void *arg) void basilisks_init(struct supernet_info *myinfo) { iguana_initQ(&myinfo->msgQ,"messageQ"); + portable_mutex_init(&myinfo->bu_mutex); portable_mutex_init(&myinfo->allcoins_mutex); portable_mutex_init(&myinfo->basilisk_mutex); portable_mutex_init(&myinfo->DEX_mutex); diff --git a/basilisk/basilisk_bitcoin.c b/basilisk/basilisk_bitcoin.c index a9529d14d..df5cc054b 100755 --- a/basilisk/basilisk_bitcoin.c +++ b/basilisk/basilisk_bitcoin.c @@ -783,32 +783,6 @@ cJSON *BTC_makeclaimfunc(struct supernet_info *myinfo,struct exchange_info *exch #include "../includes/iguana_apidefs.h" #include "../includes/iguana_apideclares.h" -HASH_ARRAY_STRING(basilisk,balances,hash,vals,hexstr) -{ - char *retstr=0,*symbol; uint32_t basilisktag; struct basilisk_item *ptr,Lptr; int32_t timeoutmillis; - if ( coin == 0 ) - { - if ( (symbol= jstr(vals,"symbol")) != 0 || (symbol= jstr(vals,"coin")) != 0 ) - coin = iguana_coinfind(symbol); - } - if ( coin != 0 && vals != 0 ) - { - if ( jobj(vals,"addresses") == 0 ) - jadd(vals,"addresses",iguana_getaddressesbyaccount(myinfo,coin,"*")); - if ( (basilisktag= juint(vals,"basilisktag")) == 0 ) - basilisktag = rand(); - if ( (timeoutmillis= juint(vals,"timeout")) <= 0 ) - timeoutmillis = BASILISK_TIMEOUT; - if ( coin->RELAYNODE != 0 && (ptr= basilisk_bitcoinbalances(&Lptr,myinfo,coin,remoteaddr,basilisktag,timeoutmillis,vals)) != 0 ) - { - retstr = ptr->retstr, ptr->retstr = 0; - ptr->finished = (uint32_t)time(NULL); - return(retstr); - } - } - return(basilisk_standardservice("BAL",myinfo,0,hash,vals,hexstr,1)); -} - HASH_ARRAY_STRING(basilisk,value,hash,vals,hexstr) { char *retstr=0,*symbol; uint32_t basilisktag; struct basilisk_item *ptr,Lptr; int32_t timeoutmillis; @@ -817,6 +791,8 @@ HASH_ARRAY_STRING(basilisk,value,hash,vals,hexstr) if ( (symbol= jstr(vals,"symbol")) != 0 || (symbol= jstr(vals,"coin")) != 0 ) coin = iguana_coinfind(symbol); } + if ( jobj(vals,"fanout") == 0 ) + jaddnum(vals,"fanout",8); if ( coin != 0 ) { if ( (basilisktag= juint(vals,"basilisktag")) == 0 ) @@ -841,6 +817,8 @@ HASH_ARRAY_STRING(basilisk,rawtx,hash,vals,hexstr) if ( (symbol= jstr(vals,"symbol")) != 0 || (symbol= jstr(vals,"coin")) != 0 ) coin = iguana_coinfind(symbol); } + if ( jobj(vals,"fanout") == 0 ) + jaddnum(vals,"fanout",8); if ( coin != 0 ) { if ( juint(vals,"burn") == 0 ) @@ -887,4 +865,228 @@ HASH_ARRAY_STRING(basilisk,rawtx,hash,vals,hexstr) } return(retstr); } + +HASH_ARRAY_STRING(basilisk,balances,hash,vals,hexstr) +{ + char *retstr=0,*symbol; uint32_t basilisktag; struct basilisk_item *ptr,Lptr; int32_t timeoutmillis; + if ( vals == 0 ) + return(clonestr("{\"error\":\"need vals object\"}")); + if ( coin == 0 ) + { + if ( (symbol= jstr(vals,"symbol")) != 0 || (symbol= jstr(vals,"coin")) != 0 ) + coin = iguana_coinfind(symbol); + } + if ( jobj(vals,"fanout") == 0 ) + jaddnum(vals,"fanout",8); + if ( jobj(vals,"numrequired") == 0 ) + jaddnum(vals,"numrequired",myinfo->numrelays); + //printf("vals.(%s)\n",jprint(vals,0)); + if ( coin != 0 ) + { + if ( jobj(vals,"addresses") == 0 ) + jadd(vals,"addresses",iguana_getaddressesbyaccount(myinfo,coin,"*")); + if ( (basilisktag= juint(vals,"basilisktag")) == 0 ) + basilisktag = rand(); + if ( (timeoutmillis= juint(vals,"timeout")) <= 0 ) + timeoutmillis = BASILISK_TIMEOUT; + if ( (coin->RELAYNODE != 0 || coin->VALIDATENODE != 0) && (ptr= basilisk_bitcoinbalances(&Lptr,myinfo,coin,remoteaddr,basilisktag,timeoutmillis,vals)) != 0 ) + { + retstr = ptr->retstr, ptr->retstr = 0; + ptr->finished = (uint32_t)time(NULL); + return(retstr); + } + } + return(basilisk_standardservice("BAL",myinfo,0,hash,vals,hexstr,1)); +} + +HASH_ARRAY_STRING(basilisk,history,hash,vals,hexstr) +{ + struct basilisk_unspent *bu; int32_t i; int64_t total = 0; struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr,*tmp2; char coinaddr[64],*symbol; cJSON *retjson,*array,*item,*details; + if ( vals == 0 ) + return(clonestr("{\"error\":\"need vals object\"}")); + if ( coin == 0 ) + { + if ( (symbol= jstr(vals,"symbol")) != 0 || (symbol= jstr(vals,"coin")) != 0 ) + coin = iguana_coinfind(symbol); + } + array = cJSON_CreateArray(); + portable_mutex_lock(&myinfo->bu_mutex); + HASH_ITER(hh,myinfo->wallet,wacct,tmp) + { + HASH_ITER(hh,wacct->waddr,waddr,tmp2) + { + for (i=0; inumunspents; i++) + { + bu = &waddr->unspents[i]; + if ( strcmp(bu->symbol,coin->symbol) == 0 ) + { + bitcoin_address(coinaddr,coin->chain->pubtype,waddr->rmd160,sizeof(waddr->rmd160)); + item = cJSON_CreateObject(); + jaddstr(item,"address",coinaddr); + jaddnum(item,"amount",dstr(bu->value)); + jaddnum(item,"numseconds",time(NULL) - bu->timestamp); + details = cJSON_CreateObject(); + jaddbits256(details,"txid",bu->txid); + jaddnum(details,"vout",bu->vout); + jaddnum(details,"height",bu->height); + if ( bu->spentheight != 0 ) + jaddnum(details,"spentheight",bu->spentheight); + else total += bu->value; + jaddnum(details,"relays",bitweight(bu->relaymask)); + jadd(item,"details",details); + jaddi(array,item); + } + } + //printf("%s numunspents.%d\n",waddr->coinaddr,waddr->numunspents); + } + } + portable_mutex_unlock(&myinfo->bu_mutex); + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","success"); + jadd(retjson,"history",array); + jaddstr(retjson,"coin",coin->symbol); + jaddnum(retjson,"balance",dstr(total)); + return(jprint(retjson,1)); +} #include "../includes/iguana_apiundefs.h" + +int32_t basilisk_unspentfind(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *txidp,int32_t *voutp,uint8_t *spendscript,int16_t hdrsi,uint32_t unspentind,int64_t value) +{ + struct basilisk_unspent *bu; int32_t i,spendlen; struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr,*tmp2; + memset(txidp,0,sizeof(*txidp)); + *voutp = -1; + portable_mutex_lock(&myinfo->bu_mutex); + HASH_ITER(hh,myinfo->wallet,wacct,tmp) + { + HASH_ITER(hh,wacct->waddr,waddr,tmp2) + { + for (i=0; inumunspents; i++) + { + bu = &waddr->unspents[i]; + if ( bu->hdrsi == hdrsi && bu->unspentind == unspentind && bu->value == value ) + { + *txidp = bu->txid; + *voutp = bu->vout; + memcpy(spendscript,bu->script,bu->spendlen); + spendlen = bu->spendlen; + portable_mutex_unlock(&myinfo->bu_mutex); + return(spendlen); + } + } + } + } + portable_mutex_unlock(&myinfo->bu_mutex); + return(-1); +} + +void basilisk_unspent_update(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *item,int32_t spentheight,int32_t relayid,int32_t RTheight) +{ + //{"txid":"4814dc8a357f93f16271eb43806a69416ec41ab1956b128d170402b0a1b37c7f","vout":2,"address":"RSyKVKNxrSDc1Vwvh4guYb9ZDEpvMFz2rm","scriptPubKey":"76a914c210f6711e98fe9971757ede2b2dcb0507f3f25e88ac","amount":9.99920000,"timestamp":1466684518,"height":1160306,"confirmations":22528,"checkind":1157,"spent":{"hdrsi":2320,"pkind":168,"unspentind":1157,"prevunspentind":0,"satoshis":"999920000","txidind":619,"vout":2,"type":2,"fileid":0,"scriptpos":0,"scriptlen":25},"spentheight":1161800,"dest":{"error":"couldnt find spent info"}} + int32_t i,n,already_spent=0; struct basilisk_unspent bu,bu2; char *address,*script; struct iguana_waccount *wacct; struct iguana_waddress *waddr; + if ( (address= jstr(item,"address")) != 0 && (script= jstr(item,"scriptPubKey")) != 0 && (waddr= iguana_waddresssearch(myinfo,&wacct,address)) != 0 ) + { + if ( relayid >= 64 ) + relayid = 0; + memset(&bu,0,sizeof(bu)); + bu.spendlen = (int32_t)strlen(script) >> 1; + if ( bu.spendlen > sizeof(bu.script) ) + { + printf("spendscript too big.%d\n",bu.spendlen); + return; + } + strcpy(bu.symbol,coin->symbol); + bu.txid = jbits256(item,"txid"); + bu.vout = jint(item,"vout"); + bu.value = jdouble(item,"amount") * SATOSHIDEN; + bu.height = jint(item,"height"); + bu.hdrsi = (bu.height / coin->chain->bundlesize); + bu.unspentind = juint(item,"checkind"); + bu.timestamp = juint(item,"timestamp"); + decode_hex(bu.script,bu.spendlen,script); + n = waddr->numunspents; + for (i=0; iunspents[i]; + bu2.status = 0; + bu2.RTheight = bu2.spentheight = 0; + bu2.relaymask = 0; + if ( memcmp(&bu,&bu2,sizeof(bu)) == 0 ) + { + if ( waddr->unspents[i].RTheight > RTheight ) + RTheight = waddr->unspents[i].RTheight; + already_spent = waddr->unspents[i].spentheight; + bu.relaymask = waddr->unspents[i].relaymask; + break; + } + } + bu.RTheight = RTheight; + bu.relaymask |= ((uint64_t)1 << relayid); + //printf("relayid.%d -> %llx wt.%d\n",relayid,(long long)bu.relaymask,bitweight(bu.relaymask)); + if ( spentheight != 0 ) + already_spent = spentheight; + if ( (bu.spentheight= already_spent) != 0 ) + bu.status = 1; + if ( i == n ) + { + if ( i >= waddr->maxunspents ) + { + waddr->maxunspents += 16; + waddr->unspents = realloc(waddr->unspents,sizeof(*waddr->unspents) * waddr->maxunspents); + printf("allocate max.%d for %s\n",waddr->maxunspents,waddr->coinaddr); + } + waddr->numunspents++; + printf("new unspent.%s %d script.%p [%d]\n",waddr->coinaddr,waddr->numunspents,bu.script,bu.spendlen); + } + waddr->unspents[i] = bu; + } +} + +void basilisk_unspents_update(struct supernet_info *myinfo,struct iguana_info *coin) +{ + char *retstr; cJSON *retarray,*vals,*relayjson,*unspents,*spends; int32_t oldest,i,j,n,num,RTheight,relayid; + if ( coin->RELAYNODE == 0 && coin->VALIDATENODE == 0 ) + { + vals = cJSON_CreateObject(); + for (i=oldest=0; irelay_RTheights[i]) != 0 && (oldest == 0 || RTheight < oldest) ) + oldest = RTheight; + jaddnum(vals,"firstheight",oldest); + jaddnum(vals,"history",3); + if ( (retstr= basilisk_balances(myinfo,coin,0,0,GENESIS_PUBKEY,vals,"")) != 0 ) + { + //printf("GOT.(%s)\n",retstr); + portable_mutex_lock(&myinfo->bu_mutex); + if ( (retarray= cJSON_Parse(retstr)) != 0 && (n= cJSON_GetArraySize(retarray)) > 0 ) + { + if ( jobj(retarray,"error") == 0 ) + { + for (i=0; irelay_RTheights[relayid] = RTheight; + } + //printf("relayid.%d RT.%d\n",relayid,RTheight); + if ( (unspents= jarray(&num,relayjson,"unspents")) != 0 ) + { + for (j=0; jbu_mutex); + } + free_json(vals); + } +} diff --git a/iguana/iguana777.h b/iguana/iguana777.h index d9d12d122..ef1d64897 100755 --- a/iguana/iguana777.h +++ b/iguana/iguana777.h @@ -52,7 +52,7 @@ struct supernet_info struct exchange_info *tradingexchanges[SUPERNET_MAXEXCHANGES]; int32_t numexchanges; struct iguana_waccount *wallet; struct iguana_info *allcoins; int32_t allcoins_being_added,allcoins_numvirts; - portable_mutex_t allcoins_mutex,gecko_mutex,basilisk_mutex,DEX_mutex,DEX_reqmutex,DEX_swapmutex; + portable_mutex_t bu_mutex,allcoins_mutex,gecko_mutex,basilisk_mutex,DEX_mutex,DEX_reqmutex,DEX_swapmutex; struct queueitem *DEX_quotes; struct basilisk_swap *swaps[256]; int32_t numswaps; struct basilisk_message *messagetable; portable_mutex_t messagemutex; queue_t msgQ; diff --git a/iguana/iguana_payments.c b/iguana/iguana_payments.c index d55f4957c..05d9c5471 100755 --- a/iguana/iguana_payments.c +++ b/iguana/iguana_payments.c @@ -200,9 +200,21 @@ int32_t iguana_bestunspent(struct iguana_info *coin,int32_t *aboveip,int64_t *ab return(abovei >= 0 ? abovei : belowi); } +cJSON *iguana_inputjson(bits256 txid,int32_t vout,uint8_t *spendscript,int32_t spendlen) +{ + char hexstr[IGUANA_MAXSCRIPTSIZE*2 + 1]; cJSON *sobj,*item = cJSON_CreateObject(); + jaddbits256(item,"txid",txid); + jaddnum(item,"vout",vout); + sobj = cJSON_CreateObject(); + init_hexbytes_noT(hexstr,spendscript,spendlen); + jaddstr(sobj,"hex",hexstr); + jadd(item,"scriptPubKey",sobj); + return(item); +} + cJSON *iguana_inputsjson(struct supernet_info *myinfo,struct iguana_info *coin,int64_t *totalp,uint64_t amount,int64_t *unspents,int32_t num) { - cJSON *item,*vins,*sobj; 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],hexstr[IGUANA_MAXSCRIPTSIZE*2+1]; int32_t height,abovei,belowi,i,spendlen,ind,hdrsi; uint32_t txidind,unspentind; struct iguana_ramchaindata *rdata; int64_t value,above,below,total = 0; int64_t remains = amount; + 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,hdrsi; uint32_t txidind,unspentind; struct iguana_ramchaindata *rdata; bits256 txid; int64_t value,above,below,total = 0; int64_t remains = amount; *totalp = 0; vins = cJSON_CreateArray(); for (i=0; iRELAYNODE == 0 && coin->VALIDATENODE == 0 ) + { + if ( (spendlen= basilisk_unspentfind(myinfo,coin,&txid,&vout,spendscript,hdrsi,unspentind,value)) > 0 ) + { + jaddi(vins,iguana_inputjson(txid,vout,spendscript,spendlen)); + total += value; + remains -= value; + //printf("%s value %.8f -> remains %.8f\n",coinaddr,dstr(value),dstr(remains)); + if ( remains <= 0 ) + break; + } + continue; + } if ( (bp= coin->bundles[hdrsi]) == 0 ) { printf("no bundle.[%d]\n",hdrsi); @@ -239,14 +264,7 @@ cJSON *iguana_inputsjson(struct supernet_info *myinfo,struct iguana_info *coin,i { if ( iguana_unspentindfind(coin,coinaddr,spendscript,&spendlen,&amount,&height,T[txidind].txid,u->vout,coin->bundlescount-1,0) == unspentind && spendlen > 0 ) { - item = cJSON_CreateObject(); - jaddbits256(item,"txid",T[txidind].txid); - jaddnum(item,"vout",u->vout); - sobj = cJSON_CreateObject(); - init_hexbytes_noT(hexstr,spendscript,spendlen); - jaddstr(sobj,"hex",hexstr); - jadd(item,"scriptPubKey",sobj); - jaddi(vins,item); + jaddi(vins,iguana_inputjson(T[txidind].txid,u->vout,spendscript,spendlen)); total += value; remains -= value; //printf("%s value %.8f -> remains %.8f\n",coinaddr,dstr(value),dstr(remains)); diff --git a/iguana/iguana_unspents.c b/iguana/iguana_unspents.c index 33f6b587c..d6c718d52 100755 --- a/iguana/iguana_unspents.c +++ b/iguana/iguana_unspents.c @@ -506,7 +506,7 @@ uint8_t *iguana_rmdarray(struct supernet_info *myinfo,struct iguana_info *coin,i int32_t iguana_unspentslists(struct supernet_info *myinfo,struct iguana_info *coin,int64_t *totalp,int64_t *unspents,int32_t max,int64_t required,int32_t minconf,cJSON *addresses,char *remoteaddr) { - int64_t remains,total,sum = 0; int32_t i,n,numunspents,numaddrs; uint8_t addrtype,pubkey[65],rmd160[20]; char *coinaddr; + int64_t total,sum = 0; int32_t i,n,numunspents,numaddrs; uint8_t addrtype,pubkey[65],rmd160[20]; char *coinaddr; struct iguana_waddress *waddr; struct iguana_waccount *wacct; struct basilisk_unspent *bu; *totalp = 0; if ( (numaddrs= cJSON_GetArraySize(addresses)) == 0 ) { @@ -514,7 +514,7 @@ int32_t iguana_unspentslists(struct supernet_info *myinfo,struct iguana_info *co return(0); } memset(pubkey,0,sizeof(pubkey)); - remains = required * 1.1 + coin->txfee; + //remains = required * 1.1 + coin->txfee; for (i=numunspents=0; ilongestchain,coin->blocks.hwmchain.height - minconf); total = 0; n = 0; - bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr); - iguana_pkhasharray(myinfo,coin,0,minconf,coin->longestchain,&total,0,coin->bundlescount,rmd160,coinaddr,pubkey,coin->blocks.hwmchain.height - minconf,unspents,&n,max-1000,remoteaddr); - //printf("n.%d max.%d total %.8f\n",n,max,dstr(total)); - if ( n > 0 ) + if ( coin->RELAYNODE != 0 || coin->VALIDATENODE != 0 ) { - sum += total; - unspents += (n << 1); - numunspents += n; - if ( numunspents > max ) - break; + bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr); + iguana_pkhasharray(myinfo,coin,0,minconf,coin->longestchain,&total,0,coin->bundlescount,rmd160,coinaddr,pubkey,coin->blocks.hwmchain.height - minconf,unspents,&n,max-1000,remoteaddr); + if ( n > 0 ) + { + sum += total; + unspents += (n << 1); + numunspents += n; + } + } + else + { + if ( (waddr= iguana_waddresssearch(myinfo,&wacct,coinaddr)) != 0 ) + { + for (i=0; inumunspents; i++) + { + bu = &waddr->unspents[i]; + if ( bu->status == 0 ) + { + unspents[0] = ((uint64_t)bu->hdrsi << 32) | bu->unspentind; + unspents[1] = bu->value; + sum += bu->value; + unspents++; + numunspents++; + } + } + } } + if ( numunspents > max ) + break; + //printf("n.%d max.%d total %.8f\n",n,max,dstr(total)); } } *totalp = sum; diff --git a/iguana/iguana_wallet.c b/iguana/iguana_wallet.c index 21783dead..aacc3467a 100755 --- a/iguana/iguana_wallet.c +++ b/iguana/iguana_wallet.c @@ -687,9 +687,10 @@ uint8_t iguana_waddrvalidate(struct supernet_info *myinfo,struct iguana_info *co cJSON *iguana_walletiterate(struct supernet_info *myinfo,struct iguana_info *coin,int32_t flag,cJSON *array,int32_t *goodp,int32_t *badp,int32_t *errors) { - struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr=0,*tmp2; uint8_t errorflags; int32_t i,good=0,bad=0,_errors[8]; cJSON *item; char coinaddr[64]; + struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr=0,*tmp2; uint8_t errorflags; int32_t i,good=0,bad=0,_errors[8]; cJSON *item; char coinaddr[64]; if ( errors == 0 ) errors = _errors; + portable_mutex_lock(&myinfo->bu_mutex); HASH_ITER(hh,myinfo->wallet,wacct,tmp) { HASH_ITER(hh,wacct->waddr,waddr,tmp2) @@ -732,6 +733,7 @@ cJSON *iguana_walletiterate(struct supernet_info *myinfo,struct iguana_info *coi myfree(wacct,sizeof(*wacct)); } } + portable_mutex_unlock(&myinfo->bu_mutex); if ( goodp != 0 ) *goodp = good; if ( badp != 0 ) diff --git a/iguana/tests/history b/iguana/tests/history index 410c32ece..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\":\"balances\",\"vals\":{\"minconf\":1,\"history\":3}}" +curl --url "http://127.0.0.1:7778" --data "{\"timeout\":20000,\"agent\":\"basilisk\",\"method\":\"history\",\"vals\":{\"coin\":\"BTCD\"}}" diff --git a/includes/iguana_apideclares.h b/includes/iguana_apideclares.h index f59e2e532..b1575aed9 100755 --- a/includes/iguana_apideclares.h +++ b/includes/iguana_apideclares.h @@ -24,6 +24,7 @@ TWO_INTS(InstantDEX,accept,requestid,quoteid); TWO_INTS(InstantDEX,swapstatus,requestid,quoteid); HASH_ARRAY_STRING(basilisk,genesis_opreturn,hash,vals,hexstr); +HASH_ARRAY_STRING(basilisk,history,hash,vals,hexstr); HASH_ARRAY_STRING(basilisk,balances,hash,vals,hexstr); HASH_ARRAY_STRING(basilisk,value,hash,vals,hexstr); diff --git a/includes/iguana_funcs.h b/includes/iguana_funcs.h index 629374d00..d02ef1ddf 100755 --- a/includes/iguana_funcs.h +++ b/includes/iguana_funcs.h @@ -413,10 +413,12 @@ int32_t iguana_voutscript(struct iguana_info *coin,struct iguana_bundle *bp,uint cJSON *iguana_unspentjson(struct supernet_info *myinfo,struct iguana_info *coin,int32_t hdrsi,uint32_t unspentind,struct iguana_txid *T,struct iguana_unspent *up,uint8_t rmd160[20],char *coinaddr,uint8_t *pubkey33,int32_t spentheight,char *remoteaddr); int32_t bitcoin_standardspend(uint8_t *script,int32_t n,uint8_t rmd160[20]); struct iguana_waddress *iguana_waddresssearch(struct supernet_info *myinfo,struct iguana_waccount **wacctp,char *coinaddr); +int32_t basilisk_unspentfind(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *txidp,int32_t *voutp,uint8_t *spendscript,int16_t hdrsi,uint32_t unspentind,int64_t value); int64_t iguana_addressreceived(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *json,char *remoteaddr,cJSON *txids,cJSON *vouts,cJSON *unspents,cJSON *spends,char *coinaddr,int32_t minconf,int32_t firstheight); cJSON *iguana_walletjson(struct supernet_info *myinfo); int32_t iguana_payloadupdate(struct supernet_info *myinfo,struct iguana_info *coin,char *retstr,struct iguana_waddress *waddr,char *account); int32_t bitcoin_MofNspendscript(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,const struct vin_info *vp); +void basilisk_unspents_update(struct supernet_info *myinfo,struct iguana_info *coin); struct iguana_txid *iguana_blocktx(struct iguana_info *coin,struct iguana_txid *tx,struct iguana_block *block,int32_t i); cJSON *iguana_p2shjson(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *retjson,struct iguana_waddress *waddr); char *setaccount(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waddress **waddrp,char *account,char *coinaddr,char *redeemScript); diff --git a/includes/iguana_structs.h b/includes/iguana_structs.h index f7218309c..d250caef5 100755 --- a/includes/iguana_structs.h +++ b/includes/iguana_structs.h @@ -364,7 +364,9 @@ struct iguana_bundlereq struct iguana_bitmap { int32_t width,height,amplitude; char name[52]; uint8_t data[IGUANA_WIDTH*IGUANA_HEIGHT*3]; }; -struct iguana_waddress { UT_hash_handle hh; uint64_t balance,*unspents; uint32_t maxunspents,numunspents; uint16_t scriptlen; uint8_t rmd160[20],pubkey[33],wiftype,addrtype; bits256 privkey; char symbol[8],coinaddr[36],wifstr[54]; uint8_t redeemScript[]; }; +struct basilisk_unspent { bits256 txid; uint64_t value,relaymask; uint32_t unspentind,timestamp; int32_t RTheight,height,spentheight; int16_t status,hdrsi,vout,spendlen; char symbol[16]; uint8_t script[256]; }; + +struct iguana_waddress { UT_hash_handle hh; struct basilisk_unspent *unspents; uint64_t balance; uint32_t maxunspents,numunspents; uint16_t scriptlen; uint8_t rmd160[20],pubkey[33],wiftype,addrtype; bits256 privkey; char symbol[8],coinaddr[36],wifstr[54]; uint8_t redeemScript[]; }; struct iguana_waccount { UT_hash_handle hh; char account[128]; struct iguana_waddress *waddr,*current; }; struct iguana_wallet { UT_hash_handle hh; struct iguana_waccount *wacct; }; @@ -413,6 +415,7 @@ struct iguana_info struct iguana_monitorinfo monitoring[256]; struct datachain_info dPoW; struct iguana_zblock newblock; char *newblockstr; + int32_t relay_RTheights[BASILISK_MAXRELAYS]; struct iguana_blocks blocks; void *mempool; void *mempools[BASILISK_MAXRELAYS]; };