Browse Source

new history

release/v0.1
jl777 8 years ago
parent
commit
cf67a62391
  1. 38
      basilisk/basilisk.c
  2. 264
      basilisk/basilisk_bitcoin.c
  3. 4
      basilisk/basilisk_swap.c
  4. 8
      iguana/iguana_payments.c
  5. 43
      iguana/iguana_realtime.c
  6. 4
      iguana/iguana_spendvectors.c
  7. 88
      iguana/iguana_unspents.c
  8. 18
      iguana/iguana_wallet.c
  9. 15
      iguana/ramchain_api.c
  10. 1
      iguana/tests/balance
  11. 9
      includes/iguana_funcs.h
  12. 2
      includes/iguana_structs.h

38
basilisk/basilisk.c

@ -882,6 +882,7 @@ void basilisks_init(struct supernet_info *myinfo)
#include "../includes/iguana_apidefs.h" #include "../includes/iguana_apidefs.h"
#include "../includes/iguana_apideclares.h" #include "../includes/iguana_apideclares.h"
HASH_ARRAY_STRING(basilisk,balances,hash,vals,hexstr) HASH_ARRAY_STRING(basilisk,balances,hash,vals,hexstr)
{ {
char *retstr=0,*symbol; uint32_t basilisktag; struct basilisk_item *ptr,Lptr; int32_t timeoutmillis; char *retstr=0,*symbol; uint32_t basilisktag; struct basilisk_item *ptr,Lptr; int32_t timeoutmillis;
@ -922,7 +923,7 @@ HASH_ARRAY_STRING(basilisk,balances,hash,vals,hexstr)
HASH_ARRAY_STRING(basilisk,history,hash,vals,hexstr) HASH_ARRAY_STRING(basilisk,history,hash,vals,hexstr)
{ {
struct basilisk_unspent *bu; int32_t i; int64_t totalspent=0,total = 0; struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr,*tmp2; char *symbol; cJSON *retjson,*array; struct basilisk_spend *s; int64_t total = 0; int32_t i,n; struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr,*tmp2; char *symbol; cJSON *retjson,*unspents,*spends,*array; //struct basilisk_spend *s; struct basilisk_unspent *bu; int32_t i;
if ( vals == 0 ) if ( vals == 0 )
return(clonestr("{\"error\":\"need vals object\"}")); return(clonestr("{\"error\":\"need vals object\"}"));
//if ( coin == 0 ) //if ( coin == 0 )
@ -932,41 +933,30 @@ HASH_ARRAY_STRING(basilisk,history,hash,vals,hexstr)
} }
if ( coin == 0 ) if ( coin == 0 )
return(clonestr("{\"error\":\"couldnt find coin\"}")); return(clonestr("{\"error\":\"couldnt find coin\"}"));
//printf("history for (%s)\n",coin->symbol); unspents = cJSON_CreateArray();
basilisk_unspents_update(myinfo,coin); spends = cJSON_CreateArray();
array = cJSON_CreateArray();
portable_mutex_lock(&myinfo->bu_mutex);
HASH_ITER(hh,myinfo->wallet,wacct,tmp) HASH_ITER(hh,myinfo->wallet,wacct,tmp)
{ {
HASH_ITER(hh,wacct->waddr,waddr,tmp2) HASH_ITER(hh,wacct->waddr,waddr,tmp2)
{ {
for (i=0; i<waddr->numunspents; i++) if ( (array= waddr->unspents) != 0 )
{ {
bu = &waddr->unspents[i]; if ( (n= cJSON_GetArraySize(array)) > 0 )
if ( strcmp(bu->symbol,coin->symbol) == 0 )
{ {
bitcoin_address(waddr->coinaddr,coin->chain->pubtype,waddr->rmd160,sizeof(waddr->rmd160)); for (i=0; i<n; i++)
jaddi(array,basilisk_history_item(coin,&total,waddr->coinaddr,bu->value,bu->timestamp,bu->txid,"vout",bu->vout,bu->height,"spentheight",bu->spentheight,bu->relaymask,-1)); total += jdouble(jitem(array,i),"amount") * SATOSHIDEN;
//printf("%s %s i.%d numunspents.%d\n",coin->symbol,waddr->coinaddr,i,waddr->numunspents);
} }
jaddi(unspents,jduplicate(waddr->unspents));
//jaddi(array,basilisk_history_item(coin,&total,waddr->coinaddr,bu->value,bu->timestamp,bu->txid,"vout",bu->vout,bu->height,"spentheight",bu->spentheight,bu->relaymask,-1));
} }
if ( waddr->spends != 0 )
jaddi(spends,jduplicate(waddr->spends));
} }
} }
if ( myinfo->numspends > 0 )
{
//spends = cJSON_CreateArray();
for (i=0; i<myinfo->numspends; i++)
{
s = &myinfo->spends[i];
//struct basilisk_spend { bits256 txid; uint64_t relaymask,value; uint32_t timestamp; int32_t vini,height,unspentheight,ismine; char destaddr[64]; };
if ( strcmp(s->symbol,coin->symbol) == 0 )
jaddi(array,basilisk_history_item(coin,&totalspent,s->destaddr,s->value,s->timestamp,s->txid,"vin",s->vini,s->height,"unspentheight",s->unspentheight,s->relaymask,s->ismine));
}
}
portable_mutex_unlock(&myinfo->bu_mutex);
retjson = cJSON_CreateObject(); retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success"); jaddstr(retjson,"result","success");
jadd(retjson,"history",array); jadd(retjson,"unspents",unspents);
jadd(retjson,"spends",spends);
jaddstr(retjson,"coin",coin->symbol); jaddstr(retjson,"coin",coin->symbol);
jaddnum(retjson,"balance",dstr(total)); jaddnum(retjson,"balance",dstr(total));
return(jprint(retjson,1)); return(jprint(retjson,1));

264
basilisk/basilisk_bitcoin.c

@ -313,11 +313,10 @@ void *basilisk_bitcoinbalances(struct basilisk_item *Lptr,struct supernet_info *
{ {
for (i=0; i<n; i++) for (i=0; i<n; i++)
{ {
//if ( coin->RTheight > 0 ) balance = iguana_addressreceived(myinfo,coin,vals,remoteaddr,0,0,unspents,spends,jstri(addresses,i),juint(vals,"minconf"),juint(vals,"firstheight"));
balance = iguana_addressreceived(myinfo,coin,vals,remoteaddr,0,0,unspents,spends,jstri(addresses,i),juint(vals,"minconf"),juint(vals,"firstheight"));
//else balance = 0;
item = cJSON_CreateObject(); item = cJSON_CreateObject();
jaddnum(item,jstri(addresses,i),dstr(balance)); jaddnum(item,jstri(addresses,i),dstr(balance));
jaddstr(item,"address",jstri(addresses,i));
jaddi(array,item); jaddi(array,item);
total += balance; total += balance;
//printf("%.8f ",dstr(balance)); //printf("%.8f ",dstr(balance));
@ -861,41 +860,11 @@ HASH_ARRAY_STRING(basilisk,rawtx,hash,vals,hexstr)
return(retstr); return(retstr);
} }
cJSON *basilisk_history_item(struct iguana_info *coin,int64_t *totalp,char *coinaddr,int64_t value,uint32_t timestamp,bits256 txid,char *vinvoutstr,int32_t vinvout,int32_t height,char *otherheightstr,int32_t otherheight,uint64_t relaymask,int32_t ismine)
{
cJSON *item,*details;
item = cJSON_CreateObject();
jaddstr(item,"address",coinaddr);
jaddnum(item,"amount",dstr(value));
if ( timestamp > 0 )
jaddnum(item,"numseconds",time(NULL) - timestamp);
details = cJSON_CreateObject();
if ( ismine > 0 )
{
jaddnum(details,"ismine",ismine);
if ( strcmp(vinvoutstr,"spentheight") == 0 )
jaddstr(details,"category","sent");
else jaddstr(details,"category","received");
}
jaddbits256(details,"txid",txid);
jaddnum(details,vinvoutstr,vinvout);
jaddnum(details,"height",height);
if ( coin->blocks.hwmchain.height > 0 )
jaddnum(details,"confirms",coin->blocks.hwmchain.height - height);
jaddnum(details,"height",height);
if ( otherheight != 0 )
jaddnum(details,otherheightstr,otherheight);
else *totalp += value;
jaddnum(details,"relays",bitweight(relaymask));
jadd(item,"details",details);
return(item);
}
#include "../includes/iguana_apiundefs.h" #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,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)
{ {
struct basilisk_unspent *bu; int32_t i,spendlen; struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr,*tmp2; char str[65]; struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr,*tmp2;
memset(txidp,0,sizeof(*txidp)); memset(txidp,0,sizeof(*txidp));
*voutp = -1; *voutp = -1;
portable_mutex_lock(&myinfo->bu_mutex); portable_mutex_lock(&myinfo->bu_mutex);
@ -903,221 +872,60 @@ int32_t basilisk_unspentfind(struct supernet_info *myinfo,struct iguana_info *co
{ {
HASH_ITER(hh,wacct->waddr,waddr,tmp2) HASH_ITER(hh,wacct->waddr,waddr,tmp2)
{ {
for (i=0; i<waddr->numunspents; i++) printf("need to port basilisk_unspentfind\n");
{
bu = &waddr->unspents[i];
if ( bu->hdrsi == outpt.hdrsi && bu->unspentind == outpt.unspentind && bu->value == value )
{
if ( bu->status == 0 )
{
*txidp = bu->txid;
*voutp = bu->vout;
memcpy(spendscript,bu->script,bu->spendlen);
spendlen = bu->spendlen;
portable_mutex_unlock(&myinfo->bu_mutex);
return(spendlen);
} else printf("unspentfind skip %s/v%d\n",bits256_str(str,bu->txid),bu->vout);
}
}
} }
} }
portable_mutex_unlock(&myinfo->bu_mutex); portable_mutex_unlock(&myinfo->bu_mutex);
return(-1); return(-1);
} }
struct basilisk_spend *basilisk_addspend(struct supernet_info *myinfo,char *symbol,bits256 txid,uint16_t vout,int32_t addflag) void basilisk_unspent_update(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *json)
{ {
int32_t i=0; struct basilisk_spend *s; cJSON *unspents,*spends,*item; int32_t n; char *address; struct iguana_waccount *wacct; struct iguana_waddress *waddr=0;
// mutex if ( (spends= jarray(&n,json,"spends")) != 0 )
if ( myinfo->numspends > 0 )
{ {
for (i=0; i<myinfo->numspends; i++) item = jitem(spends,0);
if ( (address= jstr(item,"address")) != 0 && (waddr= iguana_waddresssearch(myinfo,&wacct,address)) != 0 )
{ {
if ( myinfo->spends[i].vout == vout && bits256_cmp(txid,myinfo->spends[i].txid) == 0 ) if ( waddr->spends != 0 ) // maybe better to merge and error check if basilisk
{ free_json(waddr->spends);
char str[65]; printf("found spend.%s v%d skip it\n",bits256_str(str,txid),vout); waddr->spends = jduplicate(spends);
return(&myinfo->spends[i]);
}
} }
} }
if ( addflag != 0 && i == myinfo->numspends ) if ( (unspents= jarray(&n,json,"unspents")) != 0 )
{ {
//printf("realloc spends.[%d] %p\n",myinfo->numspends,myinfo->spends); item = jitem(unspents,0);
myinfo->spends = realloc(myinfo->spends,sizeof(*myinfo->spends) * (myinfo->numspends+1)); if ( (address= jstr(item,"address")) != 0 && (waddr= iguana_waddresssearch(myinfo,&wacct,address)) != 0 )
//printf("allocated spends.[%d] %p\n",myinfo->numspends+1,myinfo->spends);
s = &myinfo->spends[myinfo->numspends++];
memset(s,0,sizeof(*s));
s->txid = txid;
s->vout = vout;
strcpy(s->symbol,symbol);
//char str[65]; printf("ADDSPEND.%s %s/v%d\n",symbol,bits256_str(str,txid),vout);
// mutex
return(s);
}
// mutex
return(0);
}
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,j,m,already_spent=0; struct basilisk_unspent bu,bu2; char *address,*script=0,*destaddr; struct iguana_waccount *wacct; struct iguana_waddress *waddr=0; cJSON *dest,*vouts,*vitem; double ratio;
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); if ( waddr->unspents != 0 ) // maybe better to merge and error check if basilisk
return; free_json(waddr->unspents);
waddr->unspents = jduplicate(unspents);
} }
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);
//printf("unspentupdate.(%s)\n",jprint(item,0));
n = waddr->numunspents;
for (i=0; i<n; i++)
{
bu2 = waddr->unspents[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;
if ( (bu.status= waddr->unspents[i].status) != 0 )
{
//printf("mempool spend for %s/%d\n",bits256_str(str,bu.txid),bu.vout);
}
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 %s unspent.%s %d script.%p [%d] (%s)\n",coin->symbol,waddr->coinaddr,waddr->numunspents,bu.script,bu.spendlen,jprint(item,0));
if ( bu.spentheight != 0 && (dest= jobj(item,"dest")) != 0 )
{
struct basilisk_spend *s;
//{"txid":"cd4fb72f871d481c534f15d7f639883958936d49e965f58276f0925798e762df","vin":1,"height":<spentheight>,"unspentheight":<bu.height>,"relays":2}},
if ( (s= basilisk_addspend(myinfo,coin->symbol,bu.txid,bu.vout,1)) != 0 )
{
s->spentfrom = jbits256(dest,"spentfrom");
s->vini = jint(dest,"vin");
s->height = bu.spentheight;
s->timestamp = juint(dest,"timestamp");
s->unspentheight = bu.height;
s->relaymask = bu.relaymask;
ratio = jdouble(dest,"ratio");
if ( (vouts= jobj(dest,"vouts")) != 0 && (m= cJSON_GetArraySize(vouts)) > 0 )
{
for (j=0; j<m; j++)
{
vitem = jitem(vouts,j);
if ( (destaddr= jfieldname(vitem)) != 0 )
{
safecopy(s->destaddr,destaddr,sizeof(s->destaddr));
s->ismine = (iguana_waddresssearch(myinfo,&wacct,destaddr) != 0);
s->value = jdouble(vitem,jfieldname(vitem)) * SATOSHIDEN;
//printf("(%s %.8f) ",s->destaddr,dstr(s->value));
}
}
char str[65]; printf("SPEND dest.(%s) ratio %.8f (%s/v%d)\n",jprint(dest,0),ratio,bits256_str(str,s->txid),s->vini);
}
}
}
waddr->unspents[i] = bu;
}
} else printf("waddr.%p script.%p address.%p %s\n",waddr,script,address,address!=0?address:"");
}
void basilisk_relay_unspentsprocess(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *relayjson)
{
int32_t RTheight,relayid,num,j; cJSON *unspents,*spends;
RTheight = jint(relayjson,"RTheight");
if ( (relayid= basilisk_relayid(myinfo,(uint32_t)calc_ipbits(jstr(relayjson,"relay")))) < BASILISK_MAXRELAYS )
{
coin->relay_RTheights[relayid] = RTheight;
}
//printf("basilisk_relay_unspentsprocess relayid.%d RT.%d (%s)\n",relayid,RTheight,jprint(relayjson,0));
if ( (unspents= jarray(&num,relayjson,"unspents")) != 0 )
{
for (j=0; j<num; j++)
basilisk_unspent_update(myinfo,coin,jitem(unspents,j),0,relayid,RTheight);
}
if ( (spends= jarray(&num,relayjson,"spends")) != 0 )
{
for (j=0; j<num; j++)
basilisk_unspent_update(myinfo,coin,jitem(spends,j),jint(jitem(spends,j),"spentheight"),relayid,RTheight);
} }
} }
void basilisk_unspents_update(struct supernet_info *myinfo,struct iguana_info *coin) void basilisk_unspents_update(struct supernet_info *myinfo,struct iguana_info *coin)
{ {
char *retstr; cJSON *retarray,*vals; int32_t oldest,i,n,RTheight; char *retstr; cJSON *vals; int32_t oldest,i,RTheight; cJSON *retarray;
//if ( coin->FULLNODE == 0 && coin->VALIDATENODE == 0 ) vals = cJSON_CreateObject();
{ for (i=oldest=0; i<BASILISK_MAXRELAYS; i++)
vals = cJSON_CreateObject(); if ( (RTheight= coin->relay_RTheights[i]) != 0 && (oldest == 0 || RTheight < oldest) )
for (i=oldest=0; i<BASILISK_MAXRELAYS; i++) oldest = RTheight;
if ( (RTheight= coin->relay_RTheights[i]) != 0 && (oldest == 0 || RTheight < oldest) ) jaddnum(vals,"firstheight",oldest);
oldest = RTheight; jaddnum(vals,"history",3);
jaddnum(vals,"firstheight",oldest); jaddstr(vals,"coin",coin->symbol);
jaddnum(vals,"history",3); if ( (retstr= basilisk_balances(myinfo,coin,0,0,GENESIS_PUBKEY,vals,"")) != 0 )
jaddstr(vals,"coin",coin->symbol); {
if ( (retstr= basilisk_balances(myinfo,coin,0,0,GENESIS_PUBKEY,vals,"")) != 0 ) if ( (retarray= cJSON_Parse(retstr)) != 0 )
{ {
portable_mutex_lock(&myinfo->bu_mutex); if ( is_cJSON_Array(retarray) != 0 )
if ( (retarray= cJSON_Parse(retstr)) != 0 )
{ {
//printf("%s UNSPENTS_UPDATE.(%s)\n",coin->symbol,retstr); for (i=0; i<cJSON_GetArraySize(retarray); i++)
if ( jobj(retarray,"error") == 0 ) basilisk_unspent_update(myinfo,coin,jitem(retarray,i));
{ } else basilisk_unspent_update(myinfo,coin,retarray);
if ( (jstr(retarray,"ipaddr") == 0 || strcmp(jstr(retarray,"ipaddr"),myinfo->ipaddr) != 0) && (n= cJSON_GetArraySize(retarray)) > 0 ) free_json(retarray);
{
for (i=0; i<n; i++)
basilisk_relay_unspentsprocess(myinfo,coin,jitem(retarray,i));
} else basilisk_relay_unspentsprocess(myinfo,coin,retarray);
if ( 0 )
{
bits256 pubAm,pubBn; struct basilisk_rawtx test; struct basilisk_swap swap;
memset(&swap,0,sizeof(swap));
printf("create alicepayment\n");
swap.alicecoin = iguana_coinfind("BTCD");
swap.alicesatoshis = 100000;
basilisk_rawtx_setparms("alicepayment",myinfo,&swap,&test,swap.alicecoin,swap.aliceconfirms,0,swap.alicesatoshis,2,0);
basilisk_alicepayment(myinfo,swap.alicecoin,&test,pubAm,pubBn);
}
}
} else printf("couldnt parse.(%s)\n",retstr);
if ( retarray != 0 )
free_json(retarray);
free(retstr);
portable_mutex_unlock(&myinfo->bu_mutex);
} }
free_json(vals); free(retstr);
} }
free_json(vals);
} }

4
basilisk/basilisk_swap.c

@ -576,11 +576,11 @@ int32_t basilisk_rawtx_return(struct supernet_info *myinfo,int32_t height,struct
item = jitem(vins,i); item = jitem(vins,i);
txid = jbits256(item,"txid"); txid = jbits256(item,"txid");
vout = jint(item,"vout"); vout = jint(item,"vout");
if ( bits256_nonz(txid) != 0 ) /*if ( bits256_nonz(txid) != 0 )
{ {
char str[65]; printf("call addspend.(%s) v.%d\n",bits256_str(str,txid),vout); char str[65]; printf("call addspend.(%s) v.%d\n",bits256_str(str,txid),vout);
basilisk_addspend(myinfo,rawtx->coin->symbol,txid,vout,1); basilisk_addspend(myinfo,rawtx->coin->symbol,txid,vout,1);
} }*/
} }
} }
} }

8
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 *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; struct iguana_outpoint outpt; 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; uint32_t txidind; struct iguana_ramchaindata *rdata; bits256 txid; int64_t above,below,total = 0,remains = amount; struct iguana_outpoint outpt; uint64_t RTspent;
*totalp = 0; *totalp = 0;
vins = cJSON_CreateArray(); vins = cJSON_CreateArray();
for (i=0; i<num; i++) for (i=0; i<num; i++)
@ -274,7 +274,7 @@ cJSON *iguana_RTinputsjson(struct supernet_info *myinfo,struct iguana_info *coin
u = &U[outpt.unspentind]; u = &U[outpt.unspentind];
if ( (txidind= u->txidind) > 0 && txidind < rdata->numtxids ) if ( (txidind= u->txidind) > 0 && txidind < rdata->numtxids )
{ {
if ( iguana_unspentindfind(myinfo,coin,coinaddr,spendscript,&spendlen,&amount,&height,T[txidind].txid,u->vout,coin->bundlescount-1,0) == outpt.unspentind && spendlen > 0 ) if ( iguana_unspentindfind(myinfo,coin,&RTspent,coinaddr,spendscript,&spendlen,&amount,&height,T[txidind].txid,u->vout,coin->bundlescount-1,0) == outpt.unspentind && spendlen > 0 )
{ {
jaddi(vins,iguana_inputjson(T[txidind].txid,u->vout,spendscript,spendlen)); jaddi(vins,iguana_inputjson(T[txidind].txid,u->vout,spendscript,spendlen));
total += outpt.value; total += outpt.value;
@ -847,7 +847,7 @@ int64_t iguana_txdetails(struct supernet_info *myinfo,struct iguana_info *coin,c
if ( vout >= 0 ) if ( vout >= 0 )
{ {
jaddnum(item,"vout",vout); jaddnum(item,"vout",vout);
if ( (amount= iguana_txidamount(myinfo,coin,txid,vout)) != 0 ) if ( (amount= iguana_txidamount(myinfo,coin,coinaddr,txid,vout)) != 0 )
jaddnum(item,"amount",dstr(amount)); jaddnum(item,"amount",dstr(amount));
jaddstr(item,"category",iguana_txidcategory(myinfo,coin,account,coinaddr,txid,vout)); jaddstr(item,"category",iguana_txidcategory(myinfo,coin,account,coinaddr,txid,vout));
} }
@ -1252,7 +1252,7 @@ TWOINTS_AND_ARRAY(bitcoinrpc,listunspent,minconf,maxconf,array)
maxconf = (1 << 30); maxconf = (1 << 30);
if ( (argarray= array) == 0 || cJSON_GetArraySize(array) == 0 ) if ( (argarray= array) == 0 || cJSON_GetArraySize(array) == 0 )
argarray = iguana_getaddressesbyaccount(myinfo,coin,"*"); argarray = iguana_getaddressesbyaccount(myinfo,coin,"*");
retjson = iguana_RTlistunspent(myinfo,coin,argarray,minconf,maxconf,remoteaddr); retjson = iguana_RTlistunspent(myinfo,coin,argarray,minconf,maxconf,remoteaddr,0);
if ( argarray != array ) if ( argarray != array )
free_json(argarray); free_json(argarray);
return(jprint(retjson,1)); return(jprint(retjson,1));

43
iguana/iguana_realtime.c

@ -648,7 +648,7 @@ void iguana_RTunspent(struct iguana_info *coin,struct iguana_RTtxid *RTptr,struc
void iguana_RTspend(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_RTtxid *RTptr,struct iguana_block *block,int64_t polarity,uint8_t *script,int32_t scriptlen,bits256 txid,int32_t vini,bits256 prev_hash,int32_t prev_vout) void iguana_RTspend(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_RTtxid *RTptr,struct iguana_block *block,int64_t polarity,uint8_t *script,int32_t scriptlen,bits256 txid,int32_t vini,bits256 prev_hash,int32_t prev_vout)
{ {
struct iguana_RTspend *spend; struct iguana_RTtxid *spentRTptr; struct iguana_RTunspent *unspent=0; char str[65],str2[65],coinaddr[64]; uint8_t addrtype,rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE]; uint32_t unspentind; int32_t spendlen,height; uint64_t value; struct iguana_outpoint spentpt; struct iguana_RTspend *spend; struct iguana_RTtxid *spentRTptr; struct iguana_RTunspent *unspent=0; char str[65],str2[65],coinaddr[64]; uint8_t addrtype,rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE]; uint32_t unspentind; int32_t spendlen,height; uint64_t RTspent,value; struct iguana_outpoint spentpt;
//printf("RTspend %s vini.%d spend.(%s/v%d) %lld\n",bits256_str(str,txid),vini,bits256_str(str2,prev_hash),prev_vout,(long long)polarity); //printf("RTspend %s vini.%d spend.(%s/v%d) %lld\n",bits256_str(str,txid),vini,bits256_str(str2,prev_hash),prev_vout,(long long)polarity);
if ( vini == 0 && bits256_nonz(prev_hash) == 0 && prev_vout < 0 ) if ( vini == 0 && bits256_nonz(prev_hash) == 0 && prev_vout < 0 )
return; return;
@ -689,7 +689,7 @@ void iguana_RTspend(struct supernet_info *myinfo,struct iguana_info *coin,struct
} }
else else
{ {
if ( (unspentind= iguana_unspentindfind(myinfo,coin,coinaddr,spendscript,&spendlen,&value,&height,prev_hash,prev_vout,coin->bundlescount,0)) == 0 ) if ( (unspentind= iguana_unspentindfind(myinfo,coin,&RTspent,coinaddr,spendscript,&spendlen,&value,&height,prev_hash,prev_vout,coin->bundlescount,0)) == 0 )
printf("iguana_RTspend cant find spentRTptr.(%s) search history\n",bits256_str(str,prev_hash)); printf("iguana_RTspend cant find spentRTptr.(%s) search history\n",bits256_str(str,prev_hash));
else else
{ {
@ -807,7 +807,7 @@ int32_t _iguana_RTunspentfind(struct supernet_info *myinfo,struct iguana_info *c
int32_t iguana_RTunspentindfind(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr,uint8_t *spendscript,int32_t *spendlenp,uint64_t *valuep,int32_t *heightp,bits256 txid,int32_t vout,int32_t lasthdrsi,int32_t mempool) int32_t iguana_RTunspentindfind(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr,uint8_t *spendscript,int32_t *spendlenp,uint64_t *valuep,int32_t *heightp,bits256 txid,int32_t vout,int32_t lasthdrsi,int32_t mempool)
{ {
char _coinaddr[64]; uint8_t rmd160[20]; int64_t value; char _coinaddr[64]; uint8_t rmd160[20]; uint64_t value,RTspend; uint32_t unspentind;
if ( coinaddr == 0 ) if ( coinaddr == 0 )
coinaddr = _coinaddr; coinaddr = _coinaddr;
if ( (value= _RTgettxout(coin,heightp,spendlenp,spendscript,rmd160,coinaddr,txid,vout,mempool)) > 0 ) if ( (value= _RTgettxout(coin,heightp,spendlenp,spendscript,rmd160,coinaddr,txid,vout,mempool)) > 0 )
@ -816,7 +816,38 @@ int32_t iguana_RTunspentindfind(struct supernet_info *myinfo,struct iguana_info
*valuep = value; *valuep = value;
return(0); return(0);
} }
else return(iguana_unspentindfind(myinfo,coin,coinaddr,spendscript,spendlenp,valuep,heightp,txid,vout,lasthdrsi,mempool)); else
{
if ( (unspentind= iguana_unspentindfind(myinfo,coin,&RTspend,coinaddr,spendscript,spendlenp,valuep,heightp,txid,vout,lasthdrsi,mempool)) != 0 )
{
if ( valuep != 0 && *valuep == 0 )
*valuep = RTspend;
return(0);
}
return(-1);
}
}
int32_t iguana_outptset(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_outpoint *outpt,bits256 txid,int32_t vout)
{
int32_t scriptlen,height; uint64_t RTspend; char coinaddr[64]; uint64_t value = 0; struct iguana_RTtxid *RTptr;
memset(outpt,0,sizeof(*outpt));
HASH_FIND(hh,coin->RTdataset,txid.bytes,sizeof(txid),RTptr);
if ( RTptr != 0 )
{
outpt->isptr = 1;
outpt->ptr = RTptr;
}
else
{
if ( (outpt->unspentind= iguana_unspentindfind(myinfo,coin,&RTspend,coinaddr,0,&scriptlen,&value,&height,txid,vout,coin->bundlescount-1,0)) != 0 )
{
outpt->hdrsi = (height / coin->chain->bundlesize);
if ( outpt->value == 0 )
outpt->value = (value == 0) ? RTspend : value;
} else return(-1);
}
return(0);
} }
int32_t iguana_txidheight(struct supernet_info *myinfo,struct iguana_info *coin,bits256 txid) int32_t iguana_txidheight(struct supernet_info *myinfo,struct iguana_info *coin,bits256 txid)
@ -826,9 +857,9 @@ int32_t iguana_txidheight(struct supernet_info *myinfo,struct iguana_info *coin,
return(height); return(height);
} }
int64_t iguana_txidamount(struct supernet_info *myinfo,struct iguana_info *coin,bits256 txid,int32_t vout) int64_t iguana_txidamount(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout)
{ {
int32_t spendlen,height = 0; uint64_t value; char coinaddr[64]; uint8_t spendscript[IGUANA_MAXSCRIPTSIZE]; int32_t spendlen,height = 0; uint64_t value; uint8_t spendscript[IGUANA_MAXSCRIPTSIZE];
iguana_RTunspentindfind(myinfo,coin,coinaddr,spendscript,&spendlen,&value,&height,txid,vout,(coin->firstRTheight/coin->chain->bundlesize) - 1,0); iguana_RTunspentindfind(myinfo,coin,coinaddr,spendscript,&spendlen,&value,&height,txid,vout,(coin->firstRTheight/coin->chain->bundlesize) - 1,0);
return(value); return(value);
} }

4
iguana/iguana_spendvectors.c

@ -184,7 +184,7 @@ struct iguana_bundle *iguana_externalspent(struct iguana_info *coin,bits256 *pre
struct iguana_bundle *iguana_fastexternalspent(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *prevhashp,uint32_t *unspentindp,struct iguana_ramchain *ramchain,int32_t spent_hdrsi,struct iguana_spend *s) struct iguana_bundle *iguana_fastexternalspent(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *prevhashp,uint32_t *unspentindp,struct iguana_ramchain *ramchain,int32_t spent_hdrsi,struct iguana_spend *s)
{ {
int32_t prev_vout,height,hdrsi,unspentind; uint32_t ind; int32_t prev_vout,height,hdrsi,unspentind; uint32_t ind; uint64_t RTspent;
struct iguana_txid *T; bits256 *X; bits256 prev_hash; struct iguana_ramchaindata *rdata; struct iguana_txid *T; bits256 *X; bits256 prev_hash; struct iguana_ramchaindata *rdata;
if ( (rdata= ramchain->H.data) == 0 ) if ( (rdata= ramchain->H.data) == 0 )
return(0); return(0);
@ -202,7 +202,7 @@ struct iguana_bundle *iguana_fastexternalspent(struct supernet_info *myinfo,stru
X = RAMCHAIN_PTR(rdata,Xoffset); X = RAMCHAIN_PTR(rdata,Xoffset);
//X = (void *)(long)((long)rdata + rdata->Xoffset); //X = (void *)(long)((long)rdata + rdata->Xoffset);
*prevhashp = prev_hash = X[ind]; *prevhashp = prev_hash = X[ind];
if ( (unspentind= iguana_unspentindfind(myinfo,coin,0,0,0,0,&height,prev_hash,prev_vout,spent_hdrsi-1,0)) != 0 ) if ( (unspentind= iguana_unspentindfind(myinfo,coin,&RTspent,0,0,0,0,&height,prev_hash,prev_vout,spent_hdrsi-1,0)) != 0 )
//if ( (firstvout= iguana_txidfastfind(coin,&height,prev_hash,spent_hdrsi-1)) >= 0 ) //if ( (firstvout= iguana_txidfastfind(coin,&height,prev_hash,spent_hdrsi-1)) >= 0 )
{ {
/*duration = (OS_milliseconds() - startmillis); /*duration = (OS_milliseconds() - startmillis);

88
iguana/iguana_unspents.c

@ -64,12 +64,13 @@ int32_t iguana_RTunspentind2txid(struct supernet_info *myinfo,struct iguana_info
return(-1); return(-1);
} }
int32_t iguana_unspentindfind(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr,uint8_t *spendscript,int32_t *spendlenp,uint64_t *valuep,int32_t *heightp,bits256 txid,int32_t vout,int32_t lasthdrsi,int32_t mempool) int32_t iguana_unspentindfind(struct supernet_info *myinfo,struct iguana_info *coin,uint64_t *spentamountp,char *coinaddr,uint8_t *spendscript,int32_t *spendlenp,uint64_t *valuep,int32_t *heightp,bits256 txid,int32_t vout,int32_t lasthdrsi,int32_t mempool)
{ {
struct iguana_txid *tp,TX; struct gecko_memtx *memtx; struct iguana_pkhash *P; struct iguana_unspent *U; struct iguana_bundle *bp; struct iguana_ramchaindata *rdata; int64_t RTspend; int64_t value; struct iguana_outpoint spentpt; int32_t pkind,hdrsi,firstvout,spentheight,flag=0,unspentind = -1; struct iguana_txid *tp,TX; struct gecko_memtx *memtx; struct iguana_pkhash *P; struct iguana_unspent *U; struct iguana_bundle *bp; struct iguana_ramchaindata *rdata; int64_t RTspend; int64_t value; struct iguana_outpoint spentpt; int32_t pkind,hdrsi,firstvout,spentheight,flag=0,unspentind = -1;
//portable_mutex_lock(&coin->RTmutex); //portable_mutex_lock(&coin->RTmutex);
if ( valuep != 0 ) if ( valuep != 0 )
*valuep = 0; *valuep = 0;
*spentamountp = 0;
if ( coinaddr != 0 ) if ( coinaddr != 0 )
coinaddr[0] = 0; coinaddr[0] = 0;
if ( coin->fastfind != 0 && (firstvout= iguana_txidfastfind(coin,heightp,txid,lasthdrsi)) >= 0 ) if ( coin->fastfind != 0 && (firstvout= iguana_txidfastfind(coin,heightp,txid,lasthdrsi)) >= 0 )
@ -94,14 +95,14 @@ int32_t iguana_unspentindfind(struct supernet_info *myinfo,struct iguana_info *c
memset(&spentpt,0,sizeof(spentpt)); memset(&spentpt,0,sizeof(spentpt));
spentpt.hdrsi = bp->hdrsi; spentpt.hdrsi = bp->hdrsi;
spentpt.unspentind = unspentind; spentpt.unspentind = unspentind;
bitcoin_address(coinaddr,iguana_addrtype(coin,U[unspentind].type),P[pkind].rmd160,sizeof(P[pkind].rmd160));
if ( iguana_RTspentflag(myinfo,coin,&RTspend,&spentheight,&bp->ramchain,spentpt,0,1,coin->longestchain,U[unspentind].value) == 0 ) //bp == coin->current ? &coin->RTramchain : if ( iguana_RTspentflag(myinfo,coin,&RTspend,&spentheight,&bp->ramchain,spentpt,0,1,coin->longestchain,U[unspentind].value) == 0 ) //bp == coin->current ? &coin->RTramchain :
{ {
if ( valuep != 0 ) if ( valuep != 0 )
*valuep = U[unspentind].value; *valuep = U[unspentind].value;
bitcoin_address(coinaddr,iguana_addrtype(coin,U[unspentind].type),P[pkind].rmd160,sizeof(P[pkind].rmd160));
if ( spendscript != 0 && spendlenp != 0 ) if ( spendscript != 0 && spendlenp != 0 )
*spendlenp = iguana_voutscript(coin,bp,spendscript,0,&U[unspentind],&P[pkind],1); *spendlenp = iguana_voutscript(coin,bp,spendscript,0,&U[unspentind],&P[pkind],1);
} } else *spentamountp = RTspend;
} }
} }
if ( flag == 0 && mempool != 0 ) if ( flag == 0 && mempool != 0 )
@ -168,10 +169,9 @@ cJSON *ramchain_unspentjson(struct iguana_unspent *up,uint32_t unspentind)
return(item); return(item);
} }
cJSON *ramchain_spentjson(struct iguana_info *coin,int32_t spentheight,bits256 txid,int32_t vout,int64_t uvalue) cJSON *ramchain_spentjson(struct supernet_info *myinfo,struct iguana_info *coin,int32_t spentheight,bits256 txid,int32_t vout,int64_t uvalue)
{ {
char coinaddr[64]; bits256 hash2,*X; struct iguana_txid T,*tx,*spentT,*spent_tx; struct iguana_bundle *bp; int32_t j,i,ind; struct iguana_block *block; int64_t total = 0; struct iguana_unspent *U,*u; struct iguana_pkhash *P; struct iguana_spend *S,*s; struct iguana_ramchaindata *rdata; cJSON *addrs,*item,*voutobj; char coinaddr[64]; bits256 hash2,*X; struct iguana_txid T,*tx,*spentT,*spent_tx; struct iguana_bundle *bp; int32_t j,i,ind; struct iguana_block *block; int64_t value,total = 0; struct iguana_unspent *U,*u; struct iguana_pkhash *P; struct iguana_spend *S,*s; struct iguana_ramchaindata *rdata; cJSON *addrs,*item,*voutobj;
//RTpath!
item = cJSON_CreateObject(); item = cJSON_CreateObject();
hash2 = iguana_blockhash(coin,spentheight); hash2 = iguana_blockhash(coin,spentheight);
if ( (block= iguana_blockfind("spent",coin,hash2)) != 0 && (bp= coin->bundles[spentheight/coin->chain->bundlesize]) != 0 && (rdata= bp->ramchain.H.data) != 0 ) if ( (block= iguana_blockfind("spent",coin,hash2)) != 0 && (bp= coin->bundles[spentheight/coin->chain->bundlesize]) != 0 && (rdata= bp->ramchain.H.data) != 0 )
@ -185,8 +185,6 @@ cJSON *ramchain_spentjson(struct iguana_info *coin,int32_t spentheight,bits256 t
{ {
if ( (tx= iguana_blocktx(coin,&T,block,i)) != 0 ) if ( (tx= iguana_blocktx(coin,&T,block,i)) != 0 )
{ {
// struct iguana_txid { bits256 txid; uint32_t txidind:29,firstvout:28,firstvin:28,bundlei:11,locktime,version,timestamp,extraoffset; uint16_t numvouts,numvins; } __attribute__((packed));
// struct iguana_spend { uint64_t scriptpos:48,scriptlen:16; uint32_t spendtxidind,sequenceid; int16_t prevout; uint16_t fileid:15,external:1; } __attribute__((packed)); // numsigs:4,numpubkeys:4,p2sh:1,sighash:4
s = &S[tx->firstvin]; s = &S[tx->firstvin];
for (j=0; j<tx->numvins; j++,s++) for (j=0; j<tx->numvins; j++,s++)
{ {
@ -226,6 +224,34 @@ cJSON *ramchain_spentjson(struct iguana_info *coin,int32_t spentheight,bits256 t
} }
} }
} }
else
{
struct iguana_RTtxid *RTptr,*tmp; struct iguana_RTspend *spend;
HASH_ITER(hh,coin->RTdataset,RTptr,tmp)
{
for (i=0; i<RTptr->numvins; i++)
{
if ( (spend= RTptr->spends[i]) != 0 )
{
if ( bits256_cmp(spend->prev_hash,txid) == 0 && spend->prev_vout == vout )
{
value = iguana_txidamount(myinfo,coin,coinaddr,txid,vout);
jaddnum(item,"total",dstr(value));
jaddbits256(item,"spentfrom",RTptr->txid);
jaddnum(item,"vin",i);
addrs = cJSON_CreateArray();
voutobj = cJSON_CreateObject();
jaddnum(voutobj,coinaddr,dstr(value));
jaddi(addrs,voutobj);
jadd(item,"vouts",addrs);
jaddnum(item,"timestamp",RTptr->timestamp);
//printf("Found MATCH! (%s %.8f)\n",coinaddr,dstr(value));
return(item);
}
}
}
}
}
jaddstr(item,"error","couldnt find spent info"); jaddstr(item,"error","couldnt find spent info");
return(item); return(item);
} }
@ -286,7 +312,7 @@ cJSON *iguana_RTunspentjson(struct supernet_info *myinfo,struct iguana_info *coi
if ( up != 0 ) if ( up != 0 )
jadd(item,"spent",ramchain_unspentjson(up,outpt.unspentind)); jadd(item,"spent",ramchain_unspentjson(up,outpt.unspentind));
jaddnum(item,"spentheight",spentheight); jaddnum(item,"spentheight",spentheight);
jadd(item,"dest",ramchain_spentjson(coin,spentheight,txid,vout,value)); jadd(item,"dest",ramchain_spentjson(myinfo,coin,spentheight,txid,vout,value));
} }
else if ( up != 0 ) else if ( up != 0 )
jadd(item,"unspent",ramchain_unspentjson(up,outpt.unspentind)); jadd(item,"unspent",ramchain_unspentjson(up,outpt.unspentind));
@ -764,14 +790,17 @@ int32_t iguana_RTunspent_check(struct supernet_info *myinfo,struct iguana_info *
{ {
bits256 txid; int32_t vout,spentheight; bits256 txid; int32_t vout,spentheight;
memset(&txid,0,sizeof(txid)); memset(&txid,0,sizeof(txid));
printf("RTunspent_check needs to be ported\n");
return(0);
if ( iguana_RTunspentind2txid(myinfo,coin,&spentheight,&txid,&vout,outpt) == 0 ) if ( iguana_RTunspentind2txid(myinfo,coin,&spentheight,&txid,&vout,outpt) == 0 )
{ {
//char str[65]; printf("verify %s/v%d is not already used\n",bits256_str(str,txid),vout); //char str[65]; printf("verify %s/v%d is not already used\n",bits256_str(str,txid),vout);
if ( basilisk_addspend(myinfo,coin->symbol,txid,vout,0) != 0 ) //return(iguana_RTspentflag(myinfo,coin,&RTspend,&spentheight,ramchain,outpt,height,minconf,coin->longestchain,U[unspentind].value));
/*if ( basilisk_addspend(myinfo,coin->symbol,txid,vout,0) != 0 )
{ {
char str[65]; printf("iguana_unspent_check found unspentind (%u %d) %s\n",outpt.hdrsi,outpt.unspentind,bits256_str(str,txid)); char str[65]; printf("iguana_unspent_check found unspentind (%u %d) %s\n",outpt.hdrsi,outpt.unspentind,bits256_str(str,txid));
return(1); return(1);
} else return(0); } else return(0);*/
} }
printf("iguana_unspent_check: couldnt find (%d %d)\n",outpt.hdrsi,outpt.unspentind); printf("iguana_unspent_check: couldnt find (%d %d)\n",outpt.hdrsi,outpt.unspentind);
return(-1); return(-1);
@ -792,7 +821,7 @@ int32_t iguana_RTaddr_unspents(struct supernet_info *myinfo,struct iguana_info *
int32_t iguana_RTunspentslists(struct supernet_info *myinfo,struct iguana_info *coin,uint64_t *totalp,struct iguana_outpoint *unspents,int32_t max,uint64_t required,int32_t minconf,cJSON *addresses,char *remoteaddr) int32_t iguana_RTunspentslists(struct supernet_info *myinfo,struct iguana_info *coin,uint64_t *totalp,struct iguana_outpoint *unspents,int32_t max,uint64_t required,int32_t minconf,cJSON *addresses,char *remoteaddr)
{ {
uint64_t sum = 0; int32_t k,i,j,r,numunspents,numaddrs; uint8_t addrtype,rmd160[20],pubkey[65]; char *coinaddr,str[65]; struct iguana_waddress *waddr; struct iguana_waccount *wacct; struct basilisk_unspent *bu; struct iguana_outpoint outpt; uint64_t sum = 0; int32_t i,j,n,numunspents,numaddrs; uint8_t addrtype,rmd160[20],pubkey[65]; char *coinaddr; struct iguana_waddress *waddr; struct iguana_waccount *wacct; struct iguana_outpoint outpt; cJSON *array,*item;
*totalp = 0; *totalp = 0;
if ( (numaddrs= cJSON_GetArraySize(addresses)) == 0 ) if ( (numaddrs= cJSON_GetArraySize(addresses)) == 0 )
{ {
@ -822,31 +851,22 @@ int32_t iguana_RTunspentslists(struct supernet_info *myinfo,struct iguana_info *
} }
else else
{ {
if ( (waddr= iguana_waddresssearch(myinfo,&wacct,coinaddr)) != 0 && waddr->numunspents > 0 ) if ( (waddr= iguana_waddresssearch(myinfo,&wacct,coinaddr)) != 0 )
{ {
r = (rand() % waddr->numunspents); if ( (array= waddr->unspents) != 0 )
for (j=0; j<waddr->numunspents; j++)
{ {
i = ((j + r) % waddr->numunspents); if ( (n= cJSON_GetArraySize(array)) > 0 )
bu = &waddr->unspents[i];
if ( basilisk_addspend(myinfo,coin->symbol,bu->txid,bu->vout,0) == 0 )
{ {
for (k=0; k<numunspents; k++) for (i=0; i<n; i++)
{ {
// filterout duplicates here item = jitem(array,i);
iguana_outptset(myinfo,coin,&outpt,jbits256(item,"txid"),jint(item,"vout"));
*unspents = outpt;
sum += outpt.value;
unspents++;
numunspents++;
} }
memset(&outpt,0,sizeof(outpt)); }
outpt.hdrsi = bu->hdrsi;
outpt.isptr = 0;
outpt.unspentind = bu->unspentind;
outpt.value = bu->value;
*unspents = outpt;
sum += bu->value;
printf("ADD unspent, mark spent\n");
basilisk_addspend(myinfo,coin->symbol,bu->txid,bu->vout,1);
unspents++;
numunspents++;
} else printf("skip pending txid.%s/v%d\n",bits256_str(str,bu->txid),bu->vout);
} }
} }
} }
@ -917,11 +937,11 @@ uint64_t iguana_unspentavail(struct supernet_info *myinfo,struct iguana_info *co
else return(0); else return(0);
} }
cJSON *iguana_RTlistunspent(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *argarray,int32_t minconf,int32_t maxconf,char *remoteaddr) cJSON *iguana_RTlistunspent(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *argarray,int32_t minconf,int32_t maxconf,char *remoteaddr,int32_t includespends)
{ {
int32_t numrmds,numunspents=0; uint8_t *rmdarray; cJSON *retjson = cJSON_CreateArray(); int32_t numrmds,numunspents=0; uint8_t *rmdarray; cJSON *retjson = cJSON_CreateArray();
rmdarray = iguana_rmdarray(myinfo,coin,&numrmds,argarray,0); rmdarray = iguana_rmdarray(myinfo,coin,&numrmds,argarray,0);
iguana_RTunspents(myinfo,coin,retjson,minconf,maxconf,rmdarray,numrmds,(1 << 30),0,&numunspents,remoteaddr,0); iguana_RTunspents(myinfo,coin,retjson,minconf,maxconf,rmdarray,numrmds,(1 << 30),0,&numunspents,remoteaddr,includespends);
if ( rmdarray != 0 ) if ( rmdarray != 0 )
free(rmdarray); free(rmdarray);
/*{ /*{

18
iguana/iguana_wallet.c

@ -116,7 +116,7 @@ struct iguana_waddress *iguana_waddresscreate(struct supernet_info *myinfo,struc
struct iguana_waddress *iguana_waddressadd(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount *wacct,struct iguana_waddress *addwaddr,char *redeemScript) struct iguana_waddress *iguana_waddressadd(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount *wacct,struct iguana_waddress *addwaddr,char *redeemScript)
{ {
struct iguana_waddress *waddr,*ptr; uint8_t rmd160[20],addrtype; struct iguana_waddress *waddr,*ptr; uint8_t rmd160[20],addrtype;
printf("search for (%s)\n",addwaddr->coinaddr); //printf("search for (%s)\n",addwaddr->coinaddr);
bitcoin_addr2rmd160(&addrtype,rmd160,addwaddr->coinaddr); bitcoin_addr2rmd160(&addrtype,rmd160,addwaddr->coinaddr);
HASH_FIND(hh,wacct->waddr,rmd160,sizeof(rmd160),waddr); HASH_FIND(hh,wacct->waddr,rmd160,sizeof(rmd160),waddr);
if ( waddr == 0 ) if ( waddr == 0 )
@ -167,9 +167,9 @@ struct iguana_waddress *iguana_waddressadd(struct supernet_info *myinfo,struct i
{ {
HASH_ADD_KEYPTR(hh,wacct->waddr,waddr->rmd160,sizeof(waddr->rmd160),waddr); HASH_ADD_KEYPTR(hh,wacct->waddr,waddr->rmd160,sizeof(waddr->rmd160),waddr);
myinfo->dirty = (uint32_t)time(NULL); myinfo->dirty = (uint32_t)time(NULL);
int32_t i; for (i=0; i<20; i++) //int32_t i; for (i=0; i<20; i++)
printf("%02x",waddr->rmd160[i]); // printf("%02x",waddr->rmd160[i]);
printf(" add (%s) scriptlen.%d -> (%s) wif.(%s)\n",waddr->coinaddr,waddr->scriptlen,wacct->account,waddr->wifstr); //printf(" add (%s) scriptlen.%d -> (%s) wif.(%s)\n",waddr->coinaddr,waddr->scriptlen,wacct->account,waddr->wifstr);
} }
else else
{ {
@ -746,7 +746,9 @@ cJSON *iguana_walletiterate(struct supernet_info *myinfo,struct iguana_info *coi
{ {
HASH_DELETE(hh,wacct->waddr,waddr); HASH_DELETE(hh,wacct->waddr,waddr);
if ( waddr->unspents != 0 ) if ( waddr->unspents != 0 )
free(waddr->unspents); free_json(waddr->unspents), waddr->unspents = 0;
if ( waddr->spends != 0 )
free_json(waddr->spends), waddr->spends = 0;
//printf("walletiterate: %p free %s\n",waddr,waddr->coinaddr); //printf("walletiterate: %p free %s\n",waddr,waddr->coinaddr);
myfree(waddr,sizeof(*waddr) + waddr->scriptlen); myfree(waddr,sizeof(*waddr) + waddr->scriptlen);
} }
@ -879,7 +881,7 @@ void iguana_walletinitcheck(struct supernet_info *myinfo,struct iguana_info *coi
myinfo->decryptstr = 0; myinfo->decryptstr = 0;
myinfo->dirty = 0; myinfo->dirty = 0;
} }
printf("call walletiterate from initcheck.%p\n",myinfo->decryptstr); //printf("call walletiterate from initcheck.%p\n",myinfo->decryptstr);
iguana_walletiterate(myinfo,coin,1,0,0,0,0); iguana_walletiterate(myinfo,coin,1,0,0,0,0);
} }
@ -967,7 +969,7 @@ cJSON *iguana_privkeysjson(struct supernet_info *myinfo,struct iguana_info *coin
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) 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)
{ {
int64_t balance = 0; cJSON *unspentsjson,*balancejson,*item; int32_t i,n; char *balancestr; int64_t balance = 0; cJSON *unspentsjson,*balancejson,*item; int32_t i,n; char *balancestr;
if ( (balancestr= iguana_balance(IGUANA_CALLARGS,coin->symbol,coinaddr,-1,minconf)) != 0 ) if ( (balancestr= iguana_balance(IGUANA_CALLARGS,coin->symbol,coinaddr,1<<30,minconf)) != 0 )
{ {
//printf("balancestr.(%s) (%s)\n",balancestr,coinaddr); //printf("balancestr.(%s) (%s)\n",balancestr,coinaddr);
if ( (balancejson= cJSON_Parse(balancestr)) != 0 ) if ( (balancejson= cJSON_Parse(balancestr)) != 0 )
@ -1138,7 +1140,7 @@ struct iguana_waddress *iguana_getaccountaddress(struct supernet_info *myinfo,st
wacct = iguana_waccountcreate(myinfo,account); wacct = iguana_waccountcreate(myinfo,account);
if ( wacct != 0 ) if ( wacct != 0 )
{ {
if ( (waddr= wacct->current) == 0 || waddr->numunspents > 0 ) if ( (waddr= wacct->current) == 0 || waddr->unspents != 0 )
{ {
if ( (retstr= SuperNET_login(IGUANA_CALLARGS,myinfo->handle,myinfo->secret,myinfo->permanentfile,myinfo->password)) != 0 ) if ( (retstr= SuperNET_login(IGUANA_CALLARGS,myinfo->handle,myinfo->secret,myinfo->permanentfile,myinfo->password)) != 0 )
{ {

15
iguana/ramchain_api.c

@ -27,7 +27,7 @@ STRING_ARG(iguana,initfastfind,activecoin)
TWO_STRINGS_AND_TWO_DOUBLES(iguana,balance,activecoin,address,lastheightd,minconfd) TWO_STRINGS_AND_TWO_DOUBLES(iguana,balance,activecoin,address,lastheightd,minconfd)
{ {
int32_t lastheight,minconf,maxconf=SATOSHIDEN; uint64_t total=0; uint8_t rmd160[20],pubkey33[33],addrtype; struct iguana_pkhash *P; cJSON *array,*retjson = cJSON_CreateObject(); int32_t lastheight,minconf,maxconf=SATOSHIDEN; cJSON *array,*retjson = cJSON_CreateObject();
if ( activecoin != 0 && activecoin[0] != 0 ) if ( activecoin != 0 && activecoin[0] != 0 )
coin = iguana_coinfind(activecoin); coin = iguana_coinfind(activecoin);
if ( coin != 0 ) if ( coin != 0 )
@ -42,21 +42,22 @@ TWO_STRINGS_AND_TWO_DOUBLES(iguana,balance,activecoin,address,lastheightd,mincon
return(jprint(retjson,1)); return(jprint(retjson,1));
} }
jadd64bits(retjson,"RTbalance",iguana_RTbalance(coin,address)); jadd64bits(retjson,"RTbalance",iguana_RTbalance(coin,address));
if ( bitcoin_addr2rmd160(&addrtype,rmd160,address) < 0 ) array = cJSON_CreateArray();
jaddistr(array,address);
/*if ( bitcoin_addr2rmd160(&addrtype,rmd160,address) < 0 )
{ {
jaddstr(retjson,"error","cant convert address"); jaddstr(retjson,"error","cant convert address");
return(jprint(retjson,1)); return(jprint(retjson,1));
} }
memset(pubkey33,0,sizeof(pubkey33)); memset(pubkey33,0,sizeof(pubkey33));
P = calloc(coin->bundlescount,sizeof(*P)); P = calloc(coin->bundlescount,sizeof(*P));
array = cJSON_CreateArray();
//printf("Start %s balance.(%s) height.%d\n",coin->symbol,address,lastheight); //printf("Start %s balance.(%s) height.%d\n",coin->symbol,address,lastheight);
if ( lastheight <= 0 ) if ( lastheight <= 0 )
lastheight = IGUANA_MAXHEIGHT; lastheight = IGUANA_MAXHEIGHT;
iguana_RTpkhasharray(myinfo,coin,array,minconf,maxconf,&total,P,coin->bundlescount,rmd160,address,pubkey33,lastheight,0,0,0,remoteaddr,1); //iguana_RTpkhasharray(myinfo,coin,array,minconf,maxconf,&total,P,coin->bundlescount,rmd160,address,pubkey33,lastheight,0,0,0,remoteaddr,1);
free(P); jaddnum(retjson,"balance",dstr(total));
jadd(retjson,"unspents",array); //free(P);*/
jaddnum(retjson,"balance",dstr(total)); jadd(retjson,"unspents",iguana_RTlistunspent(myinfo,coin,array,minconf,maxconf,remoteaddr,1));
if ( lastheight > 0 ) if ( lastheight > 0 )
jaddnum(retjson,"RTheight",coin->RTheight); jaddnum(retjson,"RTheight",coin->RTheight);
} }

1
iguana/tests/balance

@ -0,0 +1 @@
curl --url "http://127.0.0.1:7778" --data "{\"activecoin\":\"BTCD\",\"timeout\":20000,\"agent\":\"iguana\",\"method\":\"balance\",\"address\":\"RRyBxbrAPRUBCUpiJgJZYrkxqrh8x5ta9Z\"}"

9
includes/iguana_funcs.h

@ -409,7 +409,8 @@ void iguana_volatilesalloc(struct iguana_info *coin,struct iguana_ramchain *ramc
int32_t iguana_send_ping(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_peer *addr); int32_t iguana_send_ping(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_peer *addr);
int32_t iguana_process_msgrequestQ(struct supernet_info *myinfo,struct iguana_info *coin); int32_t iguana_process_msgrequestQ(struct supernet_info *myinfo,struct iguana_info *coin);
uint32_t iguana_fastfindinit(struct iguana_info *coin); uint32_t iguana_fastfindinit(struct iguana_info *coin);
int32_t iguana_unspentindfind(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr,uint8_t *spendscript,int32_t *scriptlenp,uint64_t *valuep,int32_t *heightp,bits256 txid,int32_t vout,int32_t lasthdrsi,int32_t mempool); int32_t iguana_outptset(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_outpoint *outpt,bits256 txid,int32_t vout);
int32_t iguana_unspentindfind(struct supernet_info *myinfo,struct iguana_info *coin,uint64_t *spentamountp,char *coinaddr,uint8_t *spendscript,int32_t *scriptlenp,uint64_t *valuep,int32_t *heightp,bits256 txid,int32_t vout,int32_t lasthdrsi,int32_t mempool);
int32_t iguana_RTunspentindfind(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr,uint8_t *spendscript,int32_t *scriptlenp,uint64_t *valuep,int32_t *heightp,bits256 txid,int32_t vout,int32_t lasthdrsi,int32_t mempool); int32_t iguana_RTunspentindfind(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr,uint8_t *spendscript,int32_t *scriptlenp,uint64_t *valuep,int32_t *heightp,bits256 txid,int32_t vout,int32_t lasthdrsi,int32_t mempool);
int32_t iguana_addressvalidate(struct iguana_info *coin,uint8_t *addrtypep,char *address); int32_t iguana_addressvalidate(struct iguana_info *coin,uint8_t *addrtypep,char *address);
int32_t bitcoin_sign(void *ctx,char *symbol,uint8_t *sig,bits256 txhash2,bits256 privkey,int32_t recoverflag); int32_t bitcoin_sign(void *ctx,char *symbol,uint8_t *sig,bits256 txhash2,bits256 privkey,int32_t recoverflag);
@ -422,9 +423,9 @@ struct iguana_RTaddr *iguana_RTaddrfind(struct iguana_info *coin,uint8_t *rmd160
cJSON *iguana_RTunspentjson(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_outpoint outpt,bits256 txid,int32_t vout,int64_t value,struct iguana_unspent *up,uint8_t rmd160[20],char *coinaddr,uint8_t *pubkey33,int32_t spentheight,char *remoteaddr); cJSON *iguana_RTunspentjson(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_outpoint outpt,bits256 txid,int32_t vout,int64_t value,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]); 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); struct iguana_waddress *iguana_waddresssearch(struct supernet_info *myinfo,struct iguana_waccount **wacctp,char *coinaddr);
cJSON *iguana_RTlistunspent(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *argarray,int32_t minconf,int32_t maxconf,char *remoteaddr); 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); 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); //struct basilisk_spend *basilisk_addspend(struct supernet_info *myinfo,char *symbol,bits256 txid,uint16_t vout,int32_t addflag);
int64_t _RTgettxout(struct iguana_info *coin,int32_t *height,int32_t *scriptlen,uint8_t *script,uint8_t *rmd160,char *coinaddr,bits256 txid,int32_t vout,int32_t mempool); int64_t _RTgettxout(struct iguana_info *coin,int32_t *height,int32_t *scriptlen,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 _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); 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);
@ -522,7 +523,7 @@ char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,
char *SuperNET_JSON(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *json,char *remoteaddr,uint16_t port); char *SuperNET_JSON(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *json,char *remoteaddr,uint16_t port);
int64_t iguana_txdetails(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *item,bits256 txid,int32_t vout,int32_t height); int64_t iguana_txdetails(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *item,bits256 txid,int32_t vout,int32_t height);
int32_t iguana_txidheight(struct supernet_info *myinfo,struct iguana_info *coin,bits256 txid); int32_t iguana_txidheight(struct supernet_info *myinfo,struct iguana_info *coin,bits256 txid);
int64_t iguana_txidamount(struct supernet_info *myinfo,struct iguana_info *coin,bits256 txid,int32_t vout); int64_t iguana_txidamount(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout);
char *iguana_txidcategory(struct supernet_info *myinfo,struct iguana_info *coin,char *account,char *coinaddr,bits256 txid,int32_t vout); char *iguana_txidcategory(struct supernet_info *myinfo,struct iguana_info *coin,char *account,char *coinaddr,bits256 txid,int32_t vout);
struct supernet_info *SuperNET_accountfind(cJSON *json); struct supernet_info *SuperNET_accountfind(cJSON *json);
cJSON *SuperNET_rosettajson(struct supernet_info *myinfo,bits256 privkey,int32_t showprivs); cJSON *SuperNET_rosettajson(struct supernet_info *myinfo,bits256 privkey,int32_t showprivs);

2
includes/iguana_structs.h

@ -374,7 +374,7 @@ struct basilisk_spend { bits256 txid,spentfrom; uint64_t relaymask,value; uint32
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 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_waddress { UT_hash_handle hh; cJSON *unspents,*spends; uint64_t balance; 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; struct iguana_waddress *waddr,*current; char account[]; }; struct iguana_waccount { UT_hash_handle hh; struct iguana_waddress *waddr,*current; char account[]; };
struct iguana_wallet { UT_hash_handle hh; struct iguana_waccount *wacct; }; struct iguana_wallet { UT_hash_handle hh; struct iguana_waccount *wacct; };

Loading…
Cancel
Save