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.
676 lines
28 KiB
676 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;
|
|
if ( tablesize > 0 )
|
|
{
|
|
//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 && tablesize > 0 )
|
|
{
|
|
//int32_t i; for (i=0; i<20; i++)
|
|
// printf("%02x",rmd160[i]);
|
|
//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 supernet_info *myinfo,struct iguana_info *coin,bits256 txid)
|
|
{
|
|
struct iguana_outpoint outpt; int32_t height,firstvout,numranked; struct iguana_monitorinfo *ptr; char str[65];
|
|
if ( coin != 0 && coin->peers != 0 && (numranked= coin->peers->numranked) > 0 )
|
|
{
|
|
if ( iguana_RTunspentindfind(myinfo,coin,&outpt,0,0,0,0,&height,txid,0,coin->bundlescount-1,0) == 0 )
|
|
{
|
|
firstvout = outpt.unspentind;
|
|
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.);
|
|
}
|
|
|
|
|