/******************************************************************************
* 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 "exchanges777.h"
# include "secp256k1/include/secp256k1.h"
# include "secp256k1/include/secp256k1_schnorr.h"
# include "secp256k1/include/secp256k1_rangeproof.h"
const char * Hardcoded_coins [ ] [ 3 ] = { { " BTC " , " bitcoin " , " 0 " } , { " BTCD " , " BitcoinDark " , " 129 " } , { " VPN " , " VPNcoin " , " 129 " } , { " LTC " , " litecoin " , " 129 " } , { " endmarker " , " " , " " } } ;
struct iguana_info * iguana_coinfind ( char * symbol )
{
struct iguana_info * coin = 0 ; uint32_t symbolcrc ; struct supernet_info * myinfo = SuperNET_MYINFO ( 0 ) ;
while ( myinfo - > allcoins_being_added ! = 0 )
{
sleep ( 3 ) ;
if ( myinfo - > allcoins_being_added ! = 0 )
printf ( " wait for coinadd to complete, OK if rare \n " ) ;
sleep ( 3 ) ;
}
symbolcrc = calc_crc32 ( 0 , symbol , ( int32_t ) strlen ( symbol ) ) ;
//portable_mutex_lock(&myinfo->allcoins_mutex);
HASH_FIND ( hh , myinfo - > allcoins , & symbolcrc , sizeof ( coin - > symbolcrc ) , coin ) ;
//portable_mutex_unlock(&myinfo->allcoins_mutex);
return ( coin ) ;
}
struct iguana_info * iguana_coinadd ( char * symbol , char * name , cJSON * argjson , int32_t virtcoin )
{
struct iguana_info * coin ; uint32_t symbolcrc ; char * privatechain ; int32_t j ; struct supernet_info * myinfo = SuperNET_MYINFO ( 0 ) ;
if ( ( coin = iguana_coinfind ( symbol ) ) = = 0 )
{
if ( ( coin = iguana_coinfind ( symbol ) ) = = 0 )
{
myinfo - > allcoins_being_added = 1 ;
coin = mycalloc ( ' C ' , 1 , sizeof ( * coin ) ) ;
coin - > blockspacesize = IGUANA_MAXPACKETSIZE + 8192 ;
coin - > blockspace = calloc ( 1 , coin - > blockspacesize ) ;
if ( virtcoin ! = 0 | | ( ( privatechain = jstr ( argjson , " geckochain " ) ) ! = 0 & & privatechain [ 0 ] ! = 0 ) )
{
myinfo - > allcoins_numvirts + + ;
coin - > virtualchain = 1 ;
}
else
{
coin - > chain = iguana_chainfind ( myinfo , ( char * ) symbol , argjson , 1 ) ;
coin - > peers = calloc ( 1 , sizeof ( * coin - > peers ) ) ;
for ( j = 0 ; j < IGUANA_MAXPEERS ; j + + )
{
coin - > peers - > active [ j ] . usock = - 1 ;
strcpy ( coin - > peers - > active [ j ] . coinname , name ) ;
strcpy ( coin - > peers - > active [ j ] . symbol , symbol ) ;
}
}
if ( ( coin - > protocol = juint ( argjson , " protocol " ) ) = = 0 )
coin - > protocol = IGUANA_PROTOCOL_BITCOIN ;
coin - > ctx = secp256k1_context_create ( SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY ) ;
secp256k1_pedersen_context_initialize ( coin - > ctx ) ;
secp256k1_rangeproof_context_initialize ( coin - > ctx ) ;
strcpy ( coin - > name , name ) ;
strcpy ( coin - > symbol , symbol ) ;
iguana_initcoin ( coin , argjson ) ;
basilisk_functions ( coin , coin - > protocol ) ;
printf ( " ADD ALLCOINS.(%s) name.(%s) size %ld numvirts.%d \n " , symbol , name , sizeof ( * coin ) , myinfo - > allcoins_numvirts ) ;
coin - > symbolcrc = symbolcrc = calc_crc32 ( 0 , symbol , ( int32_t ) strlen ( symbol ) ) ;
//portable_mutex_lock(&myinfo->allcoins_mutex);
HASH_ADD ( hh , myinfo - > allcoins , symbolcrc , sizeof ( coin - > symbolcrc ) , coin ) ;
//portable_mutex_unlock(&myinfo->allcoins_mutex);
struct iguana_info * virt , * tmp ;
HASH_ITER ( hh , myinfo - > allcoins , virt , tmp )
{
printf ( " %s " , virt - > symbol ) ;
}
printf ( " allcoins \n " ) ;
myinfo - > allcoins_being_added = 0 ;
}
if ( ( coin = iguana_coinfind ( symbol ) ) = = 0 )
printf ( " error finding justadded.(%s) \n " , symbol ) ;
}
return ( coin ) ;
}
void iguana_recvalloc ( struct iguana_info * coin , int32_t numitems )
{
//coin->blocks.ptrs = myrealloc('W',coin->blocks.ptrs,coin->blocks.ptrs==0?0:coin->blocks.maxbits * sizeof(*coin->blocks.ptrs),numitems * sizeof(*coin->blocks.ptrs));
//coin->blocks.RO = myrealloc('W',coin->blocks.RO,coin->blocks.RO==0?0:coin->blocks.maxbits * sizeof(*coin->blocks.RO),numitems * sizeof(*coin->blocks.RO));
//printf("realloc waitingbits.%d -> %d\n",coin->blocks.maxbits,numitems);
//coin->blocks.maxbits = numitems;
}
static int _decreasing_double ( const void * a , const void * b )
{
# define double_a (*(double *)a)
# define double_b (*(double *)b)
if ( double_b > double_a )
return ( 1 ) ;
else if ( double_b < double_a )
return ( - 1 ) ;
return ( 0 ) ;
# undef double_a
# undef double_b
}
static int32_t revsortds ( double * buf , uint32_t num , int32_t size )
{
qsort ( buf , num , size , _decreasing_double ) ;
return ( 0 ) ;
}
double iguana_metric ( struct iguana_peer * addr , uint32_t now , double decay )
{
int32_t duration ; double metric = addr - > recvblocks * addr - > recvtotal ;
addr - > recvblocks * = decay ;
addr - > recvtotal * = decay ;
if ( now > = addr - > ready & & addr - > ready ! = 0 )
duration = ( now - addr - > ready + 1 ) ;
else duration = 1 ;
if ( metric < SMALLVAL & & duration > 300 )
metric = 0.001 ;
else metric / = duration ;
return ( metric ) ;
}
int32_t iguana_peermetrics ( struct supernet_info * myinfo , struct iguana_info * coin )
{
int32_t i , ind , n ; double * sortbuf , sum ; uint32_t now ; struct iguana_peer * addr , * slowest = 0 ;
//printf("peermetrics\n");
sortbuf = mycalloc ( ' s ' , coin - > MAXPEERS , sizeof ( double ) * 2 ) ;
coin - > peers - > mostreceived = 0 ;
now = ( uint32_t ) time ( NULL ) ;
for ( i = n = 0 ; i < coin - > MAXPEERS ; i + + )
{
addr = & coin - > peers - > active [ i ] ;
if ( addr - > usock < 0 | | addr - > dead ! = 0 | | addr - > ready = = 0 | | addr - > ipbits = = 0 )
continue ;
addr - > pendblocks > > = 1 ;
addr - > pendhdrs > > = 1 ;
if ( addr - > recvblocks > coin - > peers - > mostreceived )
coin - > peers - > mostreceived = addr - > recvblocks ;
//printf("[%.0f %.0f] ",addr->recvblocks,addr->recvtotal);
sortbuf [ n * 2 + 0 ] = iguana_metric ( addr , now , .995 ) ;
sortbuf [ n * 2 + 1 ] = i ;
n + + ;
}
if ( n > 0 )
{
revsortds ( sortbuf , n , sizeof ( double ) * 2 ) ;
portable_mutex_lock ( & coin - > peers_mutex ) ;
for ( sum = i = 0 ; i < n ; i + + )
{
if ( i < coin - > MAXPEERS )
{
coin - > peers - > topmetrics [ i ] = sortbuf [ i * 2 ] ;
ind = ( int32_t ) sortbuf [ i * 2 + 1 ] ;
coin - > peers - > ranked [ i ] = addr = & coin - > peers - > active [ ind ] ;
if ( sortbuf [ i * 2 ] > SMALLVAL & & ( double ) i / n > .8 & & ( time ( NULL ) - addr - > ready ) > 77 )
slowest = coin - > peers - > ranked [ i ] ;
//printf("(%.5f %s) ",sortbuf[i*2],coin->peers->ranked[i]->ipaddr);
coin - > peers - > ranked [ i ] - > rank = i + 1 ;
sum + = coin - > peers - > topmetrics [ i ] ;
}
}
coin - > peers - > numranked = n ;
portable_mutex_unlock ( & coin - > peers_mutex ) ;
//printf("peer metrics NUMRANKED.%d\n",n);
if ( i > 0 )
{
coin - > peers - > avemetric = ( sum / i ) ;
if ( i > = 7 * ( coin - > MAXPEERS / 8 ) & & slowest ! = 0 )
{
printf ( " prune slowest peer.(%s) numranked.%d MAXpeers->%d \n " , slowest - > ipaddr , n , coin - > MAXPEERS ) ;
slowest - > dead = 1 ;
}
}
}
myfree ( sortbuf , coin - > MAXPEERS * sizeof ( double ) * 2 ) ;
return ( coin - > peers - > mostreceived ) ;
}
void * iguana_kviAddriterator ( struct iguana_info * coin , struct iguanakv * kv , struct iguana_kvitem * item , uint64_t args , void * key , void * value , int32_t valuesize )
{
char ipaddr [ 64 ] ; int32_t i ; FILE * fp = ( FILE * ) ( long ) args ; struct iguana_peer * addr ; struct iguana_iAddr * iA = value ;
if ( fp ! = 0 & & iA ! = 0 & & iA - > numconnects > 0 & & iA - > lastconnect > time ( NULL ) - IGUANA_RECENTPEER )
{
for ( i = 0 ; i < coin - > peers - > numranked ; i + + )
if ( ( addr = coin - > peers - > ranked [ i ] ) ! = 0 & & addr - > ipbits = = iA - > ipbits )
break ;
if ( i = = coin - > peers - > numranked )
{
expand_ipbits ( ipaddr , iA - > ipbits ) ;
fprintf ( fp , " %s \n " , ipaddr ) ;
}
}
return ( 0 ) ;
}
uint32_t iguana_updatemetrics ( struct supernet_info * myinfo , struct iguana_info * coin )
{
char fname [ 512 ] , tmpfname [ 512 ] , oldfname [ 512 ] , ipaddr [ 64 ] ; int32_t i , j ; struct iguana_peer * addr , * tmpaddr ; FILE * fp ;
iguana_peermetrics ( myinfo , coin ) ;
sprintf ( fname , " %s/%s_peers.txt " , GLOBAL_CONFSDIR , coin - > symbol ) , OS_compatible_path ( fname ) ;
sprintf ( oldfname , " %s/%s_oldpeers.txt " , GLOBAL_CONFSDIR , coin - > symbol ) , OS_compatible_path ( oldfname ) ;
sprintf ( tmpfname , " %s/%s/peers.txt " , GLOBAL_TMPDIR , coin - > symbol ) , OS_compatible_path ( tmpfname ) ;
if ( ( fp = fopen ( tmpfname , " w " ) ) ! = 0 )
{
for ( i = 0 ; i < coin - > peers - > numranked ; i + + )
{
if ( ( addr = coin - > peers - > ranked [ i ] ) ! = 0 & & addr - > relayflag ! = 0 & & strcmp ( addr - > ipaddr , " 127.0.0.1 " ) ! = 0 )
{
for ( j = 0 ; j < coin - > peers - > numranked ; j + + )
{
if ( i ! = j & & ( tmpaddr = coin - > peers - > ranked [ j ] ) ! = 0 & & ( uint32_t ) addr - > ipbits = = ( uint32_t ) tmpaddr - > ipbits )
break ;
}
if ( j = = coin - > peers - > numranked )
{
expand_ipbits ( ipaddr , ( uint32_t ) addr - > ipbits ) ;
fprintf ( fp , " %s \n " , ipaddr ) ;
if ( 0 & & addr - > msgcounts . verack = = 0 )
{
printf ( " iguana_sendblockreq (%s) addrind.%d hasn't verack'ed yet \n " , addr - > ipaddr , addr - > addrind ) ;
iguana_send_version ( coin , addr , coin - > myservices ) ;
}
}
}
}
if ( ftell ( fp ) > OS_filesize ( fname ) )
{
printf ( " new peers.txt %ld vs (%s) %ld (%s) \n " , ftell ( fp ) , fname , ( long ) OS_filesize ( fname ) , GLOBAL_CONFSDIR ) ;
fclose ( fp ) ;
OS_renamefile ( fname , oldfname ) ;
OS_renamefile ( tmpfname , fname ) ;
//OS_copyfile(tmpfname,fname,1);
} else fclose ( fp ) ;
}
else
{
printf ( " iguana_updatemetrics: couldnt create.(%s) \n " , tmpfname ) ;
return ( 0 ) ;
}
return ( ( uint32_t ) time ( NULL ) ) ;
}
void iguana_emitQ ( struct iguana_info * coin , struct iguana_bundle * bp )
{
struct iguana_helper * ptr ;
ptr = mycalloc ( ' i ' , 1 , sizeof ( * ptr ) ) ;
ptr - > allocsize = sizeof ( * ptr ) ;
ptr - > coin = coin ;
ptr - > bp = bp , ptr - > hdrsi = bp - > hdrsi ;
ptr - > type = ' E ' ;
ptr - > starttime = ( uint32_t ) time ( NULL ) ;
//printf("%s EMIT.%d[%d] emitfinish.%u\n",coin->symbol,ptr->hdrsi,bp->n,bp->emitfinish);
queue_enqueue ( " emitQ " , & emitQ , & ptr - > DL , 0 ) ;
}
void iguana_bundleQ ( struct supernet_info * myinfo , struct iguana_info * coin , struct iguana_bundle * bp , int32_t timelimit )
{
struct iguana_helper * ptr ; struct iguana_bundle * tmp ; int32_t i , n = 0 ;
if ( 0 & & bp - > queued = = 0 & & bp - > emitfinish < = 1 & & iguana_bundleready ( myinfo , coin , bp , 0 ) = = bp - > n )
printf ( " bundle.[%d] is ready \n " , bp - > hdrsi ) ;
if ( bp - > queued ! = 0 )
return ;
for ( i = n = 0 ; i < coin - > bundlescount ; i + + )
{
if ( ( tmp = coin - > bundles [ i ] ) ! = 0 & & tmp - > queued ! = 0 )
n + + ;
}
if ( n < coin - > MAXBUNDLES )
{
bp - > queued = ( uint32_t ) time ( NULL ) ;
ptr = mycalloc ( ' q ' , 1 , sizeof ( * ptr ) ) ;
ptr - > allocsize = sizeof ( * ptr ) ;
ptr - > coin = coin ;
ptr - > bp = bp , ptr - > hdrsi = bp - > hdrsi ;
ptr - > type = ' B ' ;
ptr - > starttime = ( uint32_t ) time ( NULL ) ;
ptr - > timelimit = timelimit ;
coin - > numbundlesQ + + ;
// printf("%s.%d %p bundle.%d[%d] ht.%d emitfinish.%u\n",coin->symbol,n,bp,ptr->hdrsi,bp->n,bp->bundleheight,bp->emitfinish);
queue_enqueue ( " bundlesQ " , & bundlesQ , & ptr - > DL , 0 ) ;
}
else
{
bp - > queued = 0 ;
//printf("MAXBUNDLES.%d reached.%d\n",coin->MAXBUNDLES,n);
}
}
void iguana_validateQ ( struct iguana_info * coin , struct iguana_bundle * bp )
{
/*struct iguana_helper *ptr;
//if ( bp->validated <= 1 )
{
ptr = mycalloc ( ' i ' , 1 , sizeof ( * ptr ) ) ;
ptr - > allocsize = sizeof ( * ptr ) ;
ptr - > coin = coin ;
ptr - > bp = bp , ptr - > hdrsi = bp - > hdrsi ;
ptr - > type = ' V ' ;
ptr - > starttime = ( uint32_t ) time ( NULL ) ;
ptr - > timelimit = 0 ;
bp - > validated = 1 ;
//printf("VALIDATE Q %s bundle.%d[%d] utxofinish.%u balancefinish.%u\n",coin->symbol,ptr->hdrsi,bp->n,bp->utxofinish,bp->balancefinish);
queue_enqueue ( " validateQ " , & validateQ , & ptr - > DL , 0 ) ;
} */
}
int32_t iguana_emitfinished ( struct supernet_info * myinfo , struct iguana_info * coin , int32_t queueincomplete )
{
struct iguana_bundle * bp ; int32_t i , n = 0 ;
for ( i = 0 ; i < coin - > bundlescount - 1 ; i + + )
{
if ( ( bp = coin - > bundles [ i ] ) ! = 0 )
{
if ( bp - > emitfinish = = 0 & & bp - > ramchain . H . data ! = 0 )
bp - > emitfinish = ( uint32_t ) time ( NULL ) ;
if ( bp - > emitfinish > 1 )
n + + ;
//printf("%u ",bp->emitfinish);
//else if ( bp->emitfinish == 0 && bp->queued == 0 )
// iguana_bundleQ(myinfo,coin,bp,1000);
}
}
//printf("emitfinished.%d\n",n);
return ( n ) ;
}
int32_t iguana_utxofinished ( struct iguana_info * coin )
{
struct iguana_bundle * bp ; int32_t i , n = 0 ;
for ( i = 0 ; i < coin - > bundlescount - 1 ; i + + )
{
if ( ( bp = coin - > bundles [ i ] ) ! = 0 & & bp - > utxofinish > 1 )
n + + ;
}
return ( n ) ;
}
int32_t iguana_convertfinished ( struct iguana_info * coin )
{
struct iguana_bundle * bp ; int32_t i , n = 0 ;
for ( i = 0 ; i < coin - > bundlescount - 1 ; i + + )
{
if ( ( bp = coin - > bundles [ i ] ) ! = 0 & & bp - > converted > 1 )
n + + ;
}
return ( n ) ;
}
int32_t iguana_balancefinished ( struct iguana_info * coin )
{
struct iguana_bundle * bp ; int32_t i , n = 0 ;
for ( i = 0 ; i < coin - > bundlescount - 1 ; i + + )
{
if ( ( bp = coin - > bundles [ i ] ) ! = 0 & & bp - > balancefinish > 1 )
n + + ;
}
return ( n ) ;
}
int32_t iguana_validated ( struct iguana_info * coin )
{
struct iguana_bundle * bp ; int32_t i , n = 0 ;
for ( i = 0 ; i < coin - > bundlescount - 1 ; i + + )
{
if ( ( bp = coin - > bundles [ i ] ) ! = 0 & & bp - > validated > 1 )
n + + ;
}
return ( n ) ;
}
int32_t iguana_helperA ( struct supernet_info * myinfo , struct iguana_info * coin , int32_t helperid , struct iguana_bundle * bp , int32_t convertflag )
{
int32_t retval , num = 0 ;
if ( bp = = 0 )
{
printf ( " iguana_helperA unexpected null bp \n " ) ;
return ( - 1 ) ;
}
//printf("helperid.%d validate gen utxo.[%d] utxofinish.%u\n",helperid,bp->hdrsi,bp->utxofinish);
if ( iguana_bundlevalidate ( myinfo , coin , bp , 0 ) = = bp - > n ) //
{
retval = 0 ;
if ( bp - > utxofinish > 1 | | ( retval = iguana_spendvectors ( myinfo , coin , bp , & bp - > ramchain , 0 , bp - > n , convertflag , 0 ) ) > = 0 )
{
if ( retval > 0 )
{
printf ( " GENERATED UTXO.%d for ht.%d duration %d seconds \n " , bp - > hdrsi , bp - > bundleheight , ( uint32_t ) time ( NULL ) - bp - > startutxo ) ;
num + + ;
}
bp - > utxofinish = ( uint32_t ) time ( NULL ) ;
} else printf ( " UTXO gen.[%d] utxo error \n " , bp - > hdrsi ) ;
}
else
{
printf ( " error validating.[%d], restart iguana \n " , bp - > hdrsi ) ;
iguana_exit ( myinfo , bp ) ;
}
return ( num ) ;
}
int32_t iguana_helperB ( struct iguana_info * coin , int32_t helperid , struct iguana_bundle * bp , int32_t convertflag )
{
if ( bp = = 0 )
{
printf ( " iguana_helperB unexpected null bp \n " ) ;
return ( - 1 ) ;
}
//if ( bp != coin->current )
{
iguana_ramchain_prefetch ( coin , & bp - > ramchain , 7 ) ;
if ( convertflag = = 0 )
{
bp - > converted = 1 ;
iguana_convert ( coin , helperid , bp , 0 , 0 ) ;
}
bp - > converted = ( uint32_t ) time ( NULL ) ;
return ( 1 ) ;
}
return ( 0 ) ;
}
void iguana_update_balances ( struct iguana_info * coin )
{
int32_t i , hdrsi , max ; struct iguana_bundle * bp ; char fname [ 1024 ] ;
if ( coin - > RTheight > 0 )
{
printf ( " Need to restart iguana to generate new balances files \n " ) ;
printf ( " RT dataset can expand past bundle boundary, so no need to update balance files now \n " ) ;
return ;
}
max = coin - > bundlescount ;
if ( coin - > bundles [ max - 1 ] = = coin - > current | | coin - > bundles [ max - 1 ] = = 0 | | ( coin - > bundles [ max - 1 ] ! = 0 & & coin - > bundles [ max - 1 ] - > utxofinish < = 1 ) )
max - - ;
//coin->spendvectorsaved = 0;
if ( iguana_balancefinished ( coin ) < max & & iguana_spendvectorsaves ( coin ) = = 0 ) //
{
if ( coin - > origbalanceswritten < = 1 )
hdrsi = 0 ;
else hdrsi = coin - > origbalanceswritten ;
for ( i = 0 ; i < max ; i + + )
if ( ( bp = coin - > bundles [ i ] ) ! = 0 & & bp ! = coin - > current )
{
iguana_volatilespurge ( coin , & bp - > ramchain ) ;
sprintf ( fname , " %s/%s/accounts/debits.%d " , GLOBAL_DBDIR , coin - > symbol , bp - > bundleheight ) ;
OS_removefile ( fname , 0 ) ;
sprintf ( fname , " %s/%s/accounts/lastspends.%d " , GLOBAL_DBDIR , coin - > symbol , bp - > bundleheight ) ;
OS_removefile ( fname , 0 ) ;
iguana_volatilesalloc ( coin , & bp - > ramchain , 0 ) ; //i < hdrsi);
}
printf ( " accounts files purged \n " ) ;
sleep ( 3 ) ;
for ( hdrsi = 0 ; hdrsi < max ; hdrsi + + )
{
if ( ( bp = coin - > bundles [ hdrsi ] ) ! = 0 )
{
if ( bp ! = coin - > current )
{
//iguana_ramchain_prefetch(coin,&bp->ramchain,3);
if ( iguana_balancegen ( coin , 0 , bp , 0 , coin - > chain - > bundlesize - 1 , 0 ) = = 0 )
{
fprintf ( stderr , " %d " , hdrsi ) ;
bp - > balancefinish = ( uint32_t ) time ( NULL ) ;
}
else printf ( " balancegen error.[%d] \n " , bp - > hdrsi ) ;
}
} else printf ( " null bp.[%d] \n " , hdrsi ) ;
}
//if ( max != coin->origbalanceswritten )
{
coin - > balanceflush = max + 1 ;
while ( coin - > balanceflush ! = 0 )
sleep ( 3 ) ;
} // else printf("skip flush when max.%d and orig.%d\n",max,coin->origbalanceswritten);
}
else
{
for ( i = 0 ; i < max ; i + + )
if ( ( bp = coin - > bundles [ i ] ) ! = 0 & & bp ! = coin - > current )
{
iguana_volatilespurge ( coin , & bp - > ramchain ) ;
iguana_volatilesmap ( coin , & bp - > ramchain ) ;
}
}
}
int32_t iguana_utxogen ( struct supernet_info * myinfo , struct iguana_info * coin , int32_t helperid , int32_t convertflag )
{
int32_t hdrsi , n , i , max , incr , num = 0 ; struct iguana_bundle * bp ;
if ( coin - > spendvectorsaved > 1 )
{
printf ( " skip utxogen as spendvectorsaved.%u \n " , coin - > spendvectorsaved ) ;
return ( 0 ) ;
}
incr = IGUANA_NUMHELPERS ;
max = coin - > bundlescount ;
if ( coin - > bundles [ max - 1 ] = = coin - > current | | coin - > bundles [ max - 1 ] = = 0 | | ( coin - > bundles [ max - 1 ] ! = 0 & & coin - > bundles [ max - 1 ] - > utxofinish < = 1 ) )
max - - ;
printf ( " helperid.%d start %s utxogen bundlescount.%d max.%d \n " , helperid , coin - > symbol , coin - > bundlescount , max ) ;
if ( helperid < incr )
{
for ( hdrsi = helperid ; hdrsi < max ; hdrsi + = incr )
num + = iguana_helperA ( myinfo , coin , helperid , coin - > bundles [ hdrsi ] , convertflag ) ;
}
while ( ( n = iguana_utxofinished ( coin ) ) < max )
{
printf ( " helperid.%d %s utxofinished.%d vs %d \n " , helperid , coin - > symbol , n , max ) ;
sleep ( IGUANA_NUMHELPERS + 3 ) ;
}
/*if ( helperid < incr )
{
for ( hdrsi = helperid ; hdrsi < max ; hdrsi + = incr )
{
if ( ( bp = coin - > bundles [ hdrsi ] ) = = 0 )
{
printf ( " unexpected null bp for [%d] \n " , hdrsi ) ;
continue ;
}
if ( iguana_bundlevalidate ( myinfo , coin , bp , 0 ) ! = bp - > n )
{
printf ( " validate.[%d] error. refresh page or restart iguana and it should regenerate \n " , bp - > hdrsi ) ;
iguana_exit ( myinfo ) ;
} // else printf("%s helperid.%d validated.[%d]\n",coin->symbol,helperid,hdrsi);
}
}
while ( iguana_validated ( coin ) < max | | iguana_utxofinished ( coin ) < max )
{
printf ( " %s helperid.%d waiting for spendvectorsaved.%u v.%d u.%d b.%d vs max.%d \n " , coin - > symbol , helperid , coin - > spendvectorsaved , iguana_validated ( coin ) , iguana_utxofinished ( coin ) , iguana_balancefinished ( coin ) , max ) ;
sleep ( 2 * IGUANA_NUMHELPERS + 3 ) ;
} */
if ( convertflag = = 0 )
{
if ( helperid < incr )
{
for ( hdrsi = helperid ; hdrsi < max ; hdrsi + = incr )
num + = iguana_helperB ( coin , helperid , coin - > bundles [ hdrsi ] , convertflag ) ;
}
while ( ( n = iguana_convertfinished ( coin ) ) < max )
{
//printf("helperid.%d convertfinished.%d vs max %d bundlescount.%d\n",helperid,n,max,coin->bundlescount);
sleep ( IGUANA_NUMHELPERS + 3 ) ;
}
}
if ( helperid = = 0 )
{
printf ( " %s start iguana_update_balances \n " , coin - > symbol ) ;
iguana_update_balances ( coin ) ;
printf ( " %s iguana_update_balances completed \n " , coin - > symbol ) ;
if ( 1 )
{
for ( i = 0 ; i < max ; i + + )
if ( ( bp = coin - > bundles [ i ] ) ! = 0 )
{
iguana_volatilespurge ( coin , & bp - > ramchain ) ;
iguana_volatilesmap ( coin , & bp - > ramchain ) ;
}
}
}
while ( iguana_balancefinished ( coin ) < max | | coin - > balanceflush ! = 0 )
sleep ( 3 ) ;
//printf("helper.%d check validates\n",helperid);
//incr = IGUANA_NUMHELPERS;
//incr = 1;
if ( helperid = = 0 )
{
coin - > spendvectorsaved = ( uint32_t ) time ( NULL ) ;
coin - > spendvalidated = 0 ;
printf ( " %s UTXOGEN spendvectorsaved <- %u \n " , coin - > symbol , coin - > spendvectorsaved ) ;
if ( iguana_utxoaddr_gen ( myinfo , coin , ( coin - > bundlescount - 1 ) * coin - > chain - > bundlesize ) = = 0 )
{
printf ( " retry utxoaddr_gen \n " ) ;
if ( iguana_utxoaddr_gen ( myinfo , coin , ( coin - > bundlescount - 1 ) * coin - > chain - > bundlesize ) = = 0 )
{
printf ( " restart iguana: fatal error generating ledger file for %s \n " , coin - > symbol ) ;
iguana_exit ( myinfo , 0 ) ;
}
}
}
else
{
while ( coin - > spendvectorsaved < = 1 )
sleep ( IGUANA_NUMHELPERS + 3 ) ;
}
printf ( " %s helper.%d helperdone \n " , coin - > symbol , helperid ) ;
return ( num ) ;
}
int32_t iguana_coin_mainiter ( struct supernet_info * myinfo , struct iguana_info * coin , int32_t * numpeersp , struct OS_memspace * mem , struct OS_memspace * memB )
{
int32_t n , j , isRT = 0 ; struct iguana_bundle * bp ;
if ( coin - > RTheight = = 0 & & coin - > firstRTheight = = 0 & & coin - > current ! = 0 & & coin - > active ! = 0 & & coin - > started ! = 0 )
{
isRT * = ( coin - > RTheight > 0 ) ;
if ( coin - > peers ! = 0 )
* numpeersp + = coin - > peers - > numranked ;
if ( 0 & & ( rand ( ) % 10 ) = = 0 )
printf ( " %s main.%u vs %u, svs %u %d vs %d \n " , coin - > symbol , ( uint32_t ) time ( NULL ) , coin - > startutc + 10 , coin - > spendvectorsaved , coin - > blocks . hwmchain . height / coin - > chain - > bundlesize , ( coin - > longestchain - coin - > minconfirms ) / coin - > chain - > bundlesize ) ;
if ( time ( NULL ) > coin - > startutc + 60 )
{
//if ( (bp= coin->current) != 0 && bp->numsaved >= coin->chain->bundlesize && bp->startutxo == 0 )
// iguana_bundlefinalize(myinfo,coin,bp,mem,memB);
n = coin - > bundlescount - 1 ;
if ( coin - > spendvectorsaved = = 0 & & coin - > blocks . hwmchain . height / coin - > chain - > bundlesize > = ( coin - > longestchain - coin - > chain - > bundlesize ) / coin - > chain - > bundlesize )
{
//printf("%s n.%d emitfinished.%d coin->spendvectorsaved %d\n",coin->symbol,n,iguana_emitfinished(myinfo,coin,1),coin->spendvectorsaved);
if ( iguana_emitfinished ( myinfo , coin , 1 ) > = n )
{
if ( coin - > PREFETCHLAG > = 0 & & coin - > fastfind = = 0 )
{
for ( j = 0 ; j < n ; j + + )
if ( coin - > bundles [ j ] ! = 0 )
iguana_alloctxbits ( coin , & coin - > bundles [ j ] - > ramchain ) ;
sleep ( 3 ) ;
}
if ( iguana_validated ( coin ) < n | | iguana_utxofinished ( coin ) < n | | iguana_balancefinished ( coin ) < n )
{
coin - > spendvectorsaved = 1 ;
printf ( " update volatile data, need.%d vs utxo.%d balances.%d validated.%d \n " , n , iguana_utxofinished ( coin ) , iguana_balancefinished ( coin ) , iguana_validated ( coin ) ) ;
}
else
{
iguana_update_balances ( coin ) ;
coin - > spendvectorsaved = ( uint32_t ) time ( NULL ) ;
printf ( " already done UTXOGEN (%d %d %d) n.%d \n " , iguana_utxofinished ( coin ) , iguana_validated ( coin ) , iguana_balancefinished ( coin ) , n ) ;
}
}
}
}
if ( ( bp = coin - > current ) ! = 0 & & coin - > stucktime ! = 0 & & coin - > isRT = = 0 & & coin - > RTheight = = 0 & & ( time ( NULL ) - coin - > stucktime ) > coin - > MAXSTUCKTIME )
{
if ( 0 )
{
printf ( " %s is stuck too long, restarting due to %d \n " , coin - > symbol , bp - > hdrsi ) ;
if ( coin - > started ! = 0 )
{
iguana_coinpurge ( coin ) ;
sleep ( 3 ) ;
while ( coin - > started = = 0 )
{
printf ( " wait for coin to reactivate \n " ) ;
sleep ( 1 ) ;
}
sleep ( 3 ) ;
}
}
}
}
return ( isRT ) ;
}
void iguana_helper ( void * arg )
{
static uint64_t helperidbits ;
cJSON * argjson = 0 ; int32_t iter , n , i , j , retval , numpeers , polltimeout , type , helperid = rand ( ) , flag , allcurrent , idle = 0 ;
struct iguana_helper * ptr ; struct iguana_info * coin , * tmp ; struct OS_memspace MEM , * MEMB ; struct iguana_bundle * bp ; struct supernet_info * myinfo = SuperNET_MYINFO ( 0 ) ;
helperid % = 64 ;
if ( arg ! = 0 & & ( argjson = cJSON_Parse ( arg ) ) ! = 0 )
helperid = juint ( argjson , " helperid " ) ;
if ( ( ( 1 < < helperid ) & helperidbits ) ! = 0 )
{
printf ( " SKIP duplicate helper.%d \n " , helperid ) ;
return ;
}
helperidbits | = ( 1 < < helperid ) ;
if ( IGUANA_NUMHELPERS < 2 )
type = 3 ;
else type = ( 1 < < ( helperid % 2 ) ) ;
if ( argjson ! = 0 )
free_json ( argjson ) ;
printf ( " HELPER.%d started arg.(%s) type.%d \n " , helperid , ( char * ) ( arg ! = 0 ? arg : 0 ) , type ) ;
memset ( & MEM , 0 , sizeof ( MEM ) ) ;
MEMB = mycalloc ( ' b ' , IGUANA_MAXBUNDLESIZE , sizeof ( * MEMB ) ) ;
sleep ( 2 ) ;
while ( 1 )
{
//printf("helperid.%d top of loop\n",helperid);
flag = 0 ;
allcurrent = 1 ;
polltimeout = 100 ;
//portable_mutex_lock(&myinfo->allcoins_mutex);
numpeers = 0 ;
HASH_ITER ( hh , myinfo - > allcoins , coin , tmp )
{
if ( coin - > firstRTheight = = 0 )
{
if ( coin - > spendvectorsaved = = 1 )
iguana_utxogen ( myinfo , coin , helperid , 1 ) ;
else if ( coin - > spendvectorsaved > 1 & & ( coin - > spendvalidated & ( 1 < < helperid ) ) = = 0 )
{
//printf("%s spendvectorsaved.%u helperid.%d validate\n",coin->symbol,coin->spendvectorsaved,helperid);
for ( j = helperid ; j < coin - > bundlescount - 1 ; j + = IGUANA_NUMHELPERS )
if ( ( bp = coin - > bundles [ j ] ) ! = 0 )
iguana_bundlevalidate ( myinfo , coin , bp , 0 ) ;
coin - > spendvalidated | = ( 1 < < helperid ) ;
//printf("DONE %s spendvectorsaved.%u helperid.%d validate\n",coin->symbol,coin->spendvectorsaved,helperid);
}
else
{
for ( j = helperid ; j < coin - > bundlescount ; j + = IGUANA_NUMHELPERS )
{
if ( ( bp = coin - > bundles [ j ] ) ! = 0 )
{
if ( bp - > emitfinish = = 0 & & bp - > numsaved > = coin - > chain - > bundlesize & & iguana_bundleready ( myinfo , coin , bp , 0 ) = = bp - > n )
iguana_bundlefinalize ( myinfo , coin , bp , & MEM , MEMB ) ;
if ( bp - > emitfinish ! = 0 & & time ( NULL ) > bp - > emitfinish + 60 )
{
if ( bp - > validated = = 0 )
{
for ( i = 0 ; i < j ; i + + )
if ( coin - > bundles [ i ] = = 0 | | coin - > bundles [ i ] - > validated < = 1 )
break ;
if ( i = = j )
{
iguana_bundlevalidate ( myinfo , coin , bp , 0 ) ;
if ( bp - > validated > 1 )
{
for ( i = 0 ; i < j ; i + + )
if ( coin - > bundles [ i ] = = 0 | | coin - > bundles [ i ] - > utxofinish < = 1 )
break ;
if ( bp - > utxofinish = = 0 | | ( retval = iguana_spendvectors ( myinfo , coin , bp , & bp - > ramchain , 0 , bp - > n , 1 , 0 ) ) > = 0 )
{
if ( retval > 0 )
{
printf ( " GENERATED UTXO.%d for ht.%d duration %d seconds \n " , bp - > hdrsi , bp - > bundleheight , ( uint32_t ) time ( NULL ) - bp - > startutxo ) ;
bp - > utxofinish = ( uint32_t ) time ( NULL ) ;
}
}
}
}
}
}
}
}
}
if ( helperid = = 0 )
iguana_coin_mainiter ( myinfo , coin , & numpeers , & MEM , MEMB ) ;
}
}
//portable_mutex_unlock(&myinfo->allcoins_mutex);
n = queue_size ( & bundlesQ ) ;
for ( iter = 0 ; iter < n ; iter + + )
{
if ( ( ptr = queue_dequeue ( & bundlesQ , 0 ) ) ! = 0 )
{
idle = 0 ;
coin = ptr - > coin ;
if ( ( bp = ptr - > bp ) ! = 0 & & coin ! = 0 )
{
if ( coin - > polltimeout < polltimeout )
polltimeout = coin - > polltimeout ;
if ( coin - > current ! = 0 & & coin - > current - > hdrsi ! = coin - > bundlescount - 1 )
allcurrent = 0 ;
//printf("h.%d [%d] bundleQ size.%d lag.%ld\n",helperid,bp->hdrsi,queue_size(&bundlesQ),time(NULL) - bp->nexttime);
coin - > numbundlesQ - - ;
if ( bp - > startutxo = = 0 & & coin - > started ! = 0 & & time ( NULL ) > bp - > nexttime & & coin - > active ! = 0 )
{
flag + = iguana_bundleiters ( myinfo , ptr - > coin , & MEM , MEMB , bp , ptr - > timelimit , IGUANA_DEFAULTLAG ) ;
}
else
{
//printf("skip.[%d] nexttime.%u lag.%ld coin->active.%d\n",bp->hdrsi,bp->nexttime,time(NULL)-bp->nexttime,coin->active);
allcurrent - - ;
iguana_bundleQ ( myinfo , coin , bp , 1000 ) ;
}
}
else //if ( coin->active != 0 )
printf ( " helper missing param? %p %p %u \n " , ptr - > coin , bp , ptr - > timelimit ) ;
myfree ( ptr , ptr - > allocsize ) ;
} else break ;
}
if ( queue_size ( & bundlesQ ) > 1 )
allcurrent = 0 ;
if ( flag ! = 0 )
usleep ( polltimeout * 100 + 1 ) ;
else if ( allcurrent > 0 )
{
//printf("bundlesQ allcurrent\n");
usleep ( polltimeout * 10000 ) ;
} else usleep ( polltimeout * 10000 ) ;
}
}
void iguana_callcoinstart ( struct supernet_info * myinfo , struct iguana_info * coin )
{
struct iguana_bundle * bp ; int32_t bundlei ; bits256 zero ; char dirname [ 512 ] , * symbol ;
iguana_rwiAddrind ( coin , 0 , 0 , 0 ) ;
//for (i=0; i<sizeof(*coin->chain); i++)
// printf("%02x",((uint8_t *)coin->chain)[i]);
char str [ 65 ] ; printf ( " netmagic.%08x init.(%s) maxpeers.%d maxrecvcache.%s services.%llx MAXMEM.%s polltimeout.%d cache.%d pend.(%d -> %d) \n " , * ( uint32_t * ) coin - > chain - > netmagic , coin - > symbol , coin - > MAXPEERS , mbstr ( str , coin - > MAXRECVCACHE ) , ( long long ) coin - > myservices , mbstr ( str , coin - > MAXMEM ) , coin - > polltimeout , coin - > enableCACHE , coin - > startPEND , coin - > endPEND ) ;
symbol = coin - > symbol ;
sprintf ( dirname , " %s/ro " , GLOBAL_DBDIR ) , OS_ensure_directory ( dirname ) ;
sprintf ( dirname , " %s/ro/%s " , GLOBAL_DBDIR , symbol ) , OS_ensure_directory ( dirname ) ;
sprintf ( dirname , " %s/%s " , GLOBAL_DBDIR , symbol ) , OS_ensure_directory ( dirname ) ;
sprintf ( dirname , " %s/purgeable/%s " , GLOBAL_DBDIR , symbol ) , OS_ensure_directory ( dirname ) ;
sprintf ( dirname , " %s/%s/validated " , GLOBAL_DBDIR , symbol ) , OS_ensure_directory ( dirname ) ;
sprintf ( dirname , " %s/%s/accounts " , GLOBAL_DBDIR , symbol ) , OS_ensure_directory ( dirname ) ;
sprintf ( dirname , " %s/%s/spends " , GLOBAL_DBDIR , symbol ) , OS_ensure_directory ( dirname ) ;
sprintf ( dirname , " %s/%s/vouts " , GLOBAL_DBDIR , symbol ) , OS_ensure_directory ( dirname ) ;
if ( coin - > VALIDATEDIR [ 0 ] ! = 0 )
{
sprintf ( dirname , " %s " , coin - > VALIDATEDIR ) , OS_ensure_directory ( dirname ) ;
sprintf ( dirname , " %s/%s " , coin - > VALIDATEDIR , symbol ) , OS_ensure_directory ( dirname ) ;
}
sprintf ( dirname , " %s/%s " , GLOBAL_TMPDIR , symbol ) , OS_ensure_directory ( dirname ) ;
sprintf ( dirname , " %s/%s/RT " , GLOBAL_TMPDIR , coin - > symbol ) , OS_ensure_directory ( dirname ) ;
iguana_coinstart ( myinfo , coin , coin - > initialheight , coin - > mapflags ) ;
coin - > chain - > minconfirms = coin - > minconfirms ;
coin - > started = coin ;
coin - > startutc = ( uint32_t ) time ( NULL ) ;
memset ( zero . bytes , 0 , sizeof ( zero ) ) ;
if ( ( bp = iguana_bundlecreate ( coin , & bundlei , 0 , * ( bits256 * ) coin - > chain - > genesis_hashdata , zero , 1 ) ) ! = 0 )
bp - > bundleheight = 0 ;
}
void iguana_coinloop ( void * arg )
{
struct supernet_info * myinfo ; int32_t flag , i , j , n ; struct iguana_peer * addr ; bits256 zero ; uint32_t now ; struct iguana_info * coin , * * coins = arg ;
myinfo = SuperNET_MYINFO ( 0 ) ;
n = ( int32_t ) ( long ) coins [ 0 ] ;
coins + + ;
coin = coins [ 0 ] ;
printf ( " begin coinloop[%d] %s \n " , n , coin - > symbol ) ;
memset ( zero . bytes , 0 , sizeof ( zero ) ) ;
while ( 1 )
{
flag = 0 ;
for ( i = 0 ; i < n ; i + + )
{
if ( ( coin = coins [ i ] ) ! = 0 )
{
if ( n > 1 & & coin - > RTheight > 0 & & ( rand ( ) % 10 ) ! = 0 )
continue ;
if ( coin - > peers = = 0 )
{
printf ( " FATAL lack of peers struct \n " ) ;
iguana_exit ( myinfo , 0 ) ;
}
if ( coin - > virtualchain = = 0 )
{
if ( coin - > MAXPEERS > IGUANA_MAXPEERS )
coin - > MAXPEERS = IGUANA_MAXPEERS ;
if ( coin - > MAXPEERS > 1 & & coin - > MAXPEERS < IGUANA_MINPEERS )
coin - > MAXPEERS = IGUANA_MAXPEERS ;
# ifdef __PNACL__
if ( coin - > MAXPEERS > 64 )
coin - > MAXPEERS = 64 ;
# endif
}
if ( coin - > started = = 0 & & coin - > active ! = 0 )
{
iguana_callcoinstart ( myinfo , coin ) ;
}
now = ( uint32_t ) time ( NULL ) ;
coin - > idletime = 0 ;
if ( coin - > started ! = 0 & & coin - > active ! = 0 )
{
//printf("%s numranked.%d isRT.%d numsaved.%d M.%d L.%d numverified.%d hdrsi.%d\n",coin->symbol,coin->peers->numranked,coin->isRT,coin->numsaved,coin->blocks.hwmchain.height,coin->longestchain,coin->numverified,coin->current!=0?coin->current->hdrsi:-1);
if ( coin - > peers - > numranked > 4 & & coin - > isRT = = 0 & & now > coin - > startutc + 77 & & coin - > numsaved > = ( coin - > longestchain / coin - > chain - > bundlesize ) * coin - > chain - > bundlesize & & coin - > blocks . hwmchain . height > = coin - > longestchain - 30 )
{
//fprintf(stderr,">>>>>>> %s isRT blockrecv.%d.%d\n",coin->symbol,coin->blocksrecv,coin->longestchain);
//coin->isRT = 1;
if ( coin - > polltimeout > 100 )
coin - > polltimeout = 100 ;
if ( coin - > MAXPEERS > IGUANA_MINPEERS )
coin - > MAXPEERS = IGUANA_MINPEERS ;
}
if ( myinfo - > NOTARY . RELAYID < 0 )
{
if ( coin - > bindsock > = 0 )
{
if ( coin - > MAXPEERS > 1 & & coin - > peers - > numranked < IGUANA_MAXPEERS / 2 & & now > coin - > lastpossible + 2 )
{
//fprintf(stderr,"check possible\n");
if ( coin - > peers - > numranked > 0 & & ( now % 60 ) = = 0 )
iguana_send_ping ( myinfo , coin , coin - > peers - > ranked [ rand ( ) % coin - > peers - > numranked ] ) ;
coin - > lastpossible = iguana_possible_peer ( coin , 0 ) ; // tries to connect to new peers
}
}
else
{
if ( coin - > MAXPEERS > 1 & & coin - > peers - > numranked < ( ( 7 * coin - > MAXPEERS ) > > 3 ) & & now > coin - > lastpossible + 10 )
{
if ( coin - > peers ! = 0 )
{
for ( j = 0 ; j < IGUANA_MAXPEERS ; j + + )
{
i = rand ( ) % IGUANA_MAXPEERS ;
addr = & coin - > peers - > active [ ( i + j ) % IGUANA_MAXPEERS ] ;
if ( addr - > usock > = 0 & & addr - > msgcounts . verack = = 0 )
{
//printf("i.%d j.%d mainloop %s\n",i,j,addr->ipaddr);
iguana_send_version ( coin , addr , coin - > myservices ) ;
break ;
}
}
}
if ( coin - > FULLNODE ! = 0 | | coin - > VALIDATENODE ! = 0 )
{
if ( coin - > peers - > numranked > 0 )
iguana_send_ping ( myinfo , coin , coin - > peers - > ranked [ rand ( ) % coin - > peers - > numranked ] ) ;
}
coin - > lastpossible = iguana_possible_peer ( coin , 0 ) ; // tries to connect to new peers
}
}
if ( coin - > MAXPEERS > 1 & & now > coin - > peers - > lastmetrics + 10 )
{
coin - > peers - > lastmetrics = iguana_updatemetrics ( myinfo , coin ) ; // ranks peers
}
}
if ( coin - > FULLNODE ! = 0 | | coin - > VALIDATENODE ! = 0 | | coin - > MAXPEERS = = 1 )
{
portable_mutex_lock ( & coin - > allcoins_mutex ) ;
flag + = iguana_processrecv ( myinfo , coin ) ;
portable_mutex_unlock ( & coin - > allcoins_mutex ) ;
if ( strcmp ( coin - > symbol , " BTCD " ) = = 0 & & coin - > RTheight > 0 & & coin - > RTheight > coin - > chain - > bundlesize )
{
int32_t hdrsi , nonz , errs ; struct iguana_pkhash * refP ; struct iguana_bundle * bp ;
hdrsi = ( coin - > RTheight / coin - > chain - > bundlesize ) - 1 ;
if ( 0 & & ( bp = coin - > bundles [ hdrsi ] ) ! = 0 & & bp - > weights = = 0 )
bp - > weights = iguana_PoS_weights ( myinfo , coin , & refP , & bp - > supply , & bp - > numweights , & nonz , & errs , bp - > bundleheight ) ;
}
}
}
coin - > idletime = ( uint32_t ) time ( NULL ) ;
}
}
//iguana_jsonQ();
//printf("%s flag.%d isRT.%d polltimeout.%d numranked.%d\n",coin->symbol,flag,coin->isRT,coin->polltimeout,coin->peers->numranked);
/*if ( flag == 0 && coin->isRT == 0 && coin->peers != 0 )
usleep ( coin - > polltimeout * 1000 + ( coin - > peers - > numranked = = 0 ) * 1000000 ) ;
else if ( coin - > current ! = 0 & & coin - > current - > hdrsi = = coin - > longestchain / coin - > chain - > bundlesize )
usleep ( coin - > polltimeout * 5000 + 90000 + ( coin - > peers - > numranked = = 0 ) * 1000000 ) ;
else usleep ( coin - > polltimeout * 1000 ) ; */
if ( flag = = 0 )
usleep ( 100000 ) ;
}
}
void iguana_coinargs ( char * symbol , int64_t * maxrecvcachep , int32_t * minconfirmsp , int32_t * maxpeersp , int32_t * initialheightp , uint64_t * servicesp , int32_t * maxrequestsp , int32_t * maxbundlesp , cJSON * json )
{
if ( ( * maxrecvcachep = j64bits ( json , " maxrecvcache " ) ) ! = 0 )
* maxrecvcachep * = 1024 * 1024 * 1024L ;
* minconfirmsp = juint ( json , " minconfirms " ) ;
* maxpeersp = juint ( json , " maxpeers " ) ;
* maxrequestsp = juint ( json , " maxrequests " ) ;
* maxbundlesp = juint ( json , " maxbundles " ) ;
if ( ( * initialheightp = juint ( json , " initialheight " ) ) = = 0 )
* initialheightp = ( strcmp ( symbol , " BTC " ) = = 0 ) ? 400000 : 100000 ;
* servicesp = j64bits ( json , " services " ) ;
}
void iguana_nameset ( char name [ 64 ] , char * symbol , cJSON * json )
{
if ( strcmp ( " BTC " , symbol ) = = 0 )
strcpy ( name , " Bitcoin " ) ;
else if ( strcmp ( " BTCD " , symbol ) = = 0 )
strcpy ( name , " BitcoinDark " ) ;
else
{
name [ 0 ] = 0 ;
if ( json ! = 0 )
safecopy ( name , jstr ( json , " name " ) , 64 ) ;
if ( name [ 0 ] = = 0 )
strcpy ( name , symbol ) ;
}
}
struct iguana_info * iguana_setcoin ( char * symbol , void * launched , int32_t maxpeers , int64_t maxrecvcache , uint64_t services , int32_t initialheight , int32_t maphash , int32_t minconfirms , int32_t maxrequests , int32_t maxbundles , cJSON * json , int32_t virtcoin )
{
struct iguana_chain * iguana_createchain ( cJSON * json ) ;
struct iguana_info * coin ; int32_t j , m , mult , maxval , mapflags ; char name [ 64 ] ; cJSON * peers ;
mapflags = IGUANA_MAPRECVDATA | maphash * IGUANA_MAPTXIDITEMS | maphash * IGUANA_MAPPKITEMS | maphash * IGUANA_MAPBLOCKITEMS | maphash * IGUANA_MAPPEERITEMS ;
iguana_nameset ( name , symbol , json ) ;
if ( ( coin = iguana_coinfind ( symbol ) ) = = 0 )
coin = iguana_coinadd ( symbol , name , json , virtcoin ) ;
//printf("ensure directories maxval.%d mult.%d start.%d end.%d\n",maxval,mult,coin->startPEND,coin->endPEND);
mult = ( strcmp ( " BTC " , coin - > symbol ) ! = 0 ) ? 32 : 512 ;
maxval = IGUANA_MAXPENDBUNDLES ;
if ( coin - > virtualchain = = 0 )
{
if ( ( coin - > MAXPEERS = maxpeers ) < = 0 )
coin - > MAXPEERS = ( strcmp ( symbol , " BTC " ) = = 0 ) ? 128 : 64 ;
if ( ( coin - > MAXRECVCACHE = maxrecvcache ) = = 0 )
coin - > MAXRECVCACHE = IGUANA_MAXRECVCACHE ;
if ( ( coin - > MAXPENDINGREQUESTS = maxrequests ) < = 0 )
coin - > MAXPENDINGREQUESTS = ( strcmp ( symbol , " BTC " ) = = 0 ) ? IGUANA_BTCPENDINGREQUESTS : IGUANA_PENDINGREQUESTS ;
if ( jobj ( json , " prefetchlag " ) ! = 0 )
coin - > PREFETCHLAG = jint ( json , " prefetchlag " ) ;
else if ( strcmp ( " BTC " , coin - > symbol ) = = 0 )
coin - > PREFETCHLAG = 13 ;
else coin - > PREFETCHLAG = - 1 ;
if ( ( coin - > MAXSTUCKTIME = juint ( json , " maxstuck " ) ) = = 0 )
coin - > MAXSTUCKTIME = _IGUANA_MAXSTUCKTIME ;
if ( ( coin - > startPEND = juint ( json , " startpend " ) ) = = 0 )
{
if ( strcmp ( " BTCD " , coin - > symbol ) = = 0 )
coin - > startPEND = 500 ;
else coin - > startPEND = IGUANA_MAXPENDBUNDLES * mult ;
}
if ( coin - > startPEND > maxval * mult )
coin - > startPEND = maxval * mult ;
else if ( coin - > startPEND < 2 )
coin - > startPEND = 2 ;
coin - > MAXBUNDLES = coin - > startPEND ;
if ( ( coin - > endPEND = juint ( json , " endpend " ) ) = = 0 )
{
if ( strcmp ( " BTCD " , coin - > symbol ) = = 0 )
coin - > endPEND = 500 ;
else coin - > endPEND = IGUANA_MINPENDBUNDLES * mult ;
}
if ( coin - > endPEND > maxval * mult )
coin - > endPEND = maxval * mult ;
else if ( coin - > endPEND < 2 )
coin - > endPEND = 2 ;
# ifdef __PNACL__
coin - > startPEND = coin - > endPEND = 1 ;
# endif
} else coin - > MAXPEERS = 0 ;
coin - > myservices = services ;
coin - > initialheight = initialheight ;
coin - > mapflags = mapflags ;
coin - > protocol = IGUANA_PROTOCOL_BITCOIN ;
if ( ( coin - > txfee = jdouble ( json , " txfee " ) * SATOSHIDEN ) = = 0 )
coin - > txfee = 10000 ;
if ( ( coin - > txfee_perkb = j64bits ( json , " txfee_perkb " ) ) < coin - > txfee / 8 )
coin - > txfee_perkb = coin - > txfee / 8 ;
coin - > MAXMEM = juint ( json , " RAM " ) ;
if ( coin - > MAXMEM = = 0 )
coin - > MAXMEM = IGUANA_DEFAULTRAM ;
coin - > MAXMEM * = ( 1024L * 1024 * 1024 ) ;
coin - > enableCACHE = ( strcmp ( " BTCD " , coin - > symbol ) = = 0 ) ;
if ( jobj ( json , " cache " ) ! = 0 )
coin - > enableCACHE = juint ( json , " cache " ) ;
if ( ( coin - > polltimeout = juint ( json , " poll " ) ) < = 0 )
coin - > polltimeout = IGUANA_DEFAULT_POLLTIMEOUT ;
coin - > active = juint ( json , " active " ) ;
if ( ( coin - > minconfirms = minconfirms ) = = 0 )
coin - > minconfirms = ( strcmp ( symbol , " BTC " ) = = 0 ) ? 3 : 10 ;
if ( coin - > chain = = 0 & & ( coin - > chain = iguana_createchain ( json ) ) = = 0 )
{
printf ( " cant initialize chain.(%s) \n " , jstr ( json , 0 ) ) ;
strcpy ( coin - > name , " illegalcoin " ) ;
coin - > symbol [ 0 ] = 0 ;
return ( 0 ) ;
}
if ( jobj ( json , " RELAY " ) ! = 0 )
coin - > FULLNODE = juint ( json , " RELAY " ) ;
else coin - > FULLNODE = ( strcmp ( coin - > symbol , " BTCD " ) = = 0 ) ;
if ( jobj ( json , " VALIDATE " ) ! = 0 )
coin - > VALIDATENODE = juint ( json , " VALIDATE " ) ;
else coin - > VALIDATENODE = ( strcmp ( coin - > symbol , " BTCD " ) = = 0 ) ;
if ( coin - > VALIDATENODE ! = 0 | | coin - > FULLNODE ! = 0 )
SuperNET_MYINFO ( 0 ) - > IAMRELAY + + ;
# ifdef __PNACL
coin - > VALIDATENODE = coin - > FULLNODE = 0 ;
# endif
if ( jobj ( json , " validatedir " ) ! = 0 )
safecopy ( coin - > VALIDATEDIR , jstr ( json , " validatedir " ) , sizeof ( coin - > VALIDATEDIR ) ) ;
else strcpy ( coin - > VALIDATEDIR , GLOBAL_VALIDATEDIR ) ;
if ( ( peers = jarray ( & m , json , " peers " ) ) ! = 0 )
{
for ( j = 0 ; j < m ; j + + )
{
printf ( " %s " , jstr ( jitem ( peers , j ) , 0 ) ) ;
iguana_possible_peer ( coin , jstr ( jitem ( peers , j ) , 0 ) ) ;
}
printf ( " addnodes.%d \n " , m ) ;
}
char str [ 65 ] ;
if ( coin - > virtualchain = = 0 )
printf ( " pend.(%d -> %d) MAXMEM.%s enablecache.%d VALIDATEDIR.(%s) VALIDATE.%d RELAY.%d \n " , coin - > startPEND , coin - > endPEND , mbstr ( str , coin - > MAXMEM ) , coin - > enableCACHE , coin - > VALIDATEDIR , coin - > VALIDATENODE , coin - > FULLNODE ) ;
return ( coin ) ;
}
int32_t iguana_launchcoin ( struct supernet_info * myinfo , char * symbol , cJSON * json , int32_t virtcoin )
{
int32_t maxpeers , maphash , initialheight , minconfirms , maxrequests , maxbundles ; char name [ 64 ] ; int64_t maxrecvcache ; uint64_t services ; struct iguana_info * * coins , * coin ;
if ( symbol = = 0 )
return ( - 1 ) ;
if ( ( coin = iguana_coinfind ( symbol ) ) ! = 0 )
return ( 0 ) ;
iguana_nameset ( name , symbol , json ) ;
printf ( " launchcoin.%s name.%s \n " , symbol , name ) ;
if ( ( coin = iguana_coinadd ( symbol , name , json , virtcoin ) ) = = 0 )
return ( - 1 ) ;
if ( myinfo - > rpcsymbol [ 0 ] = = 0 | | iguana_coinfind ( myinfo - > rpcsymbol ) = = 0 )
strcpy ( myinfo - > rpcsymbol , symbol ) ;
if ( coin - > launched = = 0 )
{
if ( juint ( json , " GBavail " ) < 8 )
maphash = IGUANA_MAPHASHTABLES ;
else maphash = 0 ;
iguana_coinargs ( symbol , & maxrecvcache , & minconfirms , & maxpeers , & initialheight , & services , & maxrequests , & maxbundles , json ) ;
coins = mycalloc ( ' A ' , 1 + 1 , sizeof ( * coins ) ) ;
if ( ( coin = iguana_setcoin ( symbol , coins , maxpeers , maxrecvcache , services , initialheight , maphash , minconfirms , maxrequests , maxbundles , json , virtcoin ) ) ! = 0 )
{
coins [ 0 ] = ( void * ) ( ( long ) 1 ) ;
coins [ 1 ] = coin ;
printf ( " launch.%p coinloop for.%s services.%llx started.%p peers.%p \n " , coin , coin - > symbol , ( long long ) services , coin - > started , coin - > peers ) ;
coin - > launched = iguana_launch ( coin , " iguana_coinloop " , iguana_coinloop , coins , IGUANA_PERMTHREAD ) ;
coin - > active = 1 ;
coin - > started = 0 ;
return ( 1 ) ;
}
else
{
printf ( " launchcoin: couldnt initialize.(%s) \n " , symbol ) ;
myfree ( coins , sizeof ( * coins ) * 2 ) ;
return ( - 1 ) ;
}
}
return ( 0 ) ;
}
void iguana_coins ( void * arg )
{
struct iguana_info * * coins , * coin ; char * jsonstr , * symbol ; cJSON * array , * item , * json ;
int32_t i , n , maxpeers , maphash , initialheight , minconfirms , maxrequests , maxbundles ;
int64_t maxrecvcache ; uint64_t services ; struct vin_info V ; struct supernet_info * myinfo ;
myinfo = SuperNET_MYINFO ( 0 ) ;
memset ( & V , 0 , sizeof ( V ) ) ;
if ( ( jsonstr = arg ) ! = 0 & & ( json = cJSON_Parse ( jsonstr ) ) ! = 0 )
{
if ( ( array = jarray ( & n , json , " coins " ) ) = = 0 )
{
if ( ( symbol = jstr ( json , " coin " ) ) ! = 0 & & strncmp ( symbol , " BTC " , 3 ) = = 0 )
{
coins = mycalloc ( ' A ' , 1 + 1 , sizeof ( * coins ) ) ;
if ( ( coins [ 1 ] = iguana_setcoin ( symbol , coins , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , json , 0 ) ) ! = 0 )
{
_iguana_calcrmd160 ( coins [ 1 ] , & V ) ;
coins [ 0 ] = ( void * ) ( ( long ) 1 ) ;
iguana_coinloop ( coins ) ;
}
else
{
printf ( " iguana_coins: couldnt initialize.(%s) \n " , symbol ) ;
return ;
}
} else printf ( " no coins[] array in JSON.(%s) only BTCD and BTC can be quicklaunched \n " , jsonstr ) ;
free_json ( json ) ;
return ;
}
coins = mycalloc ( ' A ' , n + 1 , sizeof ( * coins ) ) ;
if ( juint ( json , " GBavail " ) < 8 )
maphash = IGUANA_MAPHASHTABLES ;
else maphash = 0 ;
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( array , i ) ;
if ( ( symbol = jstr ( item , " name " ) ) = = 0 | | strlen ( symbol ) > 8 )
{
printf ( " skip strange coin.(%s) \n " , symbol ) ;
continue ;
}
iguana_coinargs ( symbol , & maxrecvcache , & minconfirms , & maxpeers , & initialheight , & services , & maxrequests , & maxbundles , item ) ;
coins [ 1 + i ] = coin = iguana_setcoin ( symbol , coins , maxpeers , maxrecvcache , services , initialheight , maphash , minconfirms , maxrequests , maxbundles , item , 0 ) ;
if ( coin = = 0 )
{
printf ( " iguana_coins: couldnt initialize.(%s) \n " , symbol ) ;
return ;
}
}
coins [ 0 ] = ( void * ) ( ( long ) n ) ;
iguana_coinloop ( coins ) ;
}
}
char * busdata_sync ( uint32_t * noncep , char * jsonstr , char * broadcastmode , char * destNXTaddr )
{
printf ( " busdata_sync.(%s) \n " , jsonstr ) ;
return ( 0 ) ;
}
// getnewaddress, setaccount, validate address, restart, validate address
// importprivkey, setaccount, validate, restart, validate