diff --git a/crypto777/iguana_OS.c b/crypto777/iguana_OS.c index 31d14dc6f..4e8e70a4c 100755 --- a/crypto777/iguana_OS.c +++ b/crypto777/iguana_OS.c @@ -149,6 +149,8 @@ void _myfree(uint8_t type,int32_t origallocsize,void *origptr,int32_t allocsize) else { printf("myfree size error %d vs %d at %p\n",allocsize,origallocsize,origptr); + static int32_t y,z; + printf("div by zero! %d\n",y/z); getchar(); } //portable_mutex_unlock(&MEMmutex); diff --git a/iguana/iguana777.c b/iguana/iguana777.c index aa33ad6f4..a0c20f293 100755 --- a/iguana/iguana777.c +++ b/iguana/iguana777.c @@ -345,12 +345,14 @@ int32_t iguana_helpertask(FILE *fp,struct OS_memspace *mem,struct OS_memspace *m } else if ( ptr->type == 'E' ) { + coin->emitbusy++; if ( iguana_bundlesaveHT(coin,mem,memB,bp,ptr->starttime) == 0 ) { //fprintf(stderr,"emitQ coin.%p bp.[%d]\n",ptr->coin,bp->bundleheight); bp->emitfinish = (uint32_t)time(NULL) + 1; coin->numemitted++; } else bp->emitfinish = 0; + coin->emitbusy--; } } else printf("no bundle in helperrequest\n"); } else printf("no coin in helperrequest\n"); @@ -379,7 +381,7 @@ void iguana_helper(void *arg) allcurrent = 1; if ( ((ptr= queue_dequeue(&emitQ,0)) != 0 || (ptr= queue_dequeue(&helperQ,0)) != 0) ) { - if ( ptr->bp != 0 && (coin= ptr->coin) != 0 ) + if ( ptr->bp != 0 && (coin= ptr->coin) != 0 && coin->active != 0 ) { idle = 0; coin->helperdepth++; @@ -392,7 +394,7 @@ void iguana_helper(void *arg) else if ( (ptr= queue_dequeue(&bundlesQ,0)) != 0 ) { idle = 0; - if ( (bp= ptr->bp) != 0 && (coin= ptr->coin) != 0 ) + if ( (bp= ptr->bp) != 0 && (coin= ptr->coin) != 0 && coin->active != 0 ) { coin->numbundlesQ--; if ( coin->started != 0 && time(NULL) >= bp->nexttime ) @@ -400,7 +402,9 @@ void iguana_helper(void *arg) else iguana_bundleQ(ptr->coin,bp,1000); if ( coin->current != 0 && coin->current->hdrsi != coin->bundlescount-1 ) allcurrent = 0; - } else printf("helper missing param? %p %p %u\n",ptr->coin,bp,ptr->timelimit); + } + else if ( coin->active != 0 ) + printf("helper missing param? %p %p %u\n",ptr->coin,bp,ptr->timelimit); myfree(ptr,ptr->allocsize); flag++; } @@ -408,7 +412,7 @@ void iguana_helper(void *arg) { if ( (ptr= queue_dequeue(&validateQ,0)) != 0 ) { - if ( ptr->bp != 0 && ptr->coin != 0 ) + if ( ptr->bp != 0 && (coin= ptr->coin) != 0 && coin->active != 0 ) flag += iguana_bundlevalidate(ptr->coin,ptr->bp); else printf("helper validate missing param? %p %p\n",ptr->coin,ptr->bp); myfree(ptr,ptr->allocsize); @@ -433,14 +437,6 @@ void iguana_coinloop(void *arg) printf("begin coinloop[%d]\n",n); for (i=0; istarted == 0 ) - { - iguana_rwiAddrind(coin,0,0,0); - iguana_coinstart(coin,coin->initialheight,coin->mapflags); - printf("init.(%s) maxpeers.%d maxrecvcache.%s services.%llx MAXMEM.%s polltimeout.%d cache.%d pend.(%d -> %d)\n",coin->symbol,coin->MAXPEERS,mbstr(str,coin->MAXRECVCACHE),(long long)coin->myservices,mbstr(str,coin->MAXMEM),coin->polltimeout,coin->enableCACHE,coin->startPEND,coin->endPEND); - coin->started = coin; - coin->chain->minconfirms = coin->minconfirms; - } } coin = coins[0]; iguana_possible_peer(coin,"127.0.0.1"); @@ -455,8 +451,17 @@ void iguana_coinloop(void *arg) { if ( (coin= coins[i]) != 0 ) { + if ( coin->started == 0 && coin->active != 0 ) + { + iguana_rwiAddrind(coin,0,0,0); + iguana_coinstart(coin,coin->initialheight,coin->mapflags); + printf("init.(%s) maxpeers.%d maxrecvcache.%s services.%llx MAXMEM.%s polltimeout.%d cache.%d pend.(%d -> %d)\n",coin->symbol,coin->MAXPEERS,mbstr(str,coin->MAXRECVCACHE),(long long)coin->myservices,mbstr(str,coin->MAXMEM),coin->polltimeout,coin->enableCACHE,coin->startPEND,coin->endPEND); + coin->started = coin; + coin->chain->minconfirms = coin->minconfirms; + } now = (uint32_t)time(NULL); - if ( coin->active != 0 ) + coin->idletime = 0; + if ( coin->started != 0 && coin->active != 0 ) { if ( coin->isRT == 0 && now > coin->startutc+77 && coin->numsaved >= (coin->longestchain/coin->chain->bundlesize)*coin->chain->bundlesize && coin->blocks.hwmchain.height >= coin->longestchain-30 ) { @@ -498,6 +503,7 @@ void iguana_coinloop(void *arg) if ( coin->longestchain+10000 > coin->blocks.maxbits ) iguana_recvalloc(coin,coin->longestchain + 100000); } + coin->idletime = (uint32_t)time(NULL); } } if ( flag == 0 ) @@ -547,6 +553,8 @@ struct iguana_info *iguana_setcoin(char *symbol,void *launched,int32_t maxpeers, mult = (strcmp("BTC",coin->symbol) != 0) ? 512 : 1; maxval = (strcmp("BTC",coin->symbol) != 0) ? 2048 : 64; coin->MAXMEM = juint(json,"RAM"); + if ( (coin->MAXSTUCKTIME= juint(json,"maxstuck")) == 0 ) + coin->MAXSTUCKTIME = _IGUANA_MAXSTUCKTIME; if ( coin->MAXMEM == 0 ) coin->MAXMEM = IGUANA_DEFAULTRAM; if ( strcmp("BTC",coin->symbol) == 0 && coin->MAXMEM <= 4 ) diff --git a/iguana/iguana777.h b/iguana/iguana777.h index f0d27233d..85889274f 100755 --- a/iguana/iguana777.h +++ b/iguana/iguana777.h @@ -23,9 +23,10 @@ typedef int32_t (*blockhashfunc)(uint8_t *blockhashp,uint8_t *serialized,int32_t len); #define IGUANA_MAXSCRIPTSIZE 10001 -//#define IGUANA_SERIALIZE_SPENDVECTORGEN +#define IGUANA_SERIALIZE_SPENDVECTORGEN //#define IGUANA_SERIALIZE_BALANCEGEN //#define IGUANA_DISABLEPEERS +#define _IGUANA_MAXSTUCKTIME 300 #define IGUANA_MAXCOINS 64 #define IGUANA_MAXDELAY_MILLIS (3600 * 1000) @@ -179,6 +180,8 @@ struct iguana_thread void *arg; }; +struct iguana_blockreq { struct queueitem DL; bits256 hash2,*blockhashes; struct iguana_bundle *bp; int32_t n,height,bundlei; }; + struct iguana_chain { //const int32_t chain_id; @@ -282,7 +285,7 @@ struct iguana_block double PoW; // NOT consensus safe, for estimation purposes only int32_t height; uint32_t fpipbits,numrequests,issued; long fpos; uint16_t hdrsi,bundlei:11,mainchain:1,valid:1,queued:1,txvalid:1,newtx:1,peerid:8; - UT_hash_handle hh; bits256 *blockhashes; struct iguana_bundlereq *req; + UT_hash_handle hh; struct iguana_bundlereq *req; //bits256 *blockhashes; };// __attribute__((packed)); @@ -426,10 +429,10 @@ struct iguana_bloominds { uint16_t inds[8]; }; struct iguana_bundle { struct queueitem DL; struct iguana_info *coin; struct iguana_bundle *nextbp; - struct iguana_bloom16 bloom; uint32_t rawscriptspace; + struct iguana_bloom16 bloom; //uint32_t rawscriptspace; uint32_t issuetime,hdrtime,emitfinish,mergefinish,purgetime,queued,startutxo,utxofinish,balancefinish,validated,lastspeculative,dirty,nexttime,currenttime,lastprefetch; int32_t numhashes,numrecv,numsaved,numcached,generrs,checkedtmp,currentflag; - int32_t minrequests,n,hdrsi,bundleheight,numtxids,numspends,numunspents,numspec; + int32_t minrequests,n,hdrsi,bundleheight,numtxids,numspends,numunspents,numspec,isRT; double avetime,threshold,metric; uint64_t datasize,estsize; struct iguana_block *blocks[IGUANA_MAXBUNDLESIZE]; uint32_t issued[IGUANA_MAXBUNDLESIZE]; bits256 prevbundlehash2,hashes[IGUANA_MAXBUNDLESIZE+1],nextbundlehash2,allhash,*speculative; @@ -460,9 +463,9 @@ struct iguana_info struct iguana_peers peers; uint64_t instance_nonce,myservices,totalsize,totalrecv,totalpackets,sleeptime; int64_t mining,totalfees,TMPallocated,MAXRECVCACHE,MAXMEM,estsize,activebundles; - int32_t MAXPEERS,MAXPENDING,MAXBUNDLES,active,closestbundle,numemitted,lastsweep,startutc,newramchain,numcached,cachefreed,helperdepth,startPEND,endPEND,enableCACHE,RELAYNODE,VALIDATENODE,balanceswritten,RTheight; bits256 balancehash; - uint32_t lastsync,parsetime,numiAddrs,firstblock,lastpossible,bundlescount,savedblocks,backlog; - int32_t longestchain,badlongestchain,longestchain_strange; + int32_t MAXPEERS,MAXPENDING,MAXBUNDLES,MAXSTUCKTIME,active,closestbundle,numemitted,lastsweep,startutc,newramchain,numcached,cachefreed,helperdepth,startPEND,endPEND,enableCACHE,RELAYNODE,VALIDATENODE,balanceswritten,RTheight; bits256 balancehash; + uint32_t lastsync,parsetime,numiAddrs,lastpossible,bundlescount,savedblocks,backlog; + int32_t longestchain,badlongestchain,longestchain_strange,RTramchain_busy,emitbusy; struct tai starttime; double startmillis; struct iguana_chain *chain; struct iguana_iAddr *iAddrs; @@ -473,12 +476,12 @@ struct iguana_info queue_t acceptQ,hdrsQ,blocksQ,priorityQ,possibleQ,cacheQ,recvQ; double parsemillis,avetime; uint32_t Launched[8],Terminated[8]; portable_mutex_t peers_mutex,blocks_mutex; - portable_mutex_t scripts_mutex[2]; FILE *scriptsfp[2]; void *scriptsptr[2]; long scriptsfilesize[2]; + //portable_mutex_t scripts_mutex[2]; FILE *scriptsfp[2]; void *scriptsptr[2]; long scriptsfilesize[2]; //struct scriptinfo *scriptstable[2]; struct iguana_bundle *bundles[IGUANA_MAXBUNDLES],*current,*lastpending; struct iguana_ramchain RTramchain; struct OS_memspace RTmem,RThashmem; int32_t numremain,numpendings,zcount,recvcount,bcount,pcount,lastbundle,numsaved,pendbalances,numverified; - uint32_t recvtime,hdrstime,backstoptime,lastbundletime,numreqsent,numbundlesQ,lastbundleitime,lastdisp,RTgenesis; + uint32_t recvtime,hdrstime,backstoptime,lastbundletime,numreqsent,numbundlesQ,lastbundleitime,lastdisp,RTgenesis,idletime,stucktime,stuckmonitor,maxstuck; double backstopmillis; bits256 backstophash2; int64_t spaceused; int32_t initialheight,mapflags,minconfirms,numrecv,bindsock,isRT,backstop,blocksrecv,merging,polltimeout,numreqtxids,allhashes; bits256 reqtxids[64]; void *launched,*started; @@ -818,6 +821,11 @@ int32_t iguana_ramchain_iterate(struct iguana_info *coin,struct iguana_ramchain void *iguana_bundlefile(struct iguana_info *coin,char *fname,long *filesizep,struct iguana_bundle *bp,int32_t bundlei); int32_t iguana_mapchaininit(struct iguana_info *coin,struct iguana_ramchain *mapchain,struct iguana_bundle *bp,int32_t bundlei,struct iguana_block *block,void *ptr,long filesize); void iguana_autoextend(struct iguana_info *coin,struct iguana_bundle *bp); +void iguana_RTramchainfree(struct iguana_info *coin); +void iguana_coinpurge(struct iguana_info *coin); +int32_t iguana_setmaxbundles(struct iguana_info *coin); +void iguana_bundlepurgefiles(struct iguana_info *coin,struct iguana_bundle *bp); +uint32_t iguana_sparseaddtx(uint8_t *bits,int32_t width,uint32_t tablesize,bits256 txid,struct iguana_txid *T,uint32_t txidind); extern int32_t HDRnet,netBLOCKS; diff --git a/iguana/iguana_blocks.c b/iguana/iguana_blocks.c index 219fe020b..117a08b4b 100755 --- a/iguana/iguana_blocks.c +++ b/iguana/iguana_blocks.c @@ -66,7 +66,7 @@ struct iguana_block *iguana_blockhashset(struct iguana_info *coin,int32_t height } if ( createflag > 0 ) { - block = mycalloc('x',1,sizeof(*block)); + block = calloc(1,sizeof(*block)); block->RO.hash2 = hash2; block->hh.itemind = height, block->height = -1; HASH_ADD(hh,coin->blocks.hash,RO.hash2,sizeof(hash2),block); @@ -274,7 +274,7 @@ struct iguana_block *_iguana_chainlink(struct iguana_info *coin,struct iguana_bl if ( newblock == 0 ) return(0); hwmchain = &coin->blocks.hwmchain; - if ( hwmchain->height > 0 && ((bp= coin->current) == 0 || hwmchain->height/coin->chain->bundlesize > bp->hdrsi) ) + if ( hwmchain->height > 0 && ((bp= coin->current) == 0 || hwmchain->height/coin->chain->bundlesize >= bp->hdrsi+bp->isRT) ) return(0); if ( (block= iguana_blockfind(coin,newblock->RO.hash2)) != 0 ) { diff --git a/iguana/iguana_bundles.c b/iguana/iguana_bundles.c index 041923d8e..b4bd9980a 100755 --- a/iguana/iguana_bundles.c +++ b/iguana/iguana_bundles.c @@ -365,7 +365,7 @@ struct iguana_txid *iguana_bundletx(struct iguana_info *coin,struct iguana_bundl return(0); } -void iguana_bundlepurge(struct iguana_info *coin,struct iguana_bundle *bp) +void iguana_bundlepurgefiles(struct iguana_info *coin,struct iguana_bundle *bp) { static bits256 zero; char fname[1024]; int32_t hdrsi,m,j; uint32_t ipbits; @@ -663,6 +663,18 @@ int32_t iguana_bundlehdr(struct iguana_info *coin,struct iguana_bundle *bp,int32 return(counter); } +int32_t iguana_setmaxbundles(struct iguana_info *coin) +{ + double completed; + if ( coin->current != 0 && coin->bundlescount != 0 ) + { + completed = ((double)coin->current->hdrsi + 1) / coin->bundlescount; + coin->MAXBUNDLES = (double)(coin->endPEND - coin->startPEND)*completed + coin->startPEND; + //printf("MAXBUNDLES %d (%d -> %d) completed %.3f\n",coin->MAXBUNDLES,coin->startPEND,coin->endPEND,completed); + } + return(coin->MAXBUNDLES); +} + int32_t iguana_bundletweak(struct iguana_info *coin,struct iguana_bundle *bp) { struct iguana_bundle *lastbp; @@ -670,13 +682,14 @@ int32_t iguana_bundletweak(struct iguana_info *coin,struct iguana_bundle *bp) coin->current = coin->bundles[bp->hdrsi+1]; if ( (lastbp= coin->lastpending) != 0 && lastbp->hdrsi < coin->bundlescount-1 ) coin->lastpending = coin->bundles[lastbp->hdrsi + 1]; - if ( (rand() % 3) == 0 ) + iguana_setmaxbundles(coin); + /*if ( (rand() % 3) == 0 ) { if ( coin->MAXBUNDLES > coin->endPEND ) coin->MAXBUNDLES--; else if ( coin->MAXBUNDLES < coin->endPEND ) coin->MAXBUNDLES++; - } + }*/ return(coin->MAXBUNDLES); } @@ -704,7 +717,7 @@ int64_t iguana_bundlecalcs(struct iguana_info *coin,struct iguana_bundle *bp) printf("iguana_bundlecalcs.(%s) illegal hdrsi.%d bundlei.%d checki.%d\n",fname,hdrsi,bundlei,checki); continue; } - if ( coin->current == bp ) + if ( coin->current == bp && (bp->isRT != 0 || bp->hdrsi > coin->bundlescount-3) ) { if ( (fp= fopen(fname,"rb")) != 0 ) { @@ -795,7 +808,11 @@ int32_t iguana_bundlefinish(struct iguana_info *coin,struct iguana_bundle *bp) } #endif for (i=0; ihdrsi; i++) - if ( (prevbp= coin->bundles[i]) == 0 || prevbp->emitfinish < coin->startutc ) + if ( (prevbp= coin->bundles[i]) == 0 || prevbp->emitfinish < coin->startutc +#ifdef IGUANA_SERIALIZE_SPENDVECTORGEN + || (i < bp->hdrsi-16 && prevbp->utxofinish <= 1) +#endif + ) break; if ( i == bp->hdrsi ) { @@ -827,7 +844,7 @@ int32_t iguana_bundlefinish(struct iguana_info *coin,struct iguana_bundle *bp) int32_t iguana_bundleiters(struct iguana_info *coin,struct OS_memspace *mem,struct OS_memspace *memB,struct iguana_bundle *bp,int32_t timelimit) { - int32_t range,starti,lasti,retval=0,max,counter = 0; struct iguana_bundle *currentbp,*lastbp; + int32_t range,starti,lasti,i,n,len,retval=0,max,counter = 0; struct iguana_block *block; struct iguana_bundle *currentbp,*lastbp; uint8_t serialized[512]; struct iguana_peer *addr; long lag; struct iguana_blockreq *breq; if ( coin->started == 0 ) { printf("%s not ready yet\n",coin->symbol); @@ -868,7 +885,7 @@ int32_t iguana_bundleiters(struct iguana_info *coin,struct OS_memspace *mem,stru } //else printf("finish incomplete.%d\n",bp->hdrsi); } } - else if ( bp->numsaved >= bp->n ) + else if ( bp->numsaved >= bp->n )//&& (bp->isRT == 0 || coin->RTheight > bp->bundleheight+bp->n+coin->minconfirms) ) { if ( iguana_bundleready(coin,bp) == bp->n ) { @@ -885,6 +902,7 @@ int32_t iguana_bundleiters(struct iguana_info *coin,struct OS_memspace *mem,stru iguana_emitQ(coin,bp); else { + coin->emitbusy++; if ( iguana_bundlesaveHT(coin,mem,memB,bp,(uint32_t)time(NULL)) == 0 ) { //fprintf(stderr,"emitQ done coin.%p bp.[%d] ht.%d\n",coin,bp->hdrsi,bp->bundleheight); @@ -896,6 +914,7 @@ int32_t iguana_bundleiters(struct iguana_info *coin,struct OS_memspace *mem,stru fprintf(stderr,"emitQ done coin.%p bp.[%d] ht.%d error\n",coin,bp->hdrsi,bp->bundleheight); bp->emitfinish = 0; } + coin->emitbusy--; } } retval = 1; @@ -906,8 +925,40 @@ int32_t iguana_bundleiters(struct iguana_info *coin,struct OS_memspace *mem,stru counter = iguana_bundleissue(coin,bp,max,timelimit); if ( bp == coin->current && coin->isRT == 0 ) bp->nexttime--; - if ( bp->hdrsi == starti && counter > 0 ) - printf("ITER now.%u spec.%-4d bundle.%-4d h.%-4d r.%-4d s.%-4d F.%d T.%d issued.%d mb.%d/%d\n",(uint32_t)time(NULL),bp->numspec,bp->bundleheight/coin->chain->bundlesize,bp->numhashes,bp->numrecv,bp->numsaved,bp->emitfinish,timelimit,counter,coin->MAXBUNDLES,coin->bundlescount); + if ( bp->hdrsi == starti && bp->isRT == 0 ) + { + if ( counter > 0 ) + printf("ITER now.%u spec.%-4d bundle.%-4d h.%-4d r.%-4d s.%-4d F.%d T.%d issued.%d mb.%d/%d\n",(uint32_t)time(NULL),bp->numspec,bp->bundleheight/coin->chain->bundlesize,bp->numhashes,bp->numrecv,bp->numsaved,bp->emitfinish,timelimit,counter,coin->MAXBUNDLES,coin->bundlescount); + if ( coin->stucktime != 0 ) + { + lag = time(NULL)-coin->stucktime; + if ( (lag % 60) == 30 ) + { + while ( (breq= queue_dequeue(&coin->blocksQ,0)) != 0 ) + myfree(breq,sizeof(*breq)); + while ( (breq= queue_dequeue(&coin->priorityQ,0)) != 0 ) + myfree(breq,sizeof(*breq)); + for (i=n=0; in; i++) + { + if ( (block= bp->blocks[i]) != 0 && (block->RO.recvlen == 0 || block->fpos < 0 || block->fpipbits == 0 || bits256_nonz(block->RO.prev_block) == 0) ) + { + printf("[%d:%d] ",bp->hdrsi,i); + iguana_blockQ("stuck",coin,bp,i,block->RO.hash2,1); + if ( coin->peers.numranked > 8 && (addr= coin->peers.ranked[n % 8]) != 0 && addr->usock >= 0 && addr->dead == 0 && addr->msgcounts.verack != 0 ) + { + if ( (len= iguana_getdata(coin,serialized,MSG_BLOCK,&block->RO.hash2,1)) > 0 ) + { + printf("%s, ",addr->ipaddr); + iguana_send(coin,addr,serialized,len); + } + } + n++; + } + } + printf("issued %d priority requests [%d] to unstick\n",n,bp->hdrsi); + } + } + } } iguana_bundleQ(coin,bp,1000); return(retval); @@ -1002,7 +1053,7 @@ void iguana_bundlestats(struct iguana_info *coin,char *str) if ( (block= bp->blocks[j]) != 0 && (block->RO.recvlen == 0 || block->fpipbits == 0 || block->fpos < 0) && time(NULL) > block->issued+3 && (rand() % 10) == 0 ) { if ( (r= coin->peers.numranked) != 0 && (addr= coin->peers.ranked[rand() % r]) != 0 && addr->dead == 0 && addr->usock >= 0 ) - iguana_sendblockreqPT(coin,addr,bp,j,block->RO.hash2,0); printf("current stop [%d:%d]\n",bp->hdrsi,j); + iguana_sendblockreqPT(coin,addr,bp,j,block->RO.hash2,0); printf("kick [%d:%d]\n",bp->hdrsi,j); iguana_blockQ("currentstop",coin,bp,j,block->RO.hash2,1); block->issued = (uint32_t)time(NULL); break; @@ -1029,7 +1080,7 @@ void iguana_bundlestats(struct iguana_info *coin,char *str) done++; numemit++; if ( firstgap != 0 && bp->hdrsi > firstgap->hdrsi-3 ) - iguana_bundlepurge(coin,bp); + iguana_bundlepurgefiles(coin,bp); } else { @@ -1069,7 +1120,7 @@ void iguana_bundlestats(struct iguana_info *coin,char *str) free(sortbuf);*/ coin->numremain = n; coin->blocksrecv = numrecv; - char str2[65]; uint64_t tmp; int32_t diff,p = 0; struct tai difft,t = tai_now(); + uint64_t tmp; int32_t diff,p = 0; struct tai difft,t = tai_now(); for (i=0; ipeers.active[i].usock >= 0 ) p++; @@ -1090,11 +1141,23 @@ void iguana_bundlestats(struct iguana_info *coin,char *str) coin->spaceused = spaceused; coin->numverified = numv; char str4[65],str5[65]; - sprintf(str,"%s.RT%d u.%d b.%d v.%d/%d (%d/%d 1st.%d) to %d N[%d] h.%d r.%d c.%s s.%d d.%d E.%d:%d est.%d %s peers.%d/%d Q.(%d %d) L.%d [%d:%d] M.%d %s",coin->symbol,coin->RTheight,numutxo,numbalances,numv,coin->pendbalances,firstgap!=0?firstgap->numsaved:-1,firstgap!=0?firstgap->numhashes:-1,firstgap!=0?firstgap->hdrsi:-1,coin->lastpending!=0?coin->lastpending->hdrsi:0,count,numhashes,coin->blocksrecv,mbstr(str4,spaceused),numsaved,done,numemit,coin->numreqsent,coin->MAXBUNDLES,mbstr(str2,estsize),p,coin->MAXPEERS,queue_size(&coin->priorityQ),queue_size(&coin->blocksQ),coin->longestchain,coin->blocks.hwmchain.height/coin->chain->bundlesize,coin->blocks.hwmchain.height%coin->chain->bundlesize,coin->blocks.hwmchain.height,bits256_str(str5,coin->blocks.hwmchain.RO.hash2)); + if ( coin->isRT == 0 && firstgap != 0 && firstgap->hdrsi < coin->bundlescount-1 ) + { + if ( coin->stuckmonitor != (firstgap->hdrsi * coin->chain->bundlesize) + firstgap->numsaved ) + { + coin->stuckmonitor = (firstgap->hdrsi * coin->chain->bundlesize) + firstgap->numsaved; + coin->stucktime = (uint32_t)time(NULL); + } + } + if ( coin->isRT != 0 || (firstgap != 0 && firstgap->hdrsi == coin->bundlescount-1) ) + coin->stucktime = 0; + if ( coin->stucktime != 0 && time(NULL)-coin->stucktime > coin->maxstuck ) + coin->maxstuck = (uint32_t)time(NULL) - coin->stucktime; + sprintf(str,"%s.RT%d u.%d b.%d v.%d/%d (%d/%d 1st.%d) to %d N[%d] h.%d r.%d c.%s s.%d d.%d E.%d maxB.%d peers.%d/%d Q.(%d %d) L.%d [%d:%d] M.%d %s",coin->symbol,coin->RTheight,numutxo,numbalances,numv,coin->pendbalances,firstgap!=0?firstgap->numsaved:-1,firstgap!=0?firstgap->numhashes:-1,firstgap!=0?firstgap->hdrsi:-1,coin->lastpending!=0?coin->lastpending->hdrsi:0,count,numhashes,coin->blocksrecv,mbstr(str4,spaceused),numsaved,done,numemit,coin->MAXBUNDLES,p,coin->MAXPEERS,queue_size(&coin->priorityQ),queue_size(&coin->blocksQ),coin->longestchain,coin->blocks.hwmchain.height/coin->chain->bundlesize,coin->blocks.hwmchain.height%coin->chain->bundlesize,coin->blocks.hwmchain.height,bits256_str(str5,coin->blocks.hwmchain.RO.hash2)); //sprintf(str+strlen(str),"%s.%-2d %s time %.2f files.%d Q.%d %d\n",coin->symbol,flag,str,(double)(time(NULL)-coin->starttime)/60.,coin->peers.numfiles,queue_size(&coin->priorityQ),queue_size(&coin->blocksQ)); if ( time(NULL) > coin->lastdisp+3 && strcmp(str,coin->lastdispstr) != 0 ) { - printf("\n%s bQ.%d %d:%02d:%02d %03.3f\n",str,coin->numbundlesQ,(int32_t)difft.x/3600,(int32_t)(difft.x/60)%60,(int32_t)difft.x%60,difft.millis); + printf("\n%s bQ.%d %d:%02d:%02d stuck.%d max.%d\n",str,coin->numbundlesQ,(int32_t)difft.x/3600,(int32_t)(difft.x/60)%60,(int32_t)difft.x%60,coin->stucktime!=0?(uint32_t)time(NULL) - coin->stucktime:0,coin->maxstuck); strcpy(coin->lastdispstr,str); if ( (rand() % 100) == 0 ) myallocated(0,0); @@ -1102,6 +1165,7 @@ void iguana_bundlestats(struct iguana_info *coin,char *str) if ( firstgap != 0 && firstgap->queued == 0 ) iguana_bundleQ(coin,firstgap,1000); } + iguana_setmaxbundles(coin); strcpy(coin->statusstr,str); coin->estsize = estsize; } diff --git a/iguana/iguana_init.c b/iguana/iguana_init.c index 5426e17a7..885251f38 100755 --- a/iguana/iguana_init.c +++ b/iguana/iguana_init.c @@ -56,8 +56,8 @@ void iguana_initcoin(struct iguana_info *coin,cJSON *argjson) sprintf(dirname,"tmp/%s",coin->symbol), OS_portable_path(dirname); portable_mutex_init(&coin->peers_mutex); portable_mutex_init(&coin->blocks_mutex); - portable_mutex_init(&coin->scripts_mutex[0]); - portable_mutex_init(&coin->scripts_mutex[1]); + //portable_mutex_init(&coin->scripts_mutex[0]); + //portable_mutex_init(&coin->scripts_mutex[1]); iguana_meminit(&coin->blockMEM,"blockMEM",coin->blockspace,sizeof(coin->blockspace),0); iguana_initQs(coin); coin->bindsock = -1; @@ -322,6 +322,90 @@ void iguana_parseline(struct iguana_info *coin,int32_t iter,FILE *fp) } } +void iguana_ramchainpurge(struct iguana_info *coin,struct iguana_bundle *bp,struct iguana_ramchain *ramchain) +{ +} + +void iguana_bundlepurge(struct iguana_info *coin,struct iguana_bundle *bp) +{ + static bits256 zero; + if ( bp->speculative != 0 ) + myfree(bp->speculative,sizeof(*bp->speculative) * bp->numspec); + bp->numspec = 0; + bp->speculative = 0; + memset(bp->hashes,0,sizeof(bp->hashes)); + memset(bp->issued,0,sizeof(bp->issued)); + bp->prevbundlehash2 = bp->nextbundlehash2 = bp->allhash = zero; + iguana_ramchain_free(coin,&bp->ramchain,1); +} + +void iguana_blockpurge(struct iguana_info *coin,struct iguana_block *block) +{ + if ( block->req != 0 ) + { + printf("purge req inside block\n"); + myfree(block->req,block->req->allocsize); + } + free(block); +} + +void iguana_blockspurge(struct iguana_info *coin) +{ + struct iguana_block *block,*tmp; + if ( coin->blocks.hash != 0 ) + { + HASH_ITER(hh,coin->blocks.hash,block,tmp) + { + HASH_DEL(coin->blocks.hash,block); + iguana_blockpurge(coin,block); + } + coin->blocks.hash = 0; + } + if ( coin->blocks.RO != 0 ) + { + myfree(coin->blocks.RO,coin->blocks.maxbits * sizeof(*coin->blocks.RO)); + coin->blocks.RO = 0; + } + coin->blocks.maxbits = coin->blocks.maxblocks = coin->blocks.initblocks = coin->blocks.hashblocks = coin->blocks.issuedblocks = coin->blocks.recvblocks = coin->blocks.emitblocks = coin->blocks.parsedblocks = coin->blocks.dirty = 0; + memset(&coin->blocks.hwmchain,0,sizeof(coin->blocks.hwmchain)); +} + +void iguana_coinpurge(struct iguana_info *coin) +{ + int32_t i; struct iguana_bundle *bp; char *hashstr; struct iguana_bundlereq *req; struct iguana_blockreq *breq; + coin->started = 0; coin->active = 0; + coin->RTgenesis = 0; + while ( (hashstr= queue_dequeue(&coin->hdrsQ,1)) != 0 ) + free_queueitem(hashstr); + while ( (breq= queue_dequeue(&coin->blocksQ,0)) != 0 ) + myfree(breq,sizeof(*breq)); + while ( (breq= queue_dequeue(&coin->priorityQ,0)) != 0 ) + myfree(breq,sizeof(*breq)); + while ( (req= queue_dequeue(&coin->cacheQ,0)) != 0 ) + myfree(req,req->allocsize); + while ( (req= queue_dequeue(&coin->recvQ,0)) != 0 ) + { + if ( req->blocks != 0 ) + myfree(req->blocks,sizeof(*req->blocks) * req->n), req->blocks = 0; + if ( req->hashes != 0 ) + myfree(req->hashes,sizeof(*req->hashes) * req->n), req->hashes = 0; + myfree(req,req->allocsize); + } + while ( coin->idletime == 0 && coin->emitbusy > 0 ) + { + printf("coinpurge.%s waiting for idle %lu emitbusy.%d\n",coin->symbol,time(NULL),coin->emitbusy); + sleep(1); + } + iguana_RTramchainfree(coin); + coin->bundlescount = 0; + for (i=0; ibundlescount; i++) + if ( (bp= coin->bundles[i]) != 0 ) + iguana_bundlepurge(coin,bp); + coin->current = coin->lastpending = 0; + memset(coin->bundles,0,sizeof(coin->bundles)); + iguana_blockspurge(coin); +} + struct iguana_info *iguana_coinstart(struct iguana_info *coin,int32_t initialheight,int32_t mapflags) { FILE *fp; char fname[512],*symbol; int32_t iter; @@ -331,8 +415,9 @@ struct iguana_info *iguana_coinstart(struct iguana_info *coin,int32_t initialhei initialheight = coin->chain->bundlesize*10; iguana_recvalloc(coin,initialheight); coin->longestchain = 1; + memset(&coin->blocks.hwmchain,0,sizeof(coin->blocks.hwmchain)); coin->blocks.hwmchain.height = 0; - if ( (coin->myservices & NODE_NETWORK) != 0 ) + if ( (coin->myservices & NODE_NETWORK) != 0 && coin->peers.acceptloop == 0 ) { printf("MYSERVICES.%llx\n",(long long)coin->myservices); coin->peers.acceptloop = malloc(sizeof(pthread_t)); @@ -343,7 +428,7 @@ struct iguana_info *iguana_coinstart(struct iguana_info *coin,int32_t initialhei printf("error launching accept thread for port.%u\n",coin->chain->portp2p); } } - coin->firstblock = coin->blocks.parsedblocks + 1; + //coin->firstblock = coin->blocks.parsedblocks + 1; iguana_genesis(coin,coin->chain); for (iter=0; iter<2; iter++) { @@ -360,6 +445,6 @@ struct iguana_info *iguana_coinstart(struct iguana_info *coin,int32_t initialhei #ifndef IGUANA_DEDICATED_THREADS coin->peers.peersloop = iguana_launch("peersloop",iguana_peersloop,coin,IGUANA_PERMTHREAD); #endif - printf("started.%s\n",coin->symbol); + printf("started.%s %p active.%d\n",coin->symbol,coin->started,coin->active); return(coin); } diff --git a/iguana/iguana_json.c b/iguana/iguana_json.c index e6e973bff..df92b49fe 100755 --- a/iguana/iguana_json.c +++ b/iguana/iguana_json.c @@ -621,6 +621,16 @@ STRING_ARG(iguana,startcoin,activecoin) } else return(clonestr("{\"error\":\"startcoin needs coin\"}")); } +STRING_ARG(iguana,stopcoin,activecoin) +{ + if ( coin != 0 ) + { + coin->active = 0; + iguana_coinpurge(coin); + return(clonestr("{\"result\":\"coin stopped\"}")); + } else return(clonestr("{\"error\":\"stopcoin needs coin\"}")); +} + STRING_ARG(iguana,pausecoin,activecoin) { if ( coin != 0 ) diff --git a/iguana/iguana_ramchain.c b/iguana/iguana_ramchain.c index 8d610a5a6..559735cf5 100755 --- a/iguana/iguana_ramchain.c +++ b/iguana/iguana_ramchain.c @@ -212,50 +212,6 @@ void iguana_blocksetcounters(struct iguana_info *coin,struct iguana_block *block block->RO.firstexternalind = ramchain->externalind; } -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,j; - struct iguana_bundle *bp; struct iguana_ramchain *ramchain; struct iguana_block *block; - *heightp = -1; - if ( lasthdrsi < 0 ) - return(0); - for (i=lasthdrsi; i>=0; i--) - { - if ( (bp= coin->bundles[i]) != 0 && bp->emitfinish > coin->startutc ) - { - ramchain = &bp->ramchain; - if ( ramchain->H.data != 0 ) - { - TXbits = (void *)(long)((long)ramchain->H.data + ramchain->H.data->TXoffset); - T = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Toffset); - //printf("search bp.%p TXbits.%p T.%p %d %d\n",bp,TXbits,T,(int32_t)ramchain->H.data->TXoffset,(int32_t)ramchain->H.data->Toffset); - if ( (txidind= iguana_sparseaddtx(TXbits,ramchain->H.data->txsparsebits,ramchain->H.data->numtxsparse,txid,T,0)) > 0 ) - { - //printf("found txidind.%d\n",txidind); - if ( bits256_cmp(txid,T[txidind].txid) == 0 ) - { - for (j=0; jn; j++) - if ( (block= bp->blocks[j]) != 0 && txidind >= block->RO.firsttxidind && txidind < block->RO.firsttxidind+block->RO.txn_count ) - break; - if ( j < bp->n ) - { - *heightp = bp->bundleheight + j; - //printf("found height.%d\n",*heightp); - *tx = T[txidind]; - return(tx); - } - for (j=0; jn; j++) - if ( (block= bp->blocks[j]) != 0 ) - printf("(%d %d).%d ",block->RO.firsttxidind,block->RO.txn_count,txidind >= block->RO.firsttxidind && txidind < block->RO.firsttxidind+block->RO.txn_count); - printf(" <- firsttxidind txidind.%d not in block range\n",txidind); - } else printf("mismatched sparse entry\n"); - } - } - } - } - return(0); -} - int32_t iguana_peerfname(struct iguana_info *coin,int32_t *hdrsip,char *dirname,char *fname,uint32_t ipbits,bits256 hash2,bits256 prevhash2,int32_t numblocks) { struct iguana_bundle *bp = 0; int32_t bundlei = -2; char str[65]; @@ -1650,6 +1606,8 @@ int32_t iguana_ramchain_iterate(struct iguana_info *coin,struct iguana_ramchain } for (ramchain->H.txidind=rdata->firsti; ramchain->H.txidindnumtxids; ramchain->H.txidind++) { + if ( coin->active == 0 ) + return(-1);; if ( 0 && ramchain->expanded == 0 && dest != 0 ) printf("ITER [%d] TXID.%d -> dest.%p desttxid.%d dest->hashmem.%p numtxids.%d\n",ramchain->H.data->height,ramchain->H.txidind,dest,dest!=0?dest->H.txidind:0,dest!=0?dest->hashmem:0,rdata->numtxids); tx = &T[ramchain->H.txidind]; @@ -1665,6 +1623,8 @@ int32_t iguana_ramchain_iterate(struct iguana_info *coin,struct iguana_ramchain } for (j=0; jnumvouts; j++) { + if ( coin->active == 0 ) + return(-1); fileid = 0; scriptpos = 0; scriptlen = 0; @@ -1744,6 +1704,8 @@ int32_t iguana_ramchain_iterate(struct iguana_info *coin,struct iguana_ramchain tx = &T[ramchain->H.txidind]; for (j=0; jnumvins; j++) { + if ( coin->active == 0 ) + return(-1); fileid = 0; scriptpos = 0; scriptlen = 0; @@ -1873,7 +1835,7 @@ long iguana_ramchain_data(struct iguana_info *coin,struct iguana_peer *addr,stru { origtxdata->block.issued = 0; origtxdata->block.RO.recvlen = 0; - printf("ramchain data: error finding block\n"); + char str[65]; printf("ramchain data: error finding block %s\n",bits256_str(str,origtxdata->block.RO.hash2)); return(-1); } } @@ -2004,7 +1966,7 @@ long iguana_ramchain_data(struct iguana_info *coin,struct iguana_peer *addr,stru bp->numtxids += ramchain->H.data->numtxids; bp->numunspents += ramchain->H.data->numunspents; bp->numspends += ramchain->H.data->numspends; - bp->rawscriptspace += ramchain->H.data->scriptspace; + //bp->rawscriptspace += ramchain->H.data->scriptspace; } iguana_ramchain_free(coin,&R,1); } @@ -2013,7 +1975,7 @@ long iguana_ramchain_data(struct iguana_info *coin,struct iguana_peer *addr,stru bp->numtxids += ramchain->H.data->numtxids; bp->numunspents += ramchain->H.data->numunspents; bp->numspends += ramchain->H.data->numspends; - bp->rawscriptspace += ramchain->H.data->scriptspace; + //bp->rawscriptspace += ramchain->H.data->scriptspace; } if ( fpos >= 0 ) block->fpos = fpos, block->fpipbits = (uint32_t)addr->ipbits; @@ -2404,6 +2366,11 @@ int32_t iguana_bundlesaveHT(struct iguana_info *coin,struct OS_memspace *mem,str sigspace = pubkeyspace = 0; for (bundlei=starti,numtxids=numunspents=scriptspace=numspends=0; bundlei<=endi; bundlei++) { + if ( coin->active == 0 ) + { + iguana_bundlemapfree(coin,mem,&HASHMEM,ipbits,ptrs,filesizes,num,R,starti,endi); + return(-1); + } if ( (block= bp->blocks[bundlei]) == 0 || bits256_nonz(block->RO.hash2) == 0 || block != iguana_blockfind(coin,block->RO.hash2) || memcmp(block->RO.hash2.bytes,bp->hashes[bundlei].bytes,sizeof(bits256)) != 0 ) { printf("block.%p error vs %p\n",block,iguana_blockfind(coin,block->RO.hash2)); @@ -2460,6 +2427,11 @@ int32_t iguana_bundlesaveHT(struct iguana_info *coin,struct OS_memspace *mem,str iguana_ramchain_extras(coin,dest,&HASHMEM,0); for (i=starti; i<=endi; i++) { + if ( coin->active == 0 ) + { + iguana_bundlemapfree(coin,mem,&HASHMEM,ipbits,ptrs,filesizes,num,R,starti,endi); + return(-1); + } if ( (block= bp->blocks[i]) != 0 && block == iguana_blockfind(coin,bp->hashes[i]) ) { if ( bits256_nonz(block->RO.prev_block) == 0 && i > 0 ) @@ -2482,6 +2454,8 @@ int32_t iguana_bundlesaveHT(struct iguana_info *coin,struct OS_memspace *mem,str dest->H.scriptoffset = 1; for (bundlei=starti; bundlei<=endi; bundlei++) { + if ( coin->active == 0 ) + break; if ( (block= bp->blocks[bundlei]) != 0 ) { iguana_blocksetcounters(coin,block,dest); @@ -2497,7 +2471,8 @@ int32_t iguana_bundlesaveHT(struct iguana_info *coin,struct OS_memspace *mem,str bp->issued[bundlei] = 0; block->issued = 0; } - printf("error ramchain_iterate hdrs.%d bundlei.%d\n",bp->hdrsi,bundlei); + if ( coin->active != 0 ) + printf("error ramchain_iterate hdrs.%d bundlei.%d\n",bp->hdrsi,bundlei); break; } } @@ -2538,9 +2513,12 @@ int32_t iguana_bundlesaveHT(struct iguana_info *coin,struct OS_memspace *mem,str iguana_bundleload(coin,&newchain,bp,0); newchain.A = 0; } - iguana_ramchain_free(coin,dest,0); - bp->ramchain = newchain; - //printf("finished bundlesave.%d\n",bp->bundleheight); + if ( coin->active != 0 ) + { + iguana_ramchain_free(coin,dest,0); + bp->ramchain = newchain; + } + //printf("finished bundlesave.%d retval.%d\n",bp->bundleheight,retval); return(retval); } diff --git a/iguana/iguana_recv.c b/iguana/iguana_recv.c index 005061d9a..c65ebaa37 100755 --- a/iguana/iguana_recv.c +++ b/iguana/iguana_recv.c @@ -484,8 +484,8 @@ struct iguana_bundle *iguana_bundleset(struct iguana_info *coin,struct iguana_bl } prevbp = 0, prevbundlei = -2; iguana_bundlefind(coin,&prevbp,&prevbundlei,prevhash2); - if ( 0 && block->blockhashes != 0 ) - fprintf(stderr,"has blockhashes bp.%p[%d] prevbp.%p[%d]\n",bp,bundlei,prevbp,prevbundlei); + //if ( 0 && block->blockhashes != 0 ) + // fprintf(stderr,"has blockhashes bp.%p[%d] prevbp.%p[%d]\n",bp,bundlei,prevbp,prevbundlei); if ( prevbp != 0 && prevbundlei >= 0 && (prevblock= iguana_blockfind(coin,prevhash2)) != 0 ) { if ( prevbundlei < coin->chain->bundlesize ) @@ -816,7 +816,7 @@ struct iguana_bundlereq *iguana_recvblock(struct iguana_info *coin,struct iguana if ( (prev= iguana_blockfind(coin,block->RO.prev_block)) == 0 ) prev = iguana_blockhashset(coin,-1,block->RO.prev_block,1); width = sqrt(coin->chain->bundlesize); - while ( prev != 0 && width-- > 0 ) + while ( coin->active != 0 && prev != 0 && width-- > 0 ) { if ( prev->mainchain != 0 ) break; @@ -961,7 +961,7 @@ int32_t iguana_reqblocks(struct iguana_info *coin) queue_enqueue("hdrsQ",&coin->hdrsQ,queueitem(bits256_str(str,bp->hashes[0])),1); }*/ lflag = 1; - while ( lflag != 0 ) + while ( coin->active != 0 && lflag != 0 ) { lflag = 0; hdrsi = (coin->blocks.hwmchain.height+1) / coin->chain->bundlesize; @@ -1085,7 +1085,7 @@ int32_t iguana_processrecvQ(struct iguana_info *coin,int32_t *newhwmp) // single { int32_t flag = 0; struct iguana_bundlereq *req; *newhwmp = 0; - while ( (req= queue_dequeue(&coin->recvQ,0)) != 0 ) + while ( coin->active != 0 && (req= queue_dequeue(&coin->recvQ,0)) != 0 ) { //fprintf(stderr,"%s recvQ.%p type.%c n.%d\n",req->addr != 0 ? req->addr->ipaddr : "0",req,req->type,req->n); if ( req->type == 'B' ) // one block with all txdata @@ -1140,7 +1140,7 @@ int32_t iguana_reqhdrs(struct iguana_info *coin) int32_t i,lag,n = 0; struct iguana_bundle *bp; char hashstr[65]; if ( queue_size(&coin->hdrsQ) == 0 ) { - //if ( iguana_needhdrs(coin) > 0 ) + if ( coin->active != 0 ) { for (i=0; ibundlescount; i++) { @@ -1177,8 +1177,6 @@ int32_t iguana_reqhdrs(struct iguana_info *coin) return(n); } -struct iguana_blockreq { struct queueitem DL; bits256 hash2,*blockhashes; struct iguana_bundle *bp; int32_t n,height,bundlei; }; - int32_t iguana_blockQ(char *argstr,struct iguana_info *coin,struct iguana_bundle *bp,int32_t bundlei,bits256 hash2,int32_t priority) { queue_t *Q; char *str; int32_t n,height = -1; struct iguana_blockreq *req; struct iguana_block *block = 0; diff --git a/iguana/iguana_unspents.c b/iguana/iguana_unspents.c index 3ad244f4f..95dac0791 100755 --- a/iguana/iguana_unspents.c +++ b/iguana/iguana_unspents.c @@ -88,6 +88,41 @@ int32_t iguana_utxoupdate(struct iguana_info *coin,int16_t spent_hdrsi,uint32_t return(0); } +int32_t iguana_spentflag(struct iguana_info *coin,int32_t *spentheightp,struct iguana_ramchain *ramchain,int16_t spent_hdrsi,uint32_t spent_unspentind,int32_t height) +{ + uint32_t numunspents; struct iguana_hhutxo *hhutxo; struct iguana_utxo utxo; + uint8_t ubuf[sizeof(uint32_t) + sizeof(int16_t)]; + *spentheightp = 0; + numunspents = (ramchain == &coin->RTramchain) ? ramchain->H.unspentind : ramchain->H.data->numunspents; + memset(&utxo,0,sizeof(utxo)); + if ( spent_unspentind != 0 && spent_unspentind < numunspents ) + { + if ( (hhutxo= iguana_hhutxofind(coin,ubuf,spent_hdrsi,spent_unspentind)) != 0 && hhutxo->u.spentflag != 0 ) + utxo = hhutxo->u; + else if ( ramchain->Uextras != 0 ) + utxo = ramchain->Uextras[spent_unspentind]; + else + { + printf("null ramchain->Uextras unspentind.%u vs %u hdrs.%d\n",spent_unspentind,numunspents,spent_hdrsi); + return(-1); + } + } + else + { + printf("illegal unspentind.%u vs %u hdrs.%d\n",spent_unspentind,numunspents,spent_hdrsi); + return(-1); + } + if ( utxo.fromheight == 0 ) + { + printf("illegal unspentind.%u vs %u hdrs.%d zero fromheight?\n",spent_unspentind,numunspents,spent_hdrsi); + return(-1); + } + *spentheightp = utxo.fromheight; + if ( height == 0 || utxo.fromheight < height ) + return(utxo.spentflag); + else return(0); +} + int32_t iguana_volatileupdate(struct iguana_info *coin,int32_t incremental,struct iguana_ramchain *spentchain,int16_t spent_hdrsi,uint32_t spent_unspentind,uint32_t spent_pkind,uint64_t spent_value,uint32_t spendind,uint32_t fromheight) { struct iguana_account *A2; struct iguana_ramchaindata *rdata; struct iguana_utxo *utxo; @@ -121,59 +156,50 @@ int32_t iguana_volatileupdate(struct iguana_info *coin,int32_t incremental,struc return(-1); } -struct iguana_pkhash *iguana_pkhashfind(struct iguana_info *coin,struct iguana_ramchain **ramchainp,int64_t *balancep,uint32_t *lastunspentindp,struct iguana_pkhash *p,uint8_t rmd160[20],int32_t firsti,int32_t endi) +struct iguana_txid *iguana_txidfind(struct iguana_info *coin,int32_t *heightp,struct iguana_txid *tx,bits256 txid,int32_t lasthdrsi) { - uint8_t *PKbits; struct iguana_pkhash *P; uint32_t pkind,i; struct iguana_bundle *bp; struct iguana_ramchain *ramchain; struct iguana_account *ACCTS; - *balancep = 0; - *ramchainp = 0; - *lastunspentindp = 0; - for (i=firsti; ibundlescount&&i<=endi; i++) + uint8_t *TXbits; struct iguana_txid *T; uint32_t txidind; int32_t i,j; + struct iguana_bundle *bp; struct iguana_ramchain *ramchain; struct iguana_block *block; + *heightp = -1; + if ( lasthdrsi < 0 ) + return(0); + for (i=lasthdrsi; i>=0; i--) { - if ( (bp= coin->bundles[i]) != 0 ) + if ( (bp= coin->bundles[i]) != 0 && bp->emitfinish > coin->startutc ) { - ramchain = &bp->ramchain; + ramchain = (bp->isRT != 0) ? &coin->RTramchain : &bp->ramchain; if ( ramchain->H.data != 0 ) { - PKbits = (void *)(long)((long)ramchain->H.data + ramchain->H.data->PKoffset); - P = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Poffset); - ACCTS = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Aoffset); - if ( (pkind= iguana_sparseaddpk(PKbits,ramchain->H.data->pksparsebits,ramchain->H.data->numpksparse,rmd160,P,0)) > 0 && pkind < ramchain->H.data->numpkinds ) + TXbits = (void *)(long)((long)ramchain->H.data + ramchain->H.data->TXoffset); + T = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Toffset); + //printf("search bp.%p TXbits.%p T.%p %d %d\n",bp,TXbits,T,(int32_t)ramchain->H.data->TXoffset,(int32_t)ramchain->H.data->Toffset); + if ( (txidind= iguana_sparseaddtx(TXbits,ramchain->H.data->txsparsebits,ramchain->H.data->numtxsparse,txid,T,0)) > 0 ) { - *ramchainp = ramchain; - *balancep = ACCTS[pkind].total; - *lastunspentindp = ACCTS[pkind].lastunspentind; - *p = P[pkind]; - return(p); - } //else printf("not found pkind.%d vs num.%d\n",pkind,ramchain->H.data->numpkinds); - } else printf("%s.[%d] error null ramchain->H.data\n",coin->symbol,i); + //printf("found txidind.%d\n",txidind); + if ( bits256_cmp(txid,T[txidind].txid) == 0 ) + { + for (j=0; jn; j++) + if ( (block= bp->blocks[j]) != 0 && txidind >= block->RO.firsttxidind && txidind < block->RO.firsttxidind+block->RO.txn_count ) + break; + if ( j < bp->n ) + { + *heightp = bp->bundleheight + j; + //printf("found height.%d\n",*heightp); + *tx = T[txidind]; + return(tx); + } + for (j=0; jn; j++) + if ( (block= bp->blocks[j]) != 0 ) + printf("(%d %d).%d ",block->RO.firsttxidind,block->RO.txn_count,txidind >= block->RO.firsttxidind && txidind < block->RO.firsttxidind+block->RO.txn_count); + printf(" <- firsttxidind txidind.%d not in block range\n",txidind); + } else printf("mismatched sparse entry\n"); + } + } } } return(0); } -char *iguana_bundleaddrs(struct iguana_info *coin,int32_t hdrsi) -{ - uint8_t *PKbits; struct iguana_pkhash *P; uint32_t pkind; struct iguana_bundle *bp; struct iguana_ramchain *ramchain; cJSON *retjson; char rmdstr[41]; - if ( (bp= coin->bundles[hdrsi]) != 0 ) - { - ramchain = &bp->ramchain; - if ( ramchain->H.data != 0 ) - { - retjson = cJSON_CreateArray(); - PKbits = (void *)(long)((long)ramchain->H.data + ramchain->H.data->PKoffset); - P = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Poffset); - for (pkind=0; pkindH.data->numpkinds; pkind++,P++) - { - init_hexbytes_noT(rmdstr,P->rmd160,20); - jaddistr(retjson,rmdstr); - } - return(jprint(retjson,1)); - } - //iguana_bundleQ(coin,bp,bp->n); - return(clonestr("{\"error\":\"no bundle data\"}")); - } return(clonestr("{\"error\":\"no bundle\"}")); -} - struct iguana_bundle *iguana_externalspent(struct iguana_info *coin,bits256 *prevhashp,uint32_t *unspentindp,struct iguana_ramchain *ramchain,int32_t spend_hdrsi,struct iguana_spend *s) { int32_t prev_vout,height,hdrsi; uint32_t sequenceid,unspentind; char str[65]; @@ -249,10 +275,80 @@ cJSON *iguana_unspentjson(struct iguana_info *coin,int32_t hdrsi,uint32_t unspen return(item); } -int64_t iguana_pkhashbalance(struct iguana_info *coin,cJSON *array,int64_t *spentp,int32_t *nump,struct iguana_ramchain *ramchain,struct iguana_pkhash *p,uint32_t lastunspentind,uint8_t rmd160[20],char *coinaddr,uint8_t *pubkey33,int32_t hdrsi) +struct iguana_pkhash *iguana_pkhashfind(struct iguana_info *coin,struct iguana_ramchain **ramchainp,int64_t *balancep,uint32_t *lastunspentindp,struct iguana_pkhash *p,uint8_t rmd160[20],int32_t firsti,int32_t endi) { - struct iguana_unspent *U; uint32_t unspentind; int64_t balance = 0; struct iguana_txid *T; + uint8_t *PKbits; struct iguana_pkhash *P; uint32_t pkind,numpkinds,i; struct iguana_bundle *bp; struct iguana_ramchain *ramchain; struct iguana_account *ACCTS; + *balancep = 0; + *ramchainp = 0; + *lastunspentindp = 0; + for (i=firsti; ibundlescount&&i<=endi; i++) + { + if ( (bp= coin->bundles[i]) != 0 ) + { + if ( bp->isRT != 0 && coin->RTramchain_busy != 0 ) + { + printf("iguana_pkhashfind: unexpected access when RTramchain_busy\n"); + return(0); + } + ramchain = (bp->isRT != 0) ? &bp->ramchain : &coin->RTramchain; + if ( ramchain->H.data != 0 ) + { + numpkinds = (bp->isRT != 0) ? ramchain->H.data->numpkinds : ramchain->pkind; + PKbits = (void *)(long)((long)ramchain->H.data + ramchain->H.data->PKoffset); + P = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Poffset); + ACCTS = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Aoffset); + if ( (pkind= iguana_sparseaddpk(PKbits,ramchain->H.data->pksparsebits,ramchain->H.data->numpksparse,rmd160,P,0)) > 0 && pkind < numpkinds ) + { + *ramchainp = ramchain; + *balancep = ACCTS[pkind].total; + *lastunspentindp = ACCTS[pkind].lastunspentind; + *p = P[pkind]; + return(p); + } //else printf("not found pkind.%d vs num.%d\n",pkind,ramchain->H.data->numpkinds); + } else printf("%s.[%d] error null ramchain->H.data\n",coin->symbol,i); + } + } + return(0); +} + +char *iguana_bundleaddrs(struct iguana_info *coin,int32_t hdrsi) +{ + uint8_t *PKbits; struct iguana_pkhash *P; uint32_t pkind,numpkinds; struct iguana_bundle *bp; struct iguana_ramchain *ramchain; cJSON *retjson; char rmdstr[41]; + if ( (bp= coin->bundles[hdrsi]) != 0 ) + { + if ( bp->isRT != 0 && coin->RTramchain_busy != 0 ) + { + printf("iguana_bundleaddrs: unexpected access when RTramchain_busy\n"); + return(0); + } + ramchain = (bp->isRT != 0) ? &bp->ramchain : &coin->RTramchain; + if ( ramchain->H.data != 0 ) + { + numpkinds = (bp->isRT != 0) ? ramchain->H.data->numpkinds : ramchain->pkind; + retjson = cJSON_CreateArray(); + PKbits = (void *)(long)((long)ramchain->H.data + ramchain->H.data->PKoffset); + P = (void *)(long)((long)ramchain->H.data + ramchain->H.data->Poffset); + for (pkind=0; pkindrmd160,20); + jaddistr(retjson,rmdstr); + } + return(jprint(retjson,1)); + } + //iguana_bundleQ(coin,bp,bp->n); + return(clonestr("{\"error\":\"no bundle data\"}")); + } return(clonestr("{\"error\":\"no bundle\"}")); +} + +int64_t iguana_pkhashbalance(struct iguana_info *coin,cJSON *array,int64_t *spentp,int32_t *nump,struct iguana_ramchain *ramchain,struct iguana_pkhash *p,uint32_t lastunspentind,uint8_t rmd160[20],char *coinaddr,uint8_t *pubkey33,int32_t hdrsi,int32_t height) +{ + struct iguana_unspent *U; int32_t spentheight; uint32_t unspentind; int64_t balance = 0; struct iguana_txid *T; *spentp = *nump = 0; + if ( ramchain == &coin->RTramchain && coin->RTramchain_busy != 0 ) + { + printf("iguana_pkhashbalance: unexpected access when RTramchain_busy\n"); + return(0); + } if ( ramchain->Uextras == 0 ) { printf("iguana_pkhashbalance: unexpected null spents\n"); @@ -265,7 +361,7 @@ int64_t iguana_pkhashbalance(struct iguana_info *coin,cJSON *array,int64_t *spen { (*nump)++; printf("%s u.%d %.8f\n",jprint(iguana_unspentjson(coin,hdrsi,unspentind,T,&U[unspentind],rmd160,coinaddr,pubkey33),1),unspentind,dstr(U[unspentind].value)); - if ( ramchain->Uextras[unspentind].spentflag == 0 ) + if ( iguana_spentflag(coin,&spentheight,ramchain,hdrsi,unspentind,height) == 0 ) { balance += U[unspentind].value; if ( array != 0 ) @@ -279,11 +375,16 @@ int64_t iguana_pkhashbalance(struct iguana_info *coin,cJSON *array,int64_t *spen int32_t iguana_pkhasharray(struct iguana_info *coin,cJSON *array,int32_t minconf,int32_t maxconf,int64_t *totalp,struct iguana_pkhash *P,int32_t max,uint8_t rmd160[20],char *coinaddr,uint8_t *pubkey33) { int32_t i,n,m; int64_t spent,balance,netbalance,total; uint32_t lastunspentind; struct iguana_ramchain *ramchain; + if ( coin->RTramchain_busy != 0 ) + { + printf("iguana_pkhasharray: unexpected access when RTramchain_busy\n"); + return(-1); + } for (total=i=n=0; ibundlescount; i++) { if ( iguana_pkhashfind(coin,&ramchain,&balance,&lastunspentind,&P[n],rmd160,i,i) != 0 ) { - if ( (netbalance= iguana_pkhashbalance(coin,array,&spent,&m,ramchain,&P[n],lastunspentind,rmd160,coinaddr,pubkey33,i)) != balance-spent ) + if ( (netbalance= iguana_pkhashbalance(coin,array,&spent,&m,ramchain,&P[n],lastunspentind,rmd160,coinaddr,pubkey33,i,0)) != balance-spent ) { printf("pkhash balance mismatch from m.%d check %.8f vs %.8f spent %.8f [%.8f]\n",m,dstr(netbalance),dstr(balance),dstr(spent),dstr(balance)-dstr(spent)); } @@ -304,6 +405,11 @@ int32_t iguana_pkhasharray(struct iguana_info *coin,cJSON *array,int32_t minconf void iguana_unspents(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *array,int32_t minconf,int32_t maxconf,uint8_t *rmdarray,int32_t numrmds) { int64_t total,sum=0; struct iguana_pkhash *P; uint8_t *addrtypes,*pubkeys; int32_t i,flag = 0; char coinaddr[64]; + if ( coin->RTramchain_busy != 0 ) + { + printf("iguana_pkhasharray: unexpected access when RTramchain_busy\n"); + return; + } if ( rmdarray == 0 ) rmdarray = iguana_walletrmds(myinfo,coin,&numrmds), flag++; addrtypes = &rmdarray[numrmds * 20], pubkeys = &rmdarray[numrmds * 21]; @@ -321,27 +427,6 @@ void iguana_unspents(struct supernet_info *myinfo,struct iguana_info *coin,cJSON free(rmdarray); } -uint8_t *iguana_rmdarray(struct iguana_info *coin,int32_t *numrmdsp,cJSON *array,int32_t firsti) -{ - int32_t i,n,j=0; char *coinaddr; uint8_t *addrtypes,*rmdarray = 0; - *numrmdsp = 0; - if ( array != 0 && (n= cJSON_GetArraySize(array)) > 0 ) - { - *numrmdsp = n - firsti; - rmdarray = calloc(1,(n-firsti) * 21); - addrtypes = &rmdarray[(n-firsti) * 20]; - for (i=firsti; icurrent) != 0 && bp->hdrsi == coin->longestchain/coin->chain->bundlesize && bp->hdrsi == coin->balanceswritten && coin->RTheight >= bp->bundleheight && coin->RTheight < bp->bundleheight+bp->n ) + if ( (bp= coin->current) != 0 && bp->hdrsi == coin->longestchain/coin->chain->bundlesize && bp->hdrsi == coin->balanceswritten && coin->RTheight >= bp->bundleheight && coin->RTheight < bp->bundleheight+bp->n )//&& coin->blocks.hwmchain.height >= coin->longestchain-1 && coin->RTramchain.H.data->numblocks < bp->n ) { iguana_RTramchainalloc(coin,bp); + bp->isRT = 1; while ( (rdata= coin->RTramchain.H.data) != 0 && coin->RTheight <= coin->blocks.hwmchain.height) { dest = &coin->RTramchain; @@ -978,9 +1064,9 @@ int32_t iguana_realtime_update(struct iguana_info *coin) } } } - if ( dest != 0 && flag != 0 ) + n = 0; + if ( dest != 0 && flag != 0 && coin->RTheight >= coin->longestchain ) { - n = 0; while ( block != 0 ) { if ( bits256_cmp(iguana_blockhash(coin,coin->RTheight-n-1),block->RO.hash2) != 0 ) @@ -998,8 +1084,9 @@ int32_t iguana_realtime_update(struct iguana_info *coin) printf("RTgenesis verified\n"); coin->RTgenesis = (uint32_t)time(NULL); } - printf(">>>> RT.%d:%d hwm.%d L.%d T.%d U.%d S.%d P.%d X.%d -> size.%ld\n",coin->RTheight,n,coin->blocks.hwmchain.height,coin->longestchain,dest->H.txidind,dest->H.unspentind,dest->H.spendind,dest->pkind,dest->externalind,(long)dest->H.data->allocsize); } + if ( dest != 0 ) + printf(">>>> RT.%d:%d hwm.%d L.%d T.%d U.%d S.%d P.%d X.%d -> size.%ld\n",coin->RTheight,n,coin->blocks.hwmchain.height,coin->longestchain,dest->H.txidind,dest->H.unspentind,dest->H.spendind,dest->pkind,dest->externalind,(long)dest->H.data->allocsize); return(0); } @@ -1120,9 +1207,10 @@ int32_t iguana_balanceflush(struct iguana_info *coin,int32_t refhdrsi,int32_t pu printf("error mapping bundle.[%d]\n",hdrsi); } char str[65]; printf("BALANCES WRITTEN for %d bundles %s\n",coin->balanceswritten,bits256_str(str,coin->balancehash)); - exit(-1); - coin->balanceswritten = iguana_volatileinit(coin); - iguana_RTramchainfree(coin); + iguana_coinpurge(coin); + //exit(-1); + //coin->balanceswritten = iguana_volatileinit(coin); + //iguana_RTramchainfree(coin); return(coin->balanceswritten); } diff --git a/iguana/iguana_wallet.c b/iguana/iguana_wallet.c index 6577d5a4f..a373647bd 100755 --- a/iguana/iguana_wallet.c +++ b/iguana/iguana_wallet.c @@ -15,6 +15,28 @@ #include "iguana777.h" + +uint8_t *iguana_rmdarray(struct iguana_info *coin,int32_t *numrmdsp,cJSON *array,int32_t firsti) +{ + int32_t i,n,j=0; char *coinaddr; uint8_t *addrtypes,*rmdarray = 0; + *numrmdsp = 0; + if ( array != 0 && (n= cJSON_GetArraySize(array)) > 0 ) + { + *numrmdsp = n - firsti; + rmdarray = calloc(1,(n-firsti) * 21); + addrtypes = &rmdarray[(n-firsti) * 20]; + for (i=firsti; iactive != 0 && (bp= coin->current) != 0 ) + if ( (coin= Coins[i]) != 0 && coin->current != 0 ) { - if ( coin->started != 0 ) + if ( coin->active != 0 && coin->started != 0 ) { + coin->RTramchain_busy = 1; iguana_realtime_update(coin); if ( (ptr= queue_dequeue(&balancesQ,0)) != 0 ) { flag++; if ( ptr->coin != 0 && (bp= ptr->bp) != 0 ) + { iguana_balancecalc(ptr->coin,bp,bp->bundleheight,bp->bundleheight+bp->n-1); + if ( coin->active == 0 ) + { + printf("detected autopurge after account filecreation. restarting.%s\n",coin->symbol); + coin->active = 1; + } + } myfree(ptr,ptr->allocsize); } + if ( (bp= coin->current) != 0 && coin->stucktime != 0 && coin->isRT == 0 && coin->RTheight == 0 && (time(NULL) - coin->stucktime) > coin->MAXSTUCKTIME ) + { + if ( bp->emitfinish == 0 && 0 ) + { + printf("%s is stuck too long, purging files for %d\n",coin->symbol,bp->hdrsi); + iguana_bundlepurgefiles(coin,bp); + for (j=0; jn; j++) + if ( (block= bp->blocks[j]) != 0 ) + { + block->fpipbits = 0; + block->RO.recvlen = 0; + block->fpos = -1; + } + sleep(5); + } + } + coin->RTramchain_busy = (coin->RTgenesis == 0 || queue_size(&balancesQ) != 0); } } } diff --git a/includes/iguana_apideclares.h b/includes/iguana_apideclares.h index 76d544ca3..1a7d3f5c8 100755 --- a/includes/iguana_apideclares.h +++ b/includes/iguana_apideclares.h @@ -137,6 +137,7 @@ STRING_ARG(iguana,getconnectioncount,activecoin); STRING_ARG(iguana,addcoin,newcoin); STRING_ARG(iguana,startcoin,activecoin); STRING_ARG(iguana,pausecoin,activecoin); +STRING_ARG(iguana,stopcoin,activecoin); TWO_STRINGS(iguana,addnode,activecoin,ipaddr); TWO_STRINGS(iguana,persistent,activecoin,ipaddr); TWO_STRINGS(iguana,removenode,activecoin,ipaddr);