You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
489 lines
22 KiB
489 lines
22 KiB
/******************************************************************************
|
|
* Copyright © 2014-2016 The SuperNET Developers. *
|
|
* *
|
|
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
|
* the top-level directory of this distribution for the individual copyright *
|
|
* holder information and the developer policies on copyright and licensing. *
|
|
* *
|
|
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
|
* SuperNET software, including this file may be copied, modified, propagated *
|
|
* or distributed except according to the terms contained in the LICENSE file *
|
|
* *
|
|
* Removal or modification of this copyright notice is prohibited. *
|
|
* *
|
|
******************************************************************************/
|
|
|
|
#include "iguana777.h"
|
|
#include "exchanges/bitcoin.h"
|
|
|
|
struct iguana_pkhash *iguana_pkhashfind(struct iguana_info *coin,struct iguana_ramchain **ramchainp,int64_t *balancep,uint32_t *lastunspentindp,struct iguana_pkhash *p,uint8_t rmd160[20],int32_t firsti,int32_t endi)
|
|
{
|
|
uint8_t *PKbits; struct iguana_pkhash *P; uint32_t pkind,i; struct iguana_bundle *bp; struct iguana_ramchain *ramchain; struct iguana_account *ACCTS;
|
|
*balancep = 0;
|
|
*ramchainp = 0;
|
|
*lastunspentindp = 0;
|
|
for (i=firsti; i<coin->bundlescount&&i<=endi; i++)
|
|
{
|
|
if ( (bp= coin->bundles[i]) != 0 )
|
|
{
|
|
ramchain = &bp->ramchain;
|
|
if ( ramchain->H.data != 0 )
|
|
{
|
|
PKbits = (void *)(long)((long)ramchain->H.data + ramchain->H.data->PKoffset);
|
|
P = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Poffset);
|
|
ACCTS = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Aoffset);
|
|
if ( (pkind= iguana_sparseaddpk(PKbits,ramchain->H.data->pksparsebits,ramchain->H.data->numpksparse,rmd160,P,0)) > 0 && pkind < ramchain->H.data->numpkinds )
|
|
{
|
|
*ramchainp = ramchain;
|
|
*balancep = ACCTS[pkind].total;
|
|
*lastunspentindp = ACCTS[pkind].lastind;
|
|
*p = P[pkind];
|
|
return(p);
|
|
} //else printf("not found pkind.%d vs num.%d\n",pkind,ramchain->H.data->numpkinds);
|
|
} else printf("%s.[%d] error null ramchain->H.data\n",coin->symbol,i);
|
|
}
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
char *iguana_bundleaddrs(struct iguana_info *coin,int32_t hdrsi)
|
|
{
|
|
uint8_t *PKbits; struct iguana_pkhash *P; uint32_t pkind; struct iguana_bundle *bp; struct iguana_ramchain *ramchain; cJSON *retjson; char rmdstr[41];
|
|
if ( (bp= coin->bundles[hdrsi]) != 0 )
|
|
{
|
|
ramchain = &bp->ramchain;
|
|
if ( ramchain->H.data != 0 )
|
|
{
|
|
retjson = cJSON_CreateArray();
|
|
PKbits = (void *)(long)((long)ramchain->H.data + ramchain->H.data->PKoffset);
|
|
P = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Poffset);
|
|
for (pkind=0; pkind<ramchain->H.data->numpkinds; pkind++,P++)
|
|
{
|
|
init_hexbytes_noT(rmdstr,P->rmd160,20);
|
|
jaddistr(retjson,rmdstr);
|
|
}
|
|
return(jprint(retjson,1));
|
|
}
|
|
//iguana_bundleQ(coin,bp,bp->n);
|
|
return(clonestr("{\"error\":\"no bundle data\"}"));
|
|
} return(clonestr("{\"error\":\"no bundle\"}"));
|
|
}
|
|
|
|
struct iguana_bundle *iguana_spent(struct iguana_info *coin,bits256 *prevhashp,uint32_t *unspentindp,struct iguana_ramchain *ramchain,int32_t spend_hdrsi,struct iguana_spend *s)
|
|
{
|
|
int32_t prev_vout,height,hdrsi; uint32_t sequenceid,unspentind; char str[65];
|
|
struct iguana_bundle *spentbp=0; struct iguana_txid *T,TX,*tp; bits256 *X; bits256 prev_hash;
|
|
X = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Xoffset);
|
|
T = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Toffset);
|
|
sequenceid = s->sequenceid;
|
|
hdrsi = spend_hdrsi;
|
|
*unspentindp = 0;
|
|
memset(prevhashp,0,sizeof(*prevhashp));
|
|
if ( s->prevout < 0 )
|
|
{
|
|
//printf("n.%d coinbase at spendind.%d firstvin.%d -> firstvout.%d -> unspentind\n",m,spendind,nextT->firstvin,nextT->firstvout);
|
|
//nextT++;
|
|
//m++;
|
|
return(0);
|
|
}
|
|
else
|
|
{
|
|
prev_vout = s->prevout;
|
|
iguana_ramchain_spendtxid(coin,&unspentind,&prev_hash,T,ramchain->H.data->numtxids,X,ramchain->H.data->numexternaltxids,s);
|
|
*prevhashp = prev_hash;
|
|
*unspentindp = unspentind;
|
|
if ( unspentind == 0 )
|
|
{
|
|
if ( (tp= iguana_txidfind(coin,&height,&TX,prev_hash,spend_hdrsi-1)) != 0 )
|
|
{
|
|
*unspentindp = unspentind = TX.firstvout + ((prev_vout > 0) ? prev_vout : 0);
|
|
hdrsi = height / coin->chain->bundlesize;
|
|
//printf("%s height.%d firstvout.%d prev.%d ->U%d\n",bits256_str(str,prev_hash),height,TX.firstvout,prev_vout,unspentind);
|
|
}
|
|
else
|
|
{
|
|
printf("cant find prev_hash.(%s) for bp.[%d]\n",bits256_str(str,prev_hash),spend_hdrsi);
|
|
}
|
|
}
|
|
}
|
|
if ( hdrsi > spend_hdrsi || (spentbp= coin->bundles[hdrsi]) == 0 )
|
|
printf("illegal hdrsi.%d when [%d] spentbp.%p\n",hdrsi,spend_hdrsi,spentbp);//, getchar();
|
|
//else if ( spentbp->ramchain.spents[unspentind].ind != 0 || hdrsi < 0 )
|
|
// printf("DOUBLE SPEND? U%d %p bp.[%d] unspentind.%u already has %u, no room\n",unspentind,&spentbp->ramchain.spents[unspentind],hdrsi,unspentind,spentbp->ramchain.spents[unspentind].ind);//, getchar();
|
|
else if ( unspentind == 0 || unspentind >= spentbp->ramchain.H.data->numunspents )
|
|
printf("illegal unspentind.%d vs max.%d spentbp.%p[%d]\n",unspentind,spentbp->ramchain.H.data->numunspents,spentbp,hdrsi);//, getchar();
|
|
else return(spentbp);
|
|
return(0);
|
|
}
|
|
|
|
cJSON *iguana_unspentjson(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)
|
|
{
|
|
/*{
|
|
"txid" : "d54994ece1d11b19785c7248868696250ab195605b469632b7bd68130e880c9a",
|
|
"vout" : 1,
|
|
"address" : "mgnucj8nYqdrPFh2JfZSB1NmUThUGnmsqe",
|
|
"account" : "test label",
|
|
"scriptPubKey" : "76a9140dfc8bafc8419853b34d5e072ad37d1a5159f58488ac",
|
|
"amount" : 0.00010000,
|
|
"confirmations" : 6210,
|
|
"spendable" : true
|
|
},*/
|
|
//struct iguana_unspent { uint64_t value; uint32_t txidind,pkind,prevunspentind; uint16_t hdrsi:12,type:4,vout; } __attribute__((packed));
|
|
struct iguana_waccount *wacct; struct iguana_txid TX; int32_t height,ind; char scriptstr[8192],asmstr[sizeof(scriptstr)+1024]; cJSON *item;
|
|
item = cJSON_CreateObject();
|
|
jaddbits256(item,"txid",T[up->txidind].txid);
|
|
jaddnum(item,"vout",up->vout);
|
|
jaddstr(item,"address",coinaddr);
|
|
if ( (wacct= iguana_waddressfind(coin,&ind,coinaddr)) != 0 )
|
|
jaddstr(item,"account",wacct->account);
|
|
if ( iguana_scriptget(coin,scriptstr,asmstr,sizeof(scriptstr),hdrsi,unspentind,T[up->txidind].txid,up->vout,rmd160,up->type,pubkey33) != 0 )
|
|
jaddstr(item,"scriptPubKey",scriptstr);
|
|
jaddnum(item,"amount",dstr(up->value));
|
|
if ( iguana_txidfind(coin,&height,&TX,T[up->txidind].txid,coin->bundlescount-1) != 0 )
|
|
jaddnum(item,"confirmations",coin->longestchain - height);
|
|
return(item);
|
|
}
|
|
|
|
int64_t iguana_pkhashbalance(struct iguana_info *coin,cJSON *array,int64_t *spentp,int32_t *nump,struct iguana_ramchain *ramchain,struct iguana_pkhash *p,uint32_t lastunspentind,uint8_t rmd160[20],char *coinaddr,uint8_t *pubkey33,int32_t hdrsi)
|
|
{
|
|
struct iguana_unspent *U; uint32_t unspentind; int64_t balance = 0; struct iguana_txid *T;
|
|
*spentp = *nump = 0;
|
|
if ( ramchain->Uextras == 0 )
|
|
{
|
|
printf("iguana_pkhashbalance: unexpected null spents\n");
|
|
return(0);
|
|
}
|
|
unspentind = lastunspentind;
|
|
U = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Uoffset);
|
|
T = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Toffset);
|
|
while ( unspentind > 0 )
|
|
{
|
|
(*nump)++;
|
|
printf("%s u.%d %.8f\n",jprint(iguana_unspentjson(coin,hdrsi,unspentind,T,&U[unspentind],rmd160,coinaddr,pubkey33),1),unspentind,dstr(U[unspentind].value));
|
|
if ( ramchain->Uextras[unspentind].spentflag == 0 )
|
|
{
|
|
balance += U[unspentind].value;
|
|
if ( array != 0 )
|
|
jaddi(array,iguana_unspentjson(coin,hdrsi,unspentind,T,&U[unspentind],rmd160,coinaddr,pubkey33));
|
|
} else (*spentp) += U[unspentind].value;
|
|
unspentind = U[unspentind].prevunspentind;
|
|
}
|
|
return(balance);
|
|
}
|
|
|
|
int32_t iguana_pkhasharray(struct iguana_info *coin,cJSON *array,int32_t minconf,int32_t maxconf,int64_t *totalp,struct iguana_pkhash *P,int32_t max,uint8_t rmd160[20],char *coinaddr,uint8_t *pubkey33)
|
|
{
|
|
int32_t i,n,m; int64_t spent,balance,netbalance,total; uint32_t lastunspentind; struct iguana_ramchain *ramchain;
|
|
for (total=i=n=0; i<max && i<coin->bundlescount; i++)
|
|
{
|
|
if ( iguana_pkhashfind(coin,&ramchain,&balance,&lastunspentind,&P[n],rmd160,i,i) != 0 )
|
|
{
|
|
if ( (netbalance= iguana_pkhashbalance(coin,array,&spent,&m,ramchain,&P[n],lastunspentind,rmd160,coinaddr,pubkey33,i)) != balance-spent )
|
|
{
|
|
printf("pkhash balance mismatch from m.%d check %.8f vs %.8f spent %.8f [%.8f]\n",m,dstr(netbalance),dstr(balance),dstr(spent),dstr(balance)-dstr(spent));
|
|
}
|
|
else
|
|
{
|
|
//P[n].firstunspentind = lastunspentind;
|
|
total += netbalance;
|
|
n++;
|
|
}
|
|
}
|
|
//printf("%d: balance %.8f, lastunspent.%u\n",i,dstr(balance),lastunspentind);
|
|
}
|
|
//printf("n.%d max.%d\n",n,max);
|
|
*totalp = total;
|
|
return(n);
|
|
}
|
|
|
|
void iguana_unspents(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *array,int32_t minconf,int32_t maxconf,uint8_t *rmdarray,int32_t numrmds)
|
|
{
|
|
int64_t total,sum=0; struct iguana_pkhash *P; uint8_t *addrtypes,*pubkeys; int32_t i,flag = 0; char coinaddr[64];
|
|
if ( rmdarray == 0 )
|
|
rmdarray = iguana_walletrmds(myinfo,coin,&numrmds), flag++;
|
|
addrtypes = &rmdarray[numrmds * 20], pubkeys = &rmdarray[numrmds * 21];
|
|
P = calloc(coin->bundlescount,sizeof(*P));
|
|
for (i=0; i<numrmds; i++)
|
|
{
|
|
bitcoin_address(coinaddr,addrtypes[i],&rmdarray[i * 20],20);
|
|
iguana_pkhasharray(coin,array,minconf,maxconf,&total,P,coin->bundlescount,&rmdarray[i * 20],coinaddr,&pubkeys[33*i]);
|
|
printf("%s %.8f\n",coinaddr,dstr(total));
|
|
sum += total;
|
|
}
|
|
printf("sum %.8f\n",dstr(sum));
|
|
free(P);
|
|
if ( flag != 0 )
|
|
free(rmdarray);
|
|
}
|
|
|
|
uint8_t *iguana_rmdarray(struct iguana_info *coin,int32_t *numrmdsp,cJSON *array,int32_t firsti)
|
|
{
|
|
int32_t i,n,j=0; char *coinaddr; uint8_t *addrtypes,*rmdarray = 0;
|
|
*numrmdsp = 0;
|
|
if ( array != 0 && (n= cJSON_GetArraySize(array)) > 0 )
|
|
{
|
|
*numrmdsp = n - firsti;
|
|
rmdarray = calloc(1,(n-firsti) * 21);
|
|
addrtypes = &rmdarray[(n-firsti) * 20];
|
|
for (i=firsti; i<n; i++)
|
|
{
|
|
if ( (coinaddr= jstr(jitem(array,i),0)) != 0 )
|
|
{
|
|
bitcoin_addr2rmd160(&addrtypes[j],&rmdarray[20 * j],coinaddr);
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
return(rmdarray);
|
|
}
|
|
|
|
int32_t iguana_utxogen(struct iguana_info *coin,struct iguana_bundle *bp)
|
|
{
|
|
static uint64_t total,emitted;
|
|
int32_t spendind,height,n,numtxid,errs=0,emit=0; uint32_t unspentind; struct iguana_bundle *spentbp;
|
|
FILE *fp; char fname[1024],str[65],dirname[128]; int32_t hdrsi,retval = -1;
|
|
bits256 prevhash,zero,sha256; struct iguana_unspent *u; long fsize; struct iguana_txid *nextT;
|
|
struct iguana_spend *S,*s; struct iguana_spendvector *ptr; struct iguana_ramchain *ramchain;
|
|
ramchain = &bp->ramchain;
|
|
//printf("UTXO gen.%d ramchain data.%p\n",bp->bundleheight,ramchain->H.data);
|
|
if ( ramchain->H.data == 0 || (n= ramchain->H.data->numspends) < 1 )
|
|
return(0);
|
|
S = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Soffset);
|
|
nextT = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Toffset);
|
|
numtxid = 1;
|
|
if ( ramchain->Xspendinds != 0 )
|
|
{
|
|
//printf("iguana_utxogen: already have Xspendinds[%d]\n",ramchain->numXspends);
|
|
return(0);
|
|
}
|
|
ptr = mycalloc('x',sizeof(*ptr),n);
|
|
total += n;
|
|
height = bp->bundleheight;
|
|
//printf("start UTXOGEN.%d max.%d ptr.%p\n",bp->bundleheight,n,ptr);
|
|
for (spendind=ramchain->H.data->firsti; spendind<n; spendind++)
|
|
{
|
|
s = &S[spendind];
|
|
if ( spendind == nextT[numtxid].firstvin )
|
|
{
|
|
height = bp->bundleheight + numtxid;
|
|
//printf("height.%d firstvin.%d\n",height,nextT[numtxid].firstvin);
|
|
numtxid++;
|
|
}
|
|
u = 0;
|
|
if ( s->external != 0 && s->prevout >= 0 )
|
|
{
|
|
if ( (spentbp= iguana_spent(coin,&prevhash,&unspentind,ramchain,bp->hdrsi,s)) != 0 )
|
|
{
|
|
if ( (ptr[emit].ind= unspentind) != 0 && spentbp->hdrsi < bp->hdrsi )
|
|
{
|
|
ptr[emit].hdrsi = spentbp->hdrsi;
|
|
ptr[emit].height = height;
|
|
//printf("(%d u%d).%d ",spentbp->hdrsi,unspentind,emit);
|
|
emit++;
|
|
}
|
|
else
|
|
{
|
|
printf("utxogen: null unspentind for spendind.%d hdrsi.%d [%d]\n",spendind,spentbp->hdrsi,bp->hdrsi);
|
|
errs++;
|
|
}
|
|
if ( spentbp == bp )
|
|
{
|
|
char str[65];
|
|
printf("unexpected spendbp: height.%d bp.[%d] U%d <- S%d.[%d] [ext.%d %s prev.%d]\n",height,spentbp->hdrsi,unspentind,spendind,bp->hdrsi,s->external,bits256_str(str,prevhash),s->prevout);
|
|
errs++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errs++;
|
|
printf("utxogen: unresolved spendind.%d hdrsi.%d\n",spendind,bp->hdrsi);
|
|
}
|
|
}
|
|
}
|
|
if ( numtxid != bp->ramchain.H.data->numtxids )
|
|
{
|
|
printf("numtxid.%d != bp %d\n",numtxid,bp->ramchain.H.data->numtxids);
|
|
errs++;
|
|
}
|
|
if ( errs == 0 && emit >= 0 )
|
|
{
|
|
emitted += emit;
|
|
memset(zero.bytes,0,sizeof(zero));
|
|
sprintf(dirname,"DB/%s/spends",coin->symbol);
|
|
vcalc_sha256(0,sha256.bytes,(void *)ptr,(int32_t)(sizeof(*ptr) * emit));
|
|
if ( iguana_peerfname(coin,&hdrsi,dirname,fname,0,bp->hashes[0],zero,bp->n) >= 0 )
|
|
{
|
|
if ( (fp= fopen(fname,"wb")) != 0 )
|
|
{
|
|
if ( fwrite(sha256.bytes,1,sizeof(sha256),fp) != sizeof(sha256) )
|
|
printf("error writing hash for %ld -> (%s)\n",sizeof(*ptr) * emit,fname);
|
|
else if ( fwrite(ptr,sizeof(*ptr),emit,fp) != emit )
|
|
printf("error writing %d of %d -> (%s)\n",emit,n,fname);
|
|
else retval = 0;
|
|
fsize = ftell(fp);
|
|
fclose(fp);
|
|
if ( iguana_Xspendmap(coin,ramchain,bp) < 0 )
|
|
{
|
|
printf("error mapping Xspendmap.(%s)\n",fname);
|
|
retval = -1;
|
|
}
|
|
//int32_t i; for (i=0; i<ramchain->numXspends; i++)
|
|
// printf("(%d u%d) ",ramchain->Xspendinds[i].hdrsi,ramchain->Xspendinds[i].ind);
|
|
//printf("filesize %ld Xspendptr.%p %p num.%d\n",fsize,ramchain->Xspendptr,ramchain->Xspendinds,ramchain->numXspends);
|
|
} else printf("Error creating.(%s)\n",fname);
|
|
} else printf("error getting utxo fname\n");
|
|
}
|
|
if ( ptr != 0 )
|
|
myfree(ptr,sizeof(*ptr) * n);
|
|
printf("utxo %d spendinds.[%d] errs.%d [%.2f%%] emitted.%d %s of %d | ",spendind,bp->hdrsi,errs,100.*(double)emitted/(total+1),emit,mbstr(str,sizeof(*ptr) * emit),n);
|
|
return(-errs);
|
|
}
|
|
|
|
int32_t iguana_balancegen(struct iguana_info *coin,struct iguana_bundle *bp)
|
|
{
|
|
int32_t spendind,n,errs=0,emit=0; uint32_t unspentind,pkind,txidind; struct iguana_account *A2;
|
|
struct iguana_unspent *u,*spentU; struct iguana_spend *S,*s; struct iguana_ramchain *ramchain;
|
|
struct iguana_bundle *spentbp; struct iguana_txid *T,*nextT; int32_t hdrsi;
|
|
uint32_t numtxid,now,h,refheight; struct iguana_utxo *utxo;
|
|
ramchain = &bp->ramchain;
|
|
printf("BALANCEGEN.%d\n",bp->bundleheight);
|
|
if ( ramchain->H.data == 0 || (n= ramchain->H.data->numspends) < 1 )
|
|
return(0);
|
|
S = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Soffset);
|
|
nextT = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Toffset);
|
|
numtxid = 1;
|
|
refheight = bp->bundleheight;
|
|
if ( ramchain->Xspendinds == 0 )
|
|
{
|
|
printf("iguana_balancegen.%d: no Xspendinds[%d]\n",bp->hdrsi,ramchain->numXspends);
|
|
return(0);
|
|
}
|
|
for (spendind=ramchain->H.data->firsti; spendind<n; spendind++)
|
|
{
|
|
if ( spendind == nextT[numtxid].firstvin )
|
|
{
|
|
refheight = bp->bundleheight + numtxid;
|
|
//printf("height.%d firstvin.%d\n",height,nextT[numtxid].firstvin);
|
|
numtxid++;
|
|
}
|
|
s = &S[spendind];
|
|
u = 0;
|
|
unspentind = 0;
|
|
hdrsi = -1;
|
|
if ( s->external != 0 && s->prevout >= 0 )
|
|
{
|
|
if ( emit >= ramchain->numXspends )
|
|
errs++;
|
|
else
|
|
{
|
|
h = ramchain->Xspendinds[emit].height;
|
|
unspentind = ramchain->Xspendinds[emit].ind;
|
|
if ( (hdrsi= ramchain->Xspendinds[emit].hdrsi) >= 0 && hdrsi <= bp->hdrsi )
|
|
spentbp = coin->bundles[hdrsi];
|
|
else
|
|
{
|
|
printf("iguana_balancegen[%d] s.%d illegal hdrsi.%d emit.%d\n",bp->hdrsi,spendind,hdrsi,emit);
|
|
errs++;
|
|
}
|
|
//printf("%d of %d: [%d] X spendind.%d -> (%d u%d)\n",emit,ramchain->numXspends,bp->hdrsi,spendind,hdrsi,unspentind);
|
|
emit++;
|
|
}
|
|
}
|
|
else if ( s->prevout >= 0 )
|
|
{
|
|
spentbp = bp;
|
|
hdrsi = bp->hdrsi;
|
|
h = refheight;
|
|
if ( (txidind= s->spendtxidind) != 0 && txidind < spentbp->ramchain.H.data->numtxids )
|
|
{
|
|
T = (void *)(long)((long)spentbp->ramchain.H.data + spentbp->ramchain.H.data->Toffset);
|
|
unspentind = T[txidind].firstvout + s->prevout;
|
|
if ( unspentind == 0 || unspentind >= spentbp->ramchain.H.data->numunspents )
|
|
{
|
|
printf("iguana_balancegen unspentind overflow %u vs %u\n",unspentind,spentbp->ramchain.H.data->numunspents);
|
|
errs++;
|
|
}
|
|
//printf("txidind.%d 1st.%d prevout.%d\n",txidind,T[txidind].firstvout,s->prevout);
|
|
}
|
|
else
|
|
{
|
|
printf("iguana_balancegen txidind overflow %u vs %u\n",txidind,spentbp->ramchain.H.data->numtxids);
|
|
errs++;
|
|
}
|
|
//printf("[%d] spendind.%d -> (hdrsi.%d u%d)\n",bp->hdrsi,spendind,hdrsi,unspentind);
|
|
}
|
|
else continue;
|
|
now = (uint32_t)time(NULL);
|
|
if ( unspentind > 0 && unspentind < spentbp->ramchain.H.data->numunspents )
|
|
{
|
|
if ( spentbp->ramchain.Uextras == 0 )
|
|
{
|
|
spentbp->ramchain.Uextras = calloc(sizeof(*spentbp->ramchain.Uextras),spentbp->ramchain.H.data->numunspents + 16);
|
|
}
|
|
if ( spentbp->ramchain.A == 0 )
|
|
{
|
|
spentbp->ramchain.A = calloc(sizeof(*spentbp->ramchain.A),spentbp->ramchain.H.data->numpkinds + 16);
|
|
}
|
|
if ( spentbp->ramchain.Uextras == 0 || (A2= spentbp->ramchain.A) == 0 )
|
|
{
|
|
printf("null ptrs %p %p\n",spentbp->ramchain.Uextras,spentbp->ramchain.A);
|
|
errs++;
|
|
}
|
|
else
|
|
{
|
|
spentU = (void *)(long)((long)spentbp->ramchain.H.data + spentbp->ramchain.H.data->Uoffset);
|
|
u = &spentU[unspentind];
|
|
if ( (pkind= u->pkind) != 0 && pkind < spentbp->ramchain.H.data->numpkinds )
|
|
{
|
|
utxo = &spentbp->ramchain.Uextras[unspentind];
|
|
if ( utxo->spentflag == 0 )
|
|
{
|
|
utxo->prevspendind = A2[pkind].lastind;
|
|
utxo->spentflag = 1;
|
|
utxo->height = h;
|
|
A2[pkind].total += u->value;
|
|
A2[pkind].lastind = spendind;
|
|
spentbp->dirty = now;
|
|
}
|
|
else
|
|
{
|
|
errs++;
|
|
printf("iguana_balancegen: pkind.%d double spend of hdrsi.%d unspentind.%d prev.%u spentflag.%d height.%d\n",pkind,spentbp->hdrsi,unspentind,utxo->prevspendind,utxo->spentflag,utxo->height);
|
|
getchar();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errs++;
|
|
printf("iguana_balancegen: pkind overflow %d vs %d\n",pkind,spentbp->ramchain.H.data->numpkinds);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errs++;
|
|
printf("iguana_balancegen: error with unspentind.%d vs max.%d\n",unspentind,spentbp->ramchain.H.data->numunspents);
|
|
}
|
|
}
|
|
if ( numtxid != bp->ramchain.H.data->numtxids )
|
|
{
|
|
printf("iguana_balancegen: numtxid.%d != bp %d\n",numtxid,bp->ramchain.H.data->numtxids);
|
|
errs++;
|
|
}
|
|
if ( emit != ramchain->numXspends )
|
|
{
|
|
printf("iguana_balancegen: emit %d != %d ramchain->numXspends\n",emit,ramchain->numXspends);
|
|
errs++;
|
|
}
|
|
printf(">>>>>>>> balances.%d done errs.%d spendind.%d\n",bp->hdrsi,errs,n);
|
|
if ( errs == 0 )
|
|
bp->validated = (uint32_t)time(NULL);
|
|
return(-errs);
|
|
}
|
|
|
|
int32_t iguana_bundlevalidate(struct iguana_info *coin,struct iguana_bundle *bp)
|
|
{
|
|
bp->validated = (uint32_t)time(NULL);
|
|
printf("VALIDATE.%d %u\n",bp->bundleheight,bp->validated);
|
|
return(0);
|
|
}
|