virtual int init( int argc, const char *argv[] ) { txID = 0; blkID = 0; active = 0; optparse::Values &values = parser.parse_args(argc, argv); firstBlock = values.get("firstBlock"); lastBlock = values.get("lastBlock"); info("Dumping the blockchain..."); blockFile = fopen("blocks.csv", "w"); if(!blockFile) sysErrFatal("couldn't open file blocks.csv for writing\n"); fprintf(blockFile, "ID,Hash,Version,Timestamp,Nonce,Difficulty,Merkle,NumTransactions,OutputValue,FeesValue,Size\n"); txFile = fopen("transactions.csv", "w"); if(!txFile) sysErrFatal("couldn't open file txs.csv for writing\n"); fprintf(txFile, "ID,Hash,Version,BlockId,NumInputs,NumOutputs,OutputValue,FeesValue,LockTime,Size\n"); outputFile = fopen("outputs.csv", "w"); if(!outputFile) sysErrFatal("couldn't open file outputs.csv for writing\n"); fprintf(outputFile, "TransactionId,Index,Value,Script,ReceivingAddress,InputTxHash,InputTxIndex\n"); inputFile = fopen("inputs.csv", "w"); if(!inputFile) sysErrFatal("couldn't open file inputs.csv for writing\n"); fprintf(inputFile, "TransactionId,Index,Script,OutputTxHash,OutputTxIndex\n"); return 0; }
static void findBlockFiles() { gChainSize = 0; auto blockChainDir = getBlockchainDir(); auto blockDir = blockChainDir + std::string("/blocks"); info("loading block chain from directory: %s", blockChainDir.c_str()); struct stat statBuf; auto r = stat(blockDir.c_str(), &statBuf); auto oldStyle = (r<0 || !S_ISDIR(statBuf.st_mode)); int blkDatId = (oldStyle ? 1 : 0); auto fmt = oldStyle ? "/blk%04d.dat" : "/blocks/blk%05d.dat"; while(1) { char buf[64]; sprintf(buf, fmt, blkDatId++); auto fileName = blockChainDir + std::string(buf) ; auto fd = open(fileName.c_str(), O_RDONLY); if(fd<0) { if(1<blkDatId) { break; } sysErrFatal( "failed to open block chain file %s", fileName.c_str() ); } struct stat statBuf; auto r0 = fstat(fd, &statBuf); if(r0<0) { sysErrFatal( "failed to fstat block chain file %s", fileName.c_str() ); } auto fileSize = statBuf.st_size; #if !defined(_WIN64) auto r1 = posix_fadvise(fd, 0, fileSize, POSIX_FADV_NOREUSE); if(r1<0) { warning( "failed to posix_fadvise on block chain file %s", fileName.c_str() ); } #endif BlockFile blockFile; blockFile.fd = fd; blockFile.size = fileSize; blockFile.name = fileName; blockFiles.push_back(blockFile); gChainSize += fileSize; } info("block chain size = %.3f Gigs", 1e-9*gChainSize); }
static void makeBlockMaps() { auto blockChainDir = getBlockchainDir(); auto blockDir = blockChainDir + std::string("/blocks"); info("loading block chain from: %s", blockChainDir.c_str()); struct stat statBuf; auto r = stat(blockDir.c_str(), &statBuf); auto oldStyle = (r<0 || !S_ISDIR(statBuf.st_mode)); int blkDatId = (oldStyle ? 1 : 0); auto fmt = oldStyle ? "/blk%04d.dat" : "/blocks/blk%05d.dat"; while(1) { char buf[64]; sprintf(buf, fmt, blkDatId++); auto blockMapFileName = blockChainDir + std::string(buf) ; auto blockMapFD = open(blockMapFileName.c_str(), O_RDONLY); if(blockMapFD<0) { if(1<blkDatId) { break; } sysErrFatal( "failed to open block chain file %s", blockMapFileName.c_str() ); } struct stat statBuf; int st0 = fstat(blockMapFD, &statBuf); if(st0<0) { sysErrFatal( "failed to fstat block chain file %s", blockMapFileName.c_str() ); } auto mapSize = statBuf.st_size; auto st1 = posix_fadvise(blockMapFD, 0, mapSize, POSIX_FADV_NOREUSE); if(st1<0) { warning( "failed to posix_fadvise on block chain file %s", blockMapFileName.c_str() ); } Map map; map.size = mapSize; map.fd = blockMapFD; map.name = blockMapFileName; mapVec.push_back(map); } }
static void findBlockParent( Block *b ) { auto where = lseek64( b->chunk->getMap()->fd, b->chunk->getOffset(), SEEK_SET ); if(where!=(signed)b->chunk->getOffset()) { sysErrFatal( "failed to seek into block chain file %s", b->chunk->getMap()->name.c_str() ); } uint8_t buf[gHeaderSize]; auto nbRead = read( b->chunk->getMap()->fd, buf, gHeaderSize ); if(nbRead<(signed)gHeaderSize) { sysErrFatal( "failed to read from block chain file %s", b->chunk->getMap()->name.c_str() ); } auto i = gBlockMap.find(4 + buf); if(unlikely(gBlockMap.end()==i)) { uint8_t bHash[2*kSHA256ByteSize + 1]; toHex(bHash, b->hash); uint8_t pHash[2*kSHA256ByteSize + 1]; toHex(pHash, 4 + buf); warning( "in block %s failed to locate parent block %s", bHash, pHash ); return; } b->prev = i->second; }
static void mapBlockChainFiles() { std::string coinName( #if defined REDDCOIN "/.reddcoin/" #else "/.bitcoin/" #endif ); const char *home = getenv("HOME"); if(0==home) { warning("could not getenv(\"HOME\"), using \".\" instead."); home = "."; } std::string homeDir(home); std::string blockDir = homeDir + coinName + std::string("blocks"); struct stat statBuf; int r = stat(blockDir.c_str(), &statBuf); bool oldStyle = (r<0 || !S_ISDIR(statBuf.st_mode)); int blkDatId = oldStyle ? 1 : 0; const char *fmt = oldStyle ? "blk%04d.dat" : "blocks/blk%05d.dat"; while(1) { char buf[64]; sprintf(buf, fmt, blkDatId++); std::string blockMapFileName = homeDir + coinName + std::string(buf) ; int blockMapFD = open(blockMapFileName.c_str(), O_DIRECT | O_RDONLY); if(blockMapFD<0) { if(1<blkDatId) break; sysErrFatal( "failed to open block chain file %s", blockMapFileName.c_str() ); } struct stat statBuf; int r = fstat(blockMapFD, &statBuf); if(r<0) sysErrFatal( "failed to fstat block chain file %s", blockMapFileName.c_str()); size_t mapSize = statBuf.st_size; void *pMap = mmap(0, mapSize, PROT_READ, MAP_PRIVATE, blockMapFD, 0); if(((void*)-1)==pMap) { sysErrFatal( "failed to mmap block chain file %s", blockMapFileName.c_str() ); } Map map; map.size = mapSize; map.fd = blockMapFD; map.name = blockMapFileName; map.p = (const uint8_t*)pMap; mapVec.push_back(map); } }
virtual int init( int argc, const char *argv[] ) { txID = -1; blkID = 0; inputID = 0; outputID = 0; static uint64_t sz = 32 * 1000 * 1000; outputMap.setEmptyKey(empty); outputMap.resize(sz); optparse::Values& values = parser.parse_args(argc, argv); lastBlock = values.get("atBlock").asUInt64(); if (!file_exists("../blockchain/blockchain.sqlite")) { firstBlock = 0; } else { sqlite3pp::database db("../blockchain/blockchain.sqlite"); sqlite3pp::query qry(db, "SELECT MAX(block_id) FROM blocks"); sqlite3pp::query::iterator i = qry.begin(); firstBlock = (uint64_t)atoi((*i).get<char const *>(0)) + 1; info("Resuming from block %" PRIu64 ".\n", firstBlock); } info("Dumping the blockchain..."); txFile = fopen("tx.txt", "w"); if (!txFile) sysErrFatal("couldn't open file txs.txt for writing\n"); blockFile = fopen("blocks.txt", "w"); if (!blockFile) sysErrFatal("couldn't open file blocks.txt for writing\n"); inputFile = fopen("txin.txt", "w"); if (!inputFile) sysErrFatal("couldn't open file inputs.txt for writing\n"); outputFile = fopen("txout.txt", "w"); if (!outputFile) sysErrFatal("couldn't open file outputs.txt for writing\n"); FILE *sqlFile = fopen("blockchain.sql", "w"); if (!sqlFile) sysErrFatal("couldn't open file blockChain.sql for writing\n"); fprintf( sqlFile, "PRAGMA journal_mode=MEMORY;\n" "PRAGMA synchronous=0;\n" "CREATE TABLE IF NOT EXISTS blocks(\n" " block_id BIGINT NOT NULL PRIMARY KEY,\n" " block_hash TEXT NOT NULL,\n" " time BIGINT NOT NULL\n" ");\n" "\n" "CREATE TABLE IF NOT EXISTS tx(\n" " tx_id BIGINT NOT NULL PRIMARY KEY,\n" " tx_hash TEXT NOT NULL,\n" " block_id BIGINT NOT NULL,\n" " FOREIGN KEY (block_id) REFERENCES blocks (block_id)\n" ");\n" "\n" "CREATE TABLE IF NOT EXISTS txout(\n" " txout_id BIGINT NOT NULL PRIMARY KEY,\n" " address CHAR(40),\n" " txout_value BIGINT NOT NULL,\n" " tx_id BIGINT NOT NULL,\n" " txout_pos INT NOT NULL,\n" " FOREIGN KEY (tx_id) REFERENCES tx (tx_id)\n" ");\n" "\n" "CREATE TABLE IF NOT EXISTS txin(\n" " txin_id BIGINT NOT NULL PRIMARY KEY,\n" " txout_id BIGINT NOT NULL,\n" " tx_id BIGINT NOT NULL,\n" " txin_pos INT NOT NULL,\n" " FOREIGN KEY (tx_id) REFERENCES tx (tx_id)\n" ");\n" "CREATE INDEX IF NOT EXISTS x_txin_txout ON txin (txout_id);\n" "CREATE INDEX IF NOT EXISTS x_txout_address ON txout (address);\n" "CREATE INDEX IF NOT EXISTS x_txin_txid ON txin (tx_id);\n" "CREATE INDEX IF NOT EXISTS x_txout_txid ON txout (tx_id);\n" "CREATE INDEX IF NOT EXISTS x_txout_value ON txout (txout_value);\n" "CREATE VIEW IF NOT EXISTS tx_full AS SELECT blocks.time, tx.tx_hash, tx.tx_id, txout.address, txout.txout_value FROM txout LEFT JOIN tx ON (tx.tx_id = txout.tx_id) LEFT JOIN blocks ON (tx.block_id = blocks.block_id);\n" "\n" ); fclose(sqlFile); FILE *bashFile = fopen("blockchain.sh", "w"); if (!bashFile) sysErrFatal("Couldn't open file blockchain.sh for writing!\n"); fprintf( bashFile, "\n" "#!/bin/bash\n" "\n" "echo 'Recreating DB blockchain...'\n" "mkdir ../blockchain\n" "sqlite3 ../blockchain/blockchain.sqlite < blockchain.sql\n" "rm -f blockchain.sql\n" "echo done.\n" "echo\n" "rm -f blockchain.sql\n" "\n" "for i in blocks txin txout tx\n" "do\n" " echo \"Importing table ${i}...\"\n" " echo \".import $i.txt $i\" | sqlite3 ../blockchain/blockchain.sqlite\n" " echo done.\n" " rm -f $i.txt\n" " echo\n" "done\n" "rm -f blockchain.sh\n" "\n" ); fclose(bashFile); return 0; }
virtual int init( int argc, const char *argv[] ) { txID = 0; blkID = 0; inputID = 0; outputID = 0; static uint64_t sz = 32 * 1000 * 1000; outputMap.setEmptyKey(empty); outputMap.resize(sz); optparse::Values &values = parser.parse_args(argc, argv); cutoffBlock = values.get("atBlock"); info("dumping the blockchain ..."); txFile = fopen("transactions.txt", "w"); if(!txFile) sysErrFatal("couldn't open file txs.txt for writing\n"); blockFile = fopen("blocks.txt", "w"); if(!blockFile) sysErrFatal("couldn't open file blocks.txt for writing\n"); inputFile = fopen("inputs.txt", "w"); if(!inputFile) sysErrFatal("couldn't open file inputs.txt for writing\n"); outputFile = fopen("outputs.txt", "w"); if(!outputFile) sysErrFatal("couldn't open file outputs.txt for writing\n"); FILE *sqlFile = fopen("blockChain.sql", "w"); if(!sqlFile) sysErrFatal("couldn't open file blockChain.sql for writing\n"); fprintf( sqlFile, "\n" "DROP DATABASE IF EXISTS blockChain;\n" "CREATE DATABASE blockChain;\n" "USE blockChain;\n" "\n" "DROP TABLE IF EXISTS transactions;\n" "DROP TABLE IF EXISTS outputs;\n" "DROP TABLE IF EXISTS inputs;\n" "DROP TABLE IF EXISTS blocks;\n" "\n" "CREATE TABLE blocks(\n" " id BIGINT PRIMARY KEY,\n" " hash BINARY(32),\n" " time BIGINT\n" ");\n" "\n" "CREATE TABLE transactions(\n" " id BIGINT PRIMARY KEY,\n" " hash BINARY(32),\n" " blockID BIGINT\n" ");\n" "\n" "CREATE TABLE outputs(\n" " id BIGINT PRIMARY KEY,\n" " dstAddress CHAR(36),\n" " value BIGINT,\n" " txID BIGINT,\n" " offset INT\n" ");\n" "\n" "CREATE TABLE inputs(\n" " id BIGINT PRIMARY KEY,\n" " outputID BIGINT,\n" " txID BIGINT,\n" " offset INT\n" ");\n" "\n" ); fclose(sqlFile); FILE *bashFile = fopen("blockChain.bash", "w"); if(!bashFile) sysErrFatal("couldn't open file blockChain.bash for writing\n"); fprintf( bashFile, "\n" "#!/bin/bash\n" "\n" "echo\n" "\n" "echo 'wiping/re-creating DB blockChain ...'\n" "time mysql -u root -p -hlocalhost --password='' < blockChain.sql\n" "echo done\n" "echo\n" "\n" "for i in blocks inputs outputs transactions\n" "do\n" " echo Importing table $i ...\n" " time mysqlimport -u root -p -hlocalhost --password='' --lock-tables --use-threads=3 --local blockChain $i.txt\n" " echo done\n" " echo\n" "done\n" "\n" ); fclose(bashFile); return 0; }