/******************************************************************************
* Copyright © 2014 - 2017 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 * ) ( ( long ) 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 ) ;
}
// fadedreamz@gmail.com
# if defined(_M_X64)
/*
* calculate the address in a portable manner
* in all platform sizeof ( char ) / sizeof ( uchar ) = = 1
* @ author - fadedreamz @ gmail . com
*/
else if ( x < maxitems & & memcmp ( ( void * ) ( ( unsigned char * ) refdata + x * refsize ) , key , keylen ) = = 0 )
# else
else if ( x < maxitems & & memcmp ( ( void * ) ( long ) ( ( long ) refdata + x * refsize ) , key , keylen ) = = 0 )
# endif
{
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 != %u \n " , j , ( uint32_t ) 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:%u] %d %s vs %s \n " , bp - > hdrsi , ( uint32_t ) 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 ( 0 ) ;
else
{
if ( i > num )
{
printf ( " illegal val.%d vs num.%d tablesize.%d fastfind.%02x \n " , i , num , tablesize , txid . bytes [ 31 ] ) ;
return ( 0 ) ;
}
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 ( 0 ) ;
}
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 ( 0 ) ;
}
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 ) ;
}
int32_t iguana_fastfindreset ( struct iguana_info * coin )
{
int32_t i , n = 0 ;
for ( i = 0 ; i < 0x100 ; i + + )
{
if ( coin - > fast [ i ] ! = 0 )
munmap ( coin - > fast [ i ] , coin - > fastsizes [ i ] ) , n + + ;
if ( coin - > fasttables [ i ] ! = 0 )
free ( coin - > fasttables [ i ] ) ;
coin - > fast [ i ] = 0 ;
coin - > fastsizes [ i ] = 0 ;
coin - > fasttables [ i ] = 0 ;
}
coin - > fastfind = 0 ;
return ( n ) ;
}
uint32_t iguana_fastfindinit ( struct iguana_info * coin )
{
int32_t i , 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 iguana_fastfindreset ( coin ) ;
}
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("%s txid.%s not being monitored\n",coin->symbol,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. ) ;
}