/****************************************************************************** * Copyright © 2014-2015 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. * * * ******************************************************************************/ #ifdef DEFINES_ONLY #ifndef txind777_h #define txind777_h #include #include #include #include #include "../iguana777.h" #define BTCDADDRSIZE 36 struct txinds777_hdr { int64_t num,nextpos; uint32_t blocknum,timestamp,firstblocknum,lastblocknum; struct sha256_vstate state; bits256 sha256; }; struct txinds777_info { struct txinds777_hdr H; FILE *txlogfp,*indexfp,*fp; char path[512],name[64]; int64_t curitem,*blockitems; }; int64_t txind777_bundle(struct txinds777_info *txinds,uint32_t blocknum,uint32_t timestamp,int64_t *bundle,int32_t numtx); int64_t txind777_create(struct txinds777_info *txinds,uint32_t blocknum,uint32_t timestamp,void *txdata,uint16_t len); int32_t txind777_txbuf(uint8_t *txbuf,int32_t len,uint64_t val,int32_t size); int32_t txinds777_flush(struct txinds777_info *txinds,uint32_t blocknum,uint32_t blocktimestamp); struct txinds777_info *txinds777_init(char *path,char *name); int64_t txinds777_seek(struct txinds777_info *txinds,uint32_t blocknum); void *txinds777_read(int32_t *lenp,uint8_t *buf,struct txinds777_info *txinds); void txinds777_purge(struct txinds777_info *txinds); #endif #else #ifndef txind777_c #define txind777_c #ifndef txind777_h #define DEFINES_ONLY #include "txind777.c" #undef DEFINES_ONLY #endif void txinds777_purge(struct txinds777_info *txinds) { if ( txinds->fp != 0 ) fclose(txinds->fp); if ( txinds->txlogfp != 0 ) fclose(txinds->txlogfp); if ( txinds->indexfp != 0 ) fclose(txinds->indexfp); if ( txinds->blockitems != 0 ) free(txinds->blockitems); memset(txinds,0,sizeof(*txinds)); } int64_t txinds777_seek(struct txinds777_info *txinds,uint32_t blocknum) { if ( txinds->blockitems != 0 && blocknum >= txinds->H.firstblocknum && blocknum <= txinds->H.lastblocknum ) txinds->curitem = txinds->blockitems[blocknum - txinds->H.firstblocknum]; else txinds->curitem = 0; return(txinds->curitem); } void *txinds777_read(int32_t *lenp,uint8_t *buf,struct txinds777_info *txinds) { int64_t txind,fpos; int32_t len; uint32_t triplet[3]; *lenp = 0; if ( txinds->indexfp == 0 || txinds->txlogfp == 0 ) return(0); fseek(txinds->indexfp,txinds->curitem * sizeof(int64_t),SEEK_SET); if ( fread(&txind,1,sizeof(txind),txinds->indexfp) != sizeof(txind) ) { printf("error reading txindex.%lld file at pos %lld\n",(long long)txinds->curitem,(long long)(txinds->curitem * sizeof(txind))); return(0); } len = txind & 0xffff; fpos = (txind >> 16); if ( fpos+len <= txinds->H.nextpos ) { printf("load %ld for item.%d log.%ld\n",ftell(txinds->indexfp),(int32_t)txinds->curitem,(long)fpos); fseek(txinds->txlogfp,fpos,SEEK_SET); if ( len >= sizeof(triplet) && fread(triplet,1,sizeof(triplet),txinds->txlogfp) == sizeof(triplet) && len > sizeof(triplet) ) { len -= sizeof(triplet); if ( fread(buf,1,len,txinds->txlogfp) == len ) { *lenp = len; return(buf); } } } return(0); } void txinds777_ensure(struct txinds777_info *txinds,uint32_t blocknum,uint64_t curitem) { int32_t offset,oldrange,newrange; if ( txinds->blockitems == 0 ) { txinds->blockitems = realloc(txinds->blockitems,sizeof(*txinds->blockitems)); txinds->H.firstblocknum = txinds->H.lastblocknum = blocknum; } else if ( blocknum > txinds->H.lastblocknum ) { oldrange = (txinds->H.lastblocknum - txinds->H.firstblocknum + 1); newrange = (blocknum - txinds->H.firstblocknum + 1); txinds->blockitems = realloc(txinds->blockitems,sizeof(*txinds->blockitems) * newrange); if ( newrange > oldrange+1 ) memset(&txinds->blockitems[oldrange],0,(newrange - oldrange)); txinds->H.lastblocknum = blocknum; } offset = (blocknum - txinds->H.firstblocknum); txinds->blockitems[offset] = curitem; } int64_t txind777_create(struct txinds777_info *txinds,uint32_t blocknum,uint32_t timestamp,void *txdata,uint16_t len) { int64_t txind = -1; uint32_t triplet[3]; if ( txdata == 0 || txinds == 0 ) return(0); if ( len != 0 ) { txind = (txinds->H.nextpos << 16) | (len + sizeof(triplet)); if ( txinds->txlogfp != 0 ) { triplet[0] = len, triplet[1] = blocknum, triplet[2] = timestamp; //printf("triplet.(%d %d %d)\n",len,blocknum,timestamp); fseek(txinds->txlogfp,txinds->H.nextpos,SEEK_SET); if ( fwrite(triplet,1,sizeof(triplet),txinds->txlogfp) != sizeof(triplet) || fwrite(txdata,1,len,txinds->txlogfp) != len ) { printf("error updating txlog file at pos %lld\n",(long long)txinds->H.nextpos); return(-1); } } if ( txinds->indexfp != 0 ) { txinds777_ensure(txinds,blocknum,txinds->H.num); fseek(txinds->indexfp,txinds->H.num * sizeof(txind),SEEK_SET); if ( fwrite(&txind,1,sizeof(txind),txinds->indexfp) != sizeof(txind) ) { printf("error updating txindex file at pos %lld\n",(long long)(txinds->H.num * sizeof(txind))); return(-1); } txinds->H.num++; // printf("H.num %d: indexfp %ld\n",(int32_t)txinds->H.num,ftell(txinds->indexfp)); } vupdate_sha256(txinds->H.sha256.bytes,&txinds->H.state,txdata,len); txinds->H.nextpos += len + sizeof(triplet); //printf("H.num %d, nextpos %ld (len %ld) indexfp %ld logfp %ld\n",(int32_t)txinds->H.num,(long)txinds->H.nextpos,len + sizeof(triplet),ftell(txinds->indexfp),ftell(txinds->txlogfp)); } else printf("cant txlog no data\n"); return(txind); } int64_t txind777_bundle(struct txinds777_info *txinds,uint32_t blocknum,uint32_t timestamp,int64_t *bundle,int32_t numtx) { if ( bundle != 0 ) return(txind777_create(txinds,blocknum,timestamp,bundle,numtx * sizeof(*txinds))); else return(0); } FILE *txinds777_initfile(long *fposp,char *path,char *name,char *suffix,uint64_t expected) { FILE *fp; char fname[512]; long fpos = 0; sprintf(fname,"%s/%s%s",path,name,suffix), iguana_compatible_path(fname); if ( (fp= fopen(fname,"rb+")) != 0 ) { fseek(fp,0,SEEK_END); if ( (fpos= ftell(fp)) != expected ) { printf("txinds777_init: warning mismatched position %ld vs %lld\n",fpos,(long long)expected); fseek(fp,expected,SEEK_SET); if ( (fpos= ftell(fp)) != expected ) printf("txinds777_init: error mismatched position %ld vs %lld after set fpos\n",fpos,(long long)expected); } } else fp = fopen(fname,"wb+"); *fposp = fpos; return(fp); } struct txinds777_info *txinds777_init(char *path,char *name) { FILE *fp; char fname[512]; int64_t txind,checktxind; long logfpos,indexfpos; struct txinds777_hdr H,goodH; uint32_t triplet[3]; struct txinds777_info *txinds = calloc(1,sizeof(*txinds)); strcpy(txinds->path,path), strcpy(txinds->name,name); sprintf(fname,"%s/%s",path,name), iguana_compatible_path(fname); printf("txinds777_init(%s,%s)\n",path,name); if ( (fp= fopen(fname,"rb+")) != 0 ) { if ( fread(&txinds->H,1,sizeof(txinds->H),fp) == sizeof(txinds->H) ) { txinds->txlogfp = txinds777_initfile(&logfpos,path,name,".log",txinds->H.nextpos); txinds->indexfp = txinds777_initfile(&indexfpos,path,name,".index",sizeof(uint64_t) * txinds->H.num); if ( txinds->txlogfp != 0 && txinds->indexfp != 0 ) { memset(&goodH,0,sizeof(goodH)); while ( fread(&H,1,sizeof(H),fp) == sizeof(H) ) { if ( H.num*sizeof(uint64_t) > indexfpos || H.nextpos > logfpos ) break; goodH = H; //printf("loaded H nextpos %d num.%d\n",(int32_t)H.nextpos,(int32_t)H.num); } txinds->H = goodH; if ( txinds->H.nextpos > 0 ) { txinds->curitem = 0; rewind(txinds->txlogfp); rewind(txinds->indexfp); while ( txinds->curitem < txinds->H.num ) { if ( fread(&txind,1,sizeof(txind),txinds->indexfp) != sizeof(txind) ) break; logfpos = ftell(txinds->txlogfp); if ( fread(triplet,1,sizeof(triplet),txinds->txlogfp) == sizeof(triplet) ) { //printf("triplet.(%d %d %d)\n",triplet[0],triplet[1],triplet[2]); if ( (triplet[0] + logfpos) > txinds->H.nextpos ) break; checktxind = (logfpos << 16) | (triplet[0] + sizeof(triplet)); if ( checktxind != txind ) { printf("checktxind error item.%lld %llx != %llx\n",(long long)txinds->curitem,(long long)checktxind,(long long)txind); txinds->H.num = txinds->curitem; txinds->H.nextpos = logfpos; break; } txinds777_ensure(txinds,triplet[1],txinds->curitem++); fseek(txinds->txlogfp,logfpos + (triplet[0] + sizeof(triplet)),SEEK_SET); } } printf("verified %lld items, curpos %ld %ld\n",(long long)txinds->curitem,ftell(txinds->indexfp),ftell(txinds->txlogfp)); } } else { if ( txinds->txlogfp != 0 ) fclose(txinds->txlogfp), txinds->txlogfp = 0; if ( txinds->indexfp != 0 ) fclose(txinds->indexfp), txinds->indexfp = 0; } } txinds->fp = fp; } else if ( (txinds->fp= fopen(fname,"wb+")) != 0 ) fwrite(&txinds->H,1,sizeof(txinds->H),txinds->fp); if ( txinds->txlogfp == 0 || txinds->indexfp == 0 ) vupdate_sha256(txinds->H.sha256.bytes,&txinds->H.state,0,0); if ( txinds->txlogfp == 0 ) txinds->txlogfp = txinds777_initfile(&logfpos,path,name,".log",0); if ( txinds->indexfp == 0 ) txinds->indexfp = txinds777_initfile(&indexfpos,path,name,".index",0); //printf("fps %p %p %p\n",txinds->fp,txinds->txlogfp,txinds->indexfp); return(txinds); } int32_t txind777_txbuf(uint8_t *txbuf,int32_t len,uint64_t val,int32_t size) { int32_t i; if ( txbuf != 0 ) for (i=0; i>=8) txbuf[len++] = (val & 0xff); return(len); } int32_t txinds777_flush(struct txinds777_info *txinds,uint32_t blocknum,uint32_t blocktimestamp) { long fpos; if ( txinds != 0 ) { if ( txinds->txlogfp != 0 ) fflush(txinds->txlogfp); if ( txinds->indexfp != 0 ) fflush(txinds->indexfp); txinds->H.blocknum = blocknum, txinds->H.timestamp = blocktimestamp; if ( txinds->fp != 0 ) { fwrite(&txinds->H,1,sizeof(txinds->H),txinds->fp); fpos = ftell(txinds->fp); rewind(txinds->fp); fwrite(&txinds->H,1,sizeof(txinds->H),txinds->fp); fseek(txinds->fp,fpos,SEEK_SET); fflush(txinds->fp); } //printf("txinds777_flush.(%s)\n",txinds->name); } else { printf("txinds777_flush null ptr\n"); //getchar(); } return(0); } #endif #endif