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.
 
 
 
 
 
 

672 lines
28 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"
int32_t iguana_alloctxbits(struct iguana_info *coin,struct iguana_ramchain *ramchain)
{
static int64_t total; struct iguana_ramchaindata *rdata;
if ( 0 && ramchain->txbits == 0 && (rdata= ramchain->H.data) != 0 )
{
int32_t tlen; uint8_t *TXbits;
TXbits = RAMCHAIN_PTR(rdata,TXoffset);
//TXbits = (uint8_t *)((long)rdata + rdata->TXoffset);
tlen = (int32_t)hconv_bitlen(rdata->numtxsparse * rdata->txsparsebits);
ramchain->txbits = calloc(1,tlen);
memcpy(ramchain->txbits,TXbits,tlen);
total += tlen;
char str[65]; printf("%s alloc.[%d] txbits.%p[%d] total %s\n",coin->symbol,rdata->height/coin->chain->bundlesize,ramchain->txbits,tlen,mbstr(str,total));
return(tlen);
}
return(-1);
}
int32_t iguana_alloccacheT(struct iguana_info *coin,struct iguana_ramchain *ramchain)
{
static int64_t total; struct iguana_ramchaindata *rdata;
if ( ramchain->cacheT == 0 && (rdata= ramchain->H.data) != 0 )
{
int32_t i,tlen; struct iguana_txid *T;
T = RAMCHAIN_PTR(rdata,Toffset);
//T = (void *)((long)rdata + rdata->Toffset);
tlen = sizeof(*T) * rdata->numtxids;
if ( (ramchain->cacheT= calloc(1,tlen)) != 0 )
{
//memcpy(ramchain->cacheT,T,tlen);
for (i=0; i<rdata->numtxids; i++)
ramchain->cacheT[i] = T[i];
} else ramchain->cacheT = T;
total += tlen;
char str[65]; printf("alloc.[%d] cacheT.%p[%d] total %s\n",rdata->height/coin->chain->bundlesize,ramchain->cacheT,tlen,mbstr(str,total));
return(tlen);
}
return(-1);
}
uint32_t iguana_sparseadd(uint8_t *bits,uint32_t ind,int32_t width,uint32_t tablesize,uint8_t *key,int32_t keylen,uint32_t setind,void *refdata,int32_t refsize,struct iguana_ramchain *ramchain,uint32_t maxitems)
{
static uint8_t masks[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
struct iguana_ramchaindata *rdata;
int32_t i,j,x,n,modval; int64_t bitoffset; uint8_t *ptr; uint32_t *table,retval = 0;
if ( tablesize == 0 )
{
printf("iguana_sparseadd tablesize zero illegal\n");
return(0);
}
if ( 0 && setind == 0 )
{
char str[65];
for (i=n=0; i<tablesize; i++)
{
bitoffset = (i * width);
ptr = &bits[bitoffset >> 3];
modval = (bitoffset & 7);
for (x=j=0; j<width; j++,modval++)
{
if ( modval >= 8 )
ptr++, modval = 0;
x <<= 1;
x |= (*ptr & masks[modval]) >> modval;
}
if ( x != 0 )
printf("%s ",bits256_str(str,*(bits256 *)(refdata + x*refsize))), n++;
}
printf("tableentries.%d\n",n);
}
//if ( setind == 0 )
// ramchain->sparsesearches++;
//else ramchain->sparseadds++;
if ( 0 && (rdata= ramchain->H.data) != 0 && (ramchain->sparsesearches % 1000000) == 0 )
printf("[%3d] %7d.[%-2d %8d] %5.3f adds.(%-10ld %10ld) search.(hits.%-10ld %10ld) %5.2f%% max.%ld\n",ramchain->height/rdata->numblocks,ramchain->height,width,tablesize,(double)(ramchain->sparseadditers + ramchain->sparsesearchiters)/(1+ramchain->sparsesearches+ramchain->sparseadds),ramchain->sparseadds,ramchain->sparseadditers,ramchain->sparsehits,ramchain->sparsesearches,100.*(double)ramchain->sparsehits/(1+ramchain->sparsesearches),ramchain->sparsemax+1);
if ( width == 32 )
{
table = (uint32_t *)bits;
for (i=0; i<tablesize; i++,ind++)
{
if ( ind >= tablesize )
ind = 0;
if ( (x= table[ind]) == 0 )
{
//if ( ++i > ramchain->sparsemax )
// ramchain->sparsemax = i;
if ( (retval= setind) != 0 )
{
//ramchain->sparseadditers += i;
table[ind] = setind;
} //else ramchain->sparsesearchiters += i;
return(setind);
}
else if ( x < maxitems && memcmp((void *)(long)((long)refdata + x*refsize),key,keylen) == 0 )
{
if ( setind != 0 && setind != x )
printf("sparseadd index collision setind.%d != x.%d refsize.%d keylen.%d\n",setind,x,refsize,keylen);
//ramchain->sparsehits++;
//if ( ++i > ramchain->sparsemax )
// ramchain->sparsemax = i;
//ramchain->sparseadditers += i;
return(x);
}
}
}
else
{
bitoffset = (ind * width);
if ( 0 && setind == 0 )
printf("tablesize.%d width.%d bitoffset.%d\n",tablesize,width,(int32_t)bitoffset);
for (i=0; i<tablesize; i++,ind++,bitoffset+=width)
{
if ( ind >= tablesize )
{
ind = 0;
bitoffset = 0;
}
x = 0;
if ( width == 32 )
memcpy(&x,&bits[bitoffset >> 3],4);
else if ( width == 16 )
memcpy(&x,&bits[bitoffset >> 3],2);
else if ( width != 8 )
{
ptr = &bits[bitoffset >> 3];
modval = (bitoffset & 7);
if ( 0 && setind == 0 )
printf("tablesize.%d width.%d bitoffset.%d modval.%d i.%d\n",tablesize,width,(int32_t)bitoffset,modval,i);
for (x=j=0; j<width; j++,modval++)
{
if ( modval >= 8 )
ptr++, modval = 0;
x <<= 1;
x |= (*ptr & masks[modval]) >> modval;
}
}
else x = bits[bitoffset >> 3];
if ( 0 && setind == 0 )
printf("x.%d\n",x);
if ( x == 0 )
{
if ( (x= setind) == 0 )
{
//ramchain->sparsesearchiters += (i+1);
return(0);
}
//else ramchain->sparseadditers += (i+1);
if ( width == 32 )
memcpy(&bits[bitoffset >> 3],&setind,4);
else if ( width == 16 )
memcpy(&bits[bitoffset >> 3],&setind,2);
else if ( width != 8 )
{
ptr = &bits[(bitoffset+width-1) >> 3];
modval = ((bitoffset+width-1) & 7);
for (j=0; j<width; j++,x>>=1,modval--)
{
if ( modval < 0 )
ptr--, modval = 7;
if ( (x & 1) != 0 )
*ptr |= masks[modval];
}
}
else bits[bitoffset >> 3] = setind;
if ( 0 )
{
for (x=j=0; j<width; j++)
{
x <<= 1;
x |= GETBIT(bits,bitoffset+width-1-j) != 0;
}
//if ( x != setind )
printf("x.%u vs setind.%d ind.%d bitoffset.%d, width.%d\n",x,setind,ind,(int32_t)bitoffset,width);
}
//if ( i > ramchain->sparsemax )
// ramchain->sparsemax = i;
return(setind);
}
else if ( x < maxitems && memcmp((void *)(long)((long)refdata + x*refsize),key,keylen) == 0 )
{
if ( setind == 0 )
ramchain->sparsehits++;
else if ( setind != x )
printf("sparseadd index collision setind.%d != x.%d refsize.%d keylen.%d\n",setind,x,refsize,keylen);
if ( i > ramchain->sparsemax )
ramchain->sparsemax = i;
return(x);
}
}
}
return(0);
}
uint32_t iguana_sparseaddtx(uint8_t *bits,int32_t width,uint32_t tablesize,bits256 txid,struct iguana_txid *T,uint32_t txidind,struct iguana_ramchain *ramchain)
{
uint32_t ind,retval=0; struct iguana_ramchaindata *rdata = ramchain->H.data;
//char str[65]; printf("sparseaddtx %s txidind.%d bits.%p\n",bits256_str(str,txid),txidind,bits);
ind = (txid.ulongs[0] ^ txid.ulongs[1] ^ txid.ulongs[2] ^ txid.ulongs[3]) % tablesize;
if ( rdata != 0 && (retval= iguana_sparseadd(bits,ind,width,tablesize,txid.bytes,sizeof(txid),txidind,T,sizeof(*T),ramchain,rdata->numtxids)) != 0 )
{
char str[65];
if ( txidind != 0 && retval != txidind )
printf("sparse tx collision %s %u vs %u\n",bits256_str(str,txid),retval,txidind);
return(retval);
}
return(retval);
}
uint32_t iguana_sparseaddpk(uint8_t *bits,int32_t width,uint32_t tablesize,uint8_t rmd160[20],struct iguana_pkhash *P,uint32_t pkind,struct iguana_ramchain *ramchain)
{
uint32_t ind,key2; uint64_t key0,key1; struct iguana_ramchaindata *rdata;
if ( (rdata= ramchain->H.data) != 0 )
{
//int32_t i; for (i=0; i<20; i++)
// printf("%02x",rmd160[i]);
//char str[65]; printf(" sparseaddpk pkind.%d bits.%p\n",pkind,bits);
memcpy(&key0,rmd160,sizeof(key0));
memcpy(&key1,&rmd160[sizeof(key0)],sizeof(key1));
memcpy(&key2,&rmd160[sizeof(key0) + sizeof(key1)],sizeof(key2));
ind = (key0 ^ key1 ^ key2) % tablesize;
return(iguana_sparseadd(bits,ind,width,tablesize,rmd160,20,pkind,P,sizeof(*P),ramchain,rdata->numpkinds));
} else return(0);
}
int32_t iguana_ramchain_spendtxid(struct iguana_info *coin,uint32_t *unspentindp,bits256 *txidp,struct iguana_txid *T,int32_t numtxids,bits256 *X,int32_t numexternaltxids,struct iguana_spend *s)
{
uint32_t ind,external;
*unspentindp = 0;
memset(txidp,0,sizeof(*txidp));
ind = s->spendtxidind;
external = (ind >> 31) & 1;
ind &= ~(1 << 31);
//printf("s.%p ramchaintxid vout.%x spendtxidind.%d isext.%d ext.%d ind.%d\n",s,s->prevout,ind,s->external,external,ind);
if ( s->prevout < 0 )
return(-1);
if ( s->external != 0 && s->external == external && ind < numexternaltxids )
{
//printf("ind.%d X.%p[%d]\n",ind,X,numexternaltxids);
*txidp = X[ind];
return(s->prevout);
}
else if ( s->external == 0 && s->external == external && ind < numtxids )
{
*txidp = T[ind].txid;
*unspentindp = T[ind].firstvout + s->prevout;
return(s->prevout);
}
return(-2);
}
struct iguana_txid *iguana_txidfind(struct iguana_info *coin,int32_t *heightp,struct iguana_txid *tx,bits256 txid,int32_t lasthdrsi)
{
uint8_t *TXbits; struct iguana_txid *T; uint32_t txidind; int32_t i;
struct iguana_bundle *bp; struct iguana_ramchain *ramchain; struct iguana_ramchaindata *rdata; //struct iguana_block *block;
*heightp = -1;
memset(tx,0,sizeof(*tx));
if ( lasthdrsi < 0 )
return(0);
for (i=lasthdrsi; i>=0; i--)
{
if ( (bp= coin->bundles[i]) != 0 && (bp == coin->current || bp->emitfinish > 1) )
{
ramchain = &bp->ramchain;//(bp == coin->current) ? &coin->RTramchain : &bp->ramchain;
if ( (rdata= ramchain->H.data) != 0 )
{
if ( (TXbits= ramchain->txbits) == 0 )
{
if ( coin->fastfind == 0 && bp != coin->current )
iguana_alloctxbits(coin,ramchain);
if ( (TXbits= ramchain->txbits) == 0 )
{
//printf("use memory mapped.[%d]\n",rdata->height/coin->chain->bundlesize);
TXbits = RAMCHAIN_PTR(rdata,TXoffset);
//TXbits = (void *)(long)((long)rdata + rdata->TXoffset);
}
}
if ( (T= ramchain->cacheT) == 0 )
{
//if ( coin->fastfind == 0 )
// iguana_alloccacheT(coin,ramchain);
//if ( (T= ramchain->cacheT) == 0 )
T = RAMCHAIN_PTR(rdata,Toffset);
//T = (void *)(long)((long)rdata + rdata->Toffset);
}
if ( (txidind= iguana_sparseaddtx(TXbits,rdata->txsparsebits,rdata->numtxsparse,txid,T,0,ramchain)) > 0 )
{
//printf("found txidind.%d\n",txidind);
if ( bits256_cmp(txid,T[txidind].txid) == 0 )
{
if ( 0 )
{
int32_t j; struct iguana_block *block;
for (j=0; j<bp->n; j++)
if ( (block= bp->blocks[j]) != 0 && txidind >= block->RO.firsttxidind && txidind < block->RO.firsttxidind+block->RO.txn_count )
break;
if ( j < bp->n )
{
if ( j != T[txidind].bundlei )
printf("bundlei mismatch j.%d != %d\n",j,T[txidind].bundlei);
else
{
*heightp = bp->bundleheight + T[txidind].bundlei;
//printf("found height.%d\n",*heightp);
*tx = T[txidind];
return(tx);
}
}
}
else
{
*heightp = bp->bundleheight + T[txidind].bundlei;
//printf("found height.%d\n",*heightp);
*tx = T[txidind];
//printf("[%d] txidind.%d 1st.(%d %d)\n",bp->hdrsi,txidind,tx->firstvout,tx->firstvin);
return(tx);
}
}
char str[65],str2[65]; printf("iguana_txidfind mismatch.[%d:%d] %d %s vs %s\n",bp->hdrsi,T[txidind].extraoffset,txidind,bits256_str(str,txid),bits256_str(str2,T[txidind].txid));
return(0);
}
}
}
}
return(0);
}
int32_t iguana_txidfastfind(struct iguana_info *coin,int32_t *heightp,bits256 txid,int32_t lasthdrsi)
{
uint8_t *sorted,*item; int32_t i,j,val,num,tablesize,*hashtable; uint32_t firstvout;
if ( (sorted= coin->fast[txid.bytes[31]]) != 0 )
{
memcpy(&num,sorted,sizeof(num));
memcpy(&tablesize,&sorted[sizeof(num)],sizeof(tablesize));
if ( (hashtable= coin->fasttables[txid.bytes[31]]) == 0 )
{
hashtable = (int32_t *)((long)sorted + (1 + num)*16);
//printf("backup hashtable\n");
}
val = (txid.uints[4] % tablesize);
for (j=0; j<tablesize; j++,val++)
{
if ( val >= tablesize )
val = 0;
if ( (i= hashtable[val]) == 0 )
return(-1);
else
{
if ( i > num )
{
printf("illegal val.%d vs num.%d tablesize.%d fastfind.%02x\n",i,num,tablesize,txid.bytes[31]);
return(-1);
}
else
{
item = (void *)((long)sorted + i*16);
if ( memcmp(&txid.txid,item,sizeof(uint64_t)) == 0 )
{
memcpy(&firstvout,&item[sizeof(uint64_t)],sizeof(firstvout));
memcpy(heightp,&item[sizeof(uint64_t) + sizeof(firstvout)],sizeof(*heightp));
//printf("i.%d val.%d height.%d firstvout.%d j.%d\n",i,val,*heightp,firstvout,j);
if ( *heightp >= (lasthdrsi+1)*coin->chain->bundlesize )
{
printf("txidfastfind: unexpected height.%d with lasthdrsi.%d\n",*heightp,lasthdrsi);
return(-1);
}
return(firstvout);
}
else if ( 0 )
{
int32_t k;
for (k=-16; k<0; k++)
printf("%02x ",item[k]);
printf("<");
for (k=0; k<16; k++)
printf("%02x ",item[k]);
printf(">");
for (k=16; k<32; k++)
printf("%02x ",item[k]);
printf("\n");
printf("txid.%llx vs item.%llx ht.%d 1st.%d\n",(long long)txid.txid,*(long long *)item,*(int32_t *)&item[sizeof(uint64_t)],*(int32_t *)&item[sizeof(uint64_t)+sizeof(uint32_t)]);
}
}
}
}
}
return(-1);
}
int32_t iguana_fastfindadd(struct iguana_info *coin,bits256 txid,int32_t height,uint32_t firstvout)
{
FILE *fp;
if ( bits256_nonz(txid) != 0 && (fp= coin->fastfps[txid.bytes[31]]) != 0 )
{
txid.uints[6] = firstvout;
txid.uints[7] = height;
if ( fwrite(&txid,1,sizeof(txid),fp) == sizeof(txid) )
return(1);
}
return(0);
}
int64_t iguana_fastfindinitbundle(struct iguana_info *coin,struct iguana_bundle *bp,int32_t iter)
{
int32_t i; struct iguana_txid *T; struct iguana_ramchaindata *rdata; int64_t n = 0;
if ( (rdata= bp->ramchain.H.data) != 0 )
{
T = RAMCHAIN_PTR(rdata,Toffset);
//T = (void *)(long)((long)rdata + rdata->Toffset);
n = rdata->numtxids;
if ( iter == 1 )
{
for (i=0; i<n; i++)
iguana_fastfindadd(coin,T[i].txid,bp->bundleheight + T[i].bundlei,T[i].firstvout);
fprintf(stderr,"[%d:%u] ",bp->hdrsi,(int32_t)n);
}
}
return(n);
}
static int _bignum_cmp(const void *a,const void *b)
{
uint8_t *biga,*bigb; int32_t i,diff;
biga = (uint8_t *)a;
bigb = (uint8_t *)b;
for (i=0; i<32; i++)
{
if ( (diff= (biga[i] - bigb[i])) > 0 )
return(1);
else if ( diff < 0 )
return(-1);
}
return(0);
}
uint32_t iguana_fastfindinit(struct iguana_info *coin)
{
int32_t i,j,iter,num,tablesize,*hashtable; uint8_t *sorted; char fname[1024];
//if ( strcmp("BTC",coin->symbol) != 0 )
// return(0);
if ( coin->fastfind != 0 )
return(coin->fastfind);
for (iter=0; iter<2; iter++)
{
for (i=0; i<0x100; i++)
{
sprintf(fname,"DB/%s%s/fastfind/%02x.all",iter!=0?"ro/":"",coin->symbol,i), OS_compatible_path(fname);
if ( (coin->fast[i]= OS_mapfile(fname,&coin->fastsizes[i],0)) == 0 )
break;
else
{
fprintf(stderr,".");
sorted = coin->fast[i];
if ( 0 )
{
coin->fast[i] = calloc(1,coin->fastsizes[i]);
memcpy(coin->fast[i],sorted,coin->fastsizes[i]);
munmap(sorted,coin->fastsizes[i]);
}
sorted = coin->fast[i];
memcpy(&num,sorted,sizeof(num));
memcpy(&tablesize,&sorted[sizeof(num)],sizeof(tablesize));
if ( (num+1)*16 + tablesize*sizeof(*hashtable) == coin->fastsizes[i] )
{
hashtable = (int32_t *)((long)sorted + (1 + num)*16);
if ( 0 )
{
coin->fasttables[i] = calloc(tablesize,sizeof(*hashtable));
memcpy(coin->fasttables[i],hashtable,tablesize * sizeof(*hashtable));
}
}
else
{
printf("size error num.%d tablesize.%d -> %u vs %ld\n",num,tablesize,(int32_t)((num+1)*16 + tablesize*sizeof(*hashtable)),coin->fastsizes[i]);
break;
}
}
}
if ( i == 0x100 )
{
coin->fastfind = (uint32_t)time(NULL);
printf("initialized fastfind.%s iter.%d\n",coin->symbol,iter);
return(coin->fastfind);
}
else
{
for (j=0; j<i; j++)
{
munmap(coin->fast[i],coin->fastsizes[i]);
free(coin->fasttables[i]);
coin->fast[i] = 0;
coin->fastsizes[i] = 0;
}
}
}
return(0);
}
int64_t iguana_fastfindcreate(struct iguana_info *coin)
{
int32_t i,j,val,iter,errs,num,ind,tablesize,*hashtable; bits256 *sortbuf,hash2; long allocsize; struct iguana_bundle *bp; char fname[512]; uint8_t buf[16]; int64_t total = 0;
if ( coin->current != 0 && coin->bundlescount == coin->current->hdrsi+1 )
{
sprintf(fname,"DB/%s/fastfind",coin->symbol), OS_ensure_directory(fname);
for (i=0; i<0x100; i++)
{
sprintf(fname,"DB/%s/fastfind/%02x",coin->symbol,i), OS_compatible_path(fname);
if ( (coin->fastfps[i]= fopen(fname,"wb")) == 0 )
break;
}
if ( i == 0x100 )
{
for (iter=0; iter<2; iter++)
{
total = 0;
for (i=0; i<coin->bundlescount-1; i++)
if ( (bp= coin->bundles[i]) != 0 )
total += iguana_fastfindinitbundle(coin,bp,iter);
printf("iguana_fastfindinit iter.%d total.%lld\n",iter,(long long)total);
}
for (i=errs=0; i<0x100; i++)
{
fclose(coin->fastfps[i]), coin->fastfps[i] = 0;
sprintf(fname,"DB/%s/fastfind/%02x",coin->symbol,i), OS_compatible_path(fname);
//printf("%s\n",fname);
if ( (sortbuf= OS_filestr(&allocsize,fname)) != 0 )
{
OS_removefile(fname,0);
num = (int32_t)allocsize/sizeof(bits256);
qsort(sortbuf,num,sizeof(bits256),_bignum_cmp);
strcat(fname,".all");
if ( (coin->fastfps[i]= fopen(fname,"wb")) != 0 )
{
tablesize = (num << 1);
hashtable = calloc(sizeof(*hashtable),tablesize);
for (ind=1; ind<=num; ind++)
{
hash2 = sortbuf[ind-1];
val = (hash2.uints[4] % tablesize);
for (j=0; j<tablesize; j++,val++)
{
if ( val >= tablesize )
val = 0;
if ( hashtable[val] == 0 )
{
hashtable[val] = ind;
break;
}
}
}
memset(&hash2,0,sizeof(hash2));
hash2.uints[0] = num;
hash2.uints[1] = tablesize;
for (j=0; j<=num; j++)
{
memcpy(buf,&hash2.txid,sizeof(hash2.txid));
memcpy(&buf[sizeof(hash2.txid)],&hash2.uints[6],sizeof(hash2.uints[6]));
memcpy(&buf[sizeof(hash2.txid) + sizeof(hash2.uints[6])],&hash2.uints[7],sizeof(hash2.uints[7]));
fwrite(buf,1,sizeof(buf),coin->fastfps[i]);
//fwrite(hash2,1,sizeof(hash2),coin->fastfps[i]);
if ( j < num )
{
hash2 = sortbuf[j];
//char str[65]; printf("%d %s\n",j,bits256_str(str,hash2));
}
}
if ( fwrite(hashtable,sizeof(*hashtable),tablesize,coin->fastfps[i]) == tablesize )
{
fclose(coin->fastfps[i]), coin->fastfps[i] = 0;
if ( (coin->fast[i]= OS_mapfile(fname,&coin->fastsizes[i],0)) != 0 )
{
} else errs++;
printf("%s fastfind.[%02x] num.%d tablesize.%d errs.%d %p[%ld]\n",fname,i,num,tablesize,errs,coin->fast[i],coin->fastsizes[i]);
}
else
{
printf("error saving (%s)\n",fname);
OS_removefile(fname,0);
fclose(coin->fastfps[i]), coin->fastfps[i] = 0;
}
free(hashtable);
} else printf("couldnt overwrite (%s)\n",fname);
free(sortbuf);
} else printf("couldnt load sortbuf (%s)\n",fname);
}
printf("initialized with errs.%d\n",errs);
if ( errs == 0 )
coin->fastfind = (uint32_t)time(NULL);
}
}
return(total);
}
struct iguana_monitorinfo *iguana_monitorfind(struct iguana_info *coin,bits256 txid)
{
int32_t i;
for (i=0; i<sizeof(coin->monitoring)/sizeof(*coin->monitoring); i++)
if ( bits256_cmp(coin->monitoring[i].txid,txid) == 0 )
return(&coin->monitoring[i]);
return(0);
}
struct iguana_monitorinfo *iguana_txidreport(struct iguana_info *coin,bits256 txid,struct iguana_peer *addr)
{
struct iguana_monitorinfo *ptr; char str[65];
if ( (ptr= iguana_monitorfind(coin,txid)) != 0 )
{
if ( GETBIT(ptr->peerbits,addr->addrind) == 0 )
{
char str[65]; printf("%s reports %s\n",addr->ipaddr,bits256_str(str,txid));
SETBIT(ptr->peerbits,addr->addrind);
ptr->numreported++;
}
} else printf("txid.%s not being monitored\n",bits256_str(str,txid));
return(0);
}
struct iguana_monitorinfo *iguana_txidmonitor(struct iguana_info *coin,bits256 txid)
{
int32_t i; struct iguana_monitorinfo *ptr;
if ( (ptr= iguana_monitorfind(coin,txid)) == 0 )
{
for (i=0; i<sizeof(coin->monitoring)/sizeof(*coin->monitoring); i++)
if ( bits256_nonz(coin->monitoring[i].txid) == 0 )
{
memset(&coin->monitoring[i],0,sizeof(coin->monitoring[i]));
coin->monitoring[i].txid = txid;
return(ptr);
}
}
printf("no monitoring slots left\n");
return(0);
}
double iguana_txidstatus(struct iguana_info *coin,bits256 txid)
{
int32_t height,firstvout,numranked; struct iguana_monitorinfo *ptr; char str[65];
if ( coin != 0 && coin->peers != 0 && (numranked= coin->peers->numranked) > 0 )
{
if ( (firstvout= iguana_unspentindfind(coin,0,0,0,0,&height,txid,0,coin->bundlescount-1)) != 0 )
{
if ( (ptr= iguana_monitorfind(coin,txid)) != 0 )
memset(ptr,0,sizeof(*ptr));
return((double)coin->longestchain - height);
}
if ( (ptr= iguana_monitorfind(coin,txid)) != 0 )
return((double)ptr->numreported / numranked);
else
{
printf("iguana_txidstatus: unexpected missing %s %s\n",coin->symbol,bits256_str(str,txid));
iguana_txidmonitor(coin,txid);
}
}
return(0.);
}