bool process(void) { switch ( mMode ) { case CM_PROCESS: if ( mProcessBlock < mBlockChain->getBlockCount() && !isESC() ) { mCurrentBlock = mBlockChain->readBlock(mProcessBlock); if ( mCurrentBlock ) { if ( mLastTime == 0 ) { mLastTime = mCurrentBlock->timeStamp; mSatoshiTime = mCurrentBlock->timeStamp; } else { uint32_t currentTime = mCurrentBlock->timeStamp; time_t tnow(currentTime); struct tm beg; beg = *localtime(&tnow); time_t tbefore(mLastTime); struct tm before; before = *localtime(&tbefore); bool getStats = false; switch ( mStatResolution ) { case SR_DAY: if ( beg.tm_yday != before.tm_yday && currentTime > mLastTime ) { getStats = true; } break; case SR_MONTH: if ( beg.tm_mon != before.tm_mon && currentTime > mLastTime ) { getStats = true; } break; case SR_YEAR: if ( beg.tm_year != before.tm_year && currentTime > mLastTime ) { getStats = true; } break; case SR_LAST: break; } if ( getStats ) { if ( mProcessTransactions ) { const char *months[12] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; printf("Gathering statistics for %s %d, %d to %s %d, %d\r\n", months[before.tm_mon], before.tm_mday, before.tm_year+1900, months[beg.tm_mon], beg.tm_mday, beg.tm_year+1900); mBlockChain->gatherStatistics(mLastTime,static_cast<uint32_t>(zombieDate),mRecordAddresses); } if ( mTransactionValue ) { mBlockChain->reportTransactionValues(mLastTime); } mLastTime = currentTime; } } if ( mProcessTransactions ) { mBlockChain->processTransactions(mCurrentBlock); // process transactions into individual addresses } if ( mTransactionValue ) { mBlockChain->accumulateTransactionValues(mCurrentBlock); } } mProcessBlock++; if ( (mProcessBlock%1000) == 0 ) { printf("Processed block #%d of %d total.\r\n", mProcessBlock, mBlockChain->getBlockCount() ); } } else { printf("Finished processing all blocks in the blockchain.\r\n"); mBlockChain->reportCounts(); if ( mProcessTransactions ) { printf("Gathering final statistics.\r\n"); mBlockChain->gatherStatistics(mLastTime,static_cast<uint32_t>(zombieDate),mRecordAddresses); printf("Saving statistics to file 'stats.csv\r\n"); mBlockChain->saveStatistics(mRecordAddresses,mMinBalance); } mMode = CM_EXIT; mProcessBlock = 0; } break; case CM_SCAN: if ( isESC() ) { mMode = CM_EXIT; printf("ESC hit, exiting before processing any blocks.\r\n"); } else { bool ok = mBlockChain->readBlockHeaders(mMaxBlock,mLastBlockScan); if ( !ok ) { mFinishedScanning = true; mMode = CM_PROCESS; // done scanning. mLastBlockScan = mBlockChain->buildBlockChain(); printf("Finished scanning block headers. Built block-chain with %d blocks found..\r\n", mLastBlockScan); } } break; case CM_NONE: break; case CM_EXIT: break; } return mMode != CM_EXIT; }
bool process(void) { uint32_t argc; const char **argv = getInputString(argc); if ( argv ) { if ( strcmp(argv[0],"scan") == 0 ) { if ( mMode == CM_SCAN ) { printf("Pausing block-chain scan at block #%d\r\n", mLastBlockScan ); mMode = CM_NONE; } else { printf("Scanning block-chain re-started from block %d up to a maximum of %d blocks..\r\n", mLastBlockScan, mMaxBlock); mMode = CM_SCAN; } } else if ( strcmp(argv[0],"exit") == 0 || strcmp(argv[0],"bye") == 0 || strcmp(argv[0],"quit") == 0 ) { mMode = CM_EXIT; } else if ( strcmp(argv[0],"stop_scan") == 0 ) { if ( mFinishedScanning ) { printf("Already finished scanning the block-chain headers. Found %d blocks.\r\n", mLastBlockScan ); } else { stopScanning(); } } else if ( strcmp(argv[0],"help") == 0 ) { help(); } else if ( strcmp(argv[0],"max_blocks") == 0 ) { if ( argc >= 2 ) { mMaxBlock = atoi(argv[1]); if ( mMaxBlock < 1 ) mMaxBlock = 1; printf("Maximum block scan set to %d\r\n", mMaxBlock ); } } else if ( strcmp(argv[0],"by_day") == 0 ) { mStatResolution = SR_DAY; printf("Will accumulate statistics on a per-day basis.\r\n"); if ( !mProcessTransactions ) { printf("Note: You must enable 'statistics' for this to take effect.\r\n"); } } else if ( strcmp(argv[0],"by_month") == 0 ) { mStatResolution = SR_MONTH; printf("Will accumulate statistics on a monthly basis.\r\n"); if ( !mProcessTransactions ) { printf("Note: You must enable 'statistics' for this to take effect.\r\n"); } } else if ( strcmp(argv[0],"by_year") == 0 ) { mStatResolution = SR_YEAR; printf("Will accumulate statistics on an annual basis.\r\n"); if ( !mProcessTransactions ) { printf("Note: You must enable 'statistics' for this to take effect.\r\n"); } } else if ( strcmp(argv[0],"record_addresses") == 0 ) { mRecordAddresses = mRecordAddresses ? false : true; printf("record_addresses set to %s\r\n", mRecordAddresses ? "true" : "false"); } else if ( strcmp(argv[0],"adr") == 0 ) { if ( argc == 1 ) { printf("You must supply an address to output.\r\n"); } else { for (uint32_t i=1; i<argc; i++) { const char *adr = argv[i]; mBlockChain->printAddress(adr); } } } else if ( strcmp(argv[0],"process") == 0 ) { if ( mMode == CM_PROCESS ) { printf("Pausing processing block-chain blocks at block #%d of %d\r\n", mProcessBlock, mBlockChain->getBlockCount() ); mMode = CM_NONE; } else { if ( !mFinishedScanning ) { stopScanning(); } mProcessBlock = 0; mMode = CM_PROCESS; printf("Beginning processing of %d blocks : Gathering Statistics=%s\r\n", mBlockChain->getBlockCount(), mProcessTransactions ? "true":"false"); } } else if ( strcmp(argv[0],"statistics") == 0 ) { mProcessTransactions = mProcessTransactions ? false : true; if ( mProcessTransactions ) { printf("Block Processing will gather statistics.\r\n"); printf("*** WARNING : This will consume an enormous amount of memory! ***\r\n"); } else { printf("Block processing will not gather statistics.\r\n"); } } else if ( strcmp(argv[0],"load_record") == 0 ) { if ( mAddresses ) { mAddresses->release(); mAddresses = NULL; } printf("Loading previously recorded addresses from file 'BlockChainAddresses.bin\r\n"); mAddresses = createBlockChainAddresses("BlockChainAddresses.bin"); } else if ( strcmp(argv[0],"min_balance") == 0 ) { if ( argc == 1 ) { printf("No minimum balance specified, defaulting to 1btc.\r\n"); } else { mMinBalance = (uint32_t)atoi(argv[1]); if ( mMinBalance < 1 ) { mMinBalance = 1; } else { if ( mMinBalance > 1000000 ) { mMinBalance = 1000000; } } printf("Minimum balance set to %d bitcoins.\r\n", mMinBalance ); } } else if ( strcmp(argv[0],"top_balance") == 0 ) { uint32_t tcount = 100; if ( argc >= 2 ) { tcount = atoi(argv[1]); if ( tcount < 1 ) { tcount = 1; } } printf("Printing the most valuable %d bitcoin addresses with a balance of more than %d bitcoins.\r\n", tcount, mMinBalance ); mBlockChain->printTopBalances(tcount,mMinBalance); } else if ( strcmp(argv[0],"oldest") == 0 ) { uint32_t tcount = 100; if ( argc >= 2 ) { tcount = atoi(argv[1]); if ( tcount < 1 ) { tcount = 1; } } printf("Printing the %d oldest bitcoin addresses with a balance of more than %d bitcoins.\r\n", tcount, mMinBalance ); mBlockChain->printOldest(tcount,mMinBalance); } else if ( strcmp(argv[0],"zombie") == 0 ) { uint32_t zdays = 365; if ( argc >=2 ) { zdays = atoi(argv[1]); if ( zdays < 1 ) { zdays = 1; } } printf("Generating Zombie Count for addresses older than %d days with a balance of more than %d bitcoins.\r\n", zdays, mMinBalance ); mBlockChain->zombieReport(zdays,mMinBalance); } else if ( strcmp(argv[0],"by_day") == 0 ) { mStatResolution = SR_DAY; printf("Gathering statistics every day.\r\n"); } else if ( strcmp(argv[0],"by_month") == 0 ) { mStatResolution = SR_MONTH; printf("Gathering statistics every month.\r\n"); } else if ( strcmp(argv[0],"by_year") == 0 ) { mStatResolution = SR_YEAR; printf("Gathering statistics every year.\r\n"); } else if ( strcmp(argv[0],"counts") == 0 ) { mBlockChain->reportCounts(); } else if ( strcmp(argv[0],"block") == 0 ) { if ( argc == 1 ) { if ( mCurrentBlock ) { mBlockChain->printBlock(mCurrentBlock); mCurrentBlock = mBlockChain->readBlock(mCurrentBlock->blockIndex+1); } } else { for (uint32_t i=1; i<argc; i++) { uint32_t index = (uint32_t)atoi(argv[i]); mCurrentBlock = getBlock(index); if ( mCurrentBlock ) { mBlockChain->printBlock(mCurrentBlock); } } } } } switch ( mMode ) { case CM_PROCESS: if ( mProcessBlock < mBlockChain->getBlockCount() ) { mCurrentBlock = mBlockChain->readBlock(mProcessBlock); if ( mCurrentBlock && mProcessTransactions ) { if ( mLastTime == 0 ) { mLastTime = mCurrentBlock->timeStamp; mSatoshiTime = mCurrentBlock->timeStamp; } else { uint32_t currentTime = mCurrentBlock->timeStamp; time_t tnow(currentTime); struct tm beg; beg = *localtime(&tnow); time_t tbefore(mLastTime); struct tm before; before = *localtime(&tbefore); bool getStats = false; switch ( mStatResolution ) { case SR_DAY: if ( beg.tm_yday != before.tm_yday ) { getStats = true; } break; case SR_MONTH: if ( beg.tm_mon != before.tm_mon ) { getStats = true; } break; case SR_YEAR: if ( beg.tm_year != before.tm_year ) { getStats = true; } break; } if ( getStats ) { const char *months[12] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; printf("Gathering statistics for %s %d, %d to %s %d, %d\r\n", months[before.tm_mon], before.tm_mday, before.tm_year+1900, months[beg.tm_mon], beg.tm_mday, beg.tm_year+1900); mBlockChain->gatherStatistics(mLastTime,(uint32_t)zombieDate,mRecordAddresses); mLastTime = currentTime; } } mBlockChain->processTransactions(mCurrentBlock); // process transactions into individual addresses } mProcessBlock++; if ( (mProcessBlock%10000) == 0 ) { printf("Processed block #%d of %d total.\r\n", mProcessBlock, mBlockChain->getBlockCount() ); } } else { printf("Finished processing all blocks in the blockchain.\r\n"); mBlockChain->reportCounts(); if ( mProcessTransactions ) { printf("Gathering final statistics.\r\n"); mBlockChain->gatherStatistics(mLastTime,(uint32_t)zombieDate,mRecordAddresses); printf("Saving statistics to file 'stats.csv\r\n"); mBlockChain->saveStatistics(mRecordAddresses); } mMode = CM_NONE; mProcessBlock = 0; } break; case CM_SCAN: { bool ok = mBlockChain->readBlockHeaders(mMaxBlock,mLastBlockScan); if ( !ok ) { mFinishedScanning = true; mMode = CM_NONE; // done scanning. mLastBlockScan = mBlockChain->buildBlockChain(); printf("Finished scanning block headers. Built block-chain with %d blocks found..\r\n", mLastBlockScan); printf("To resolve transactions you must execute the 'process' command.\r\n"); printf("To gather statistics so you can ouput balances of individual addresses, you must execute the 'statistics' command prior to running the process command.\r\n"); } } break; } return mMode != CM_EXIT; }