//j.恢复区块池上下文状态 public void restore_blockReadBlocksFromFile(List <FileStatusItem_Class> fileStatusList) { foreach (FileStatusItem_Class fileStatusItemObject in fileStatusList) { blockCountOfFile.Add(fileStatusItemObject.totalBlocks); if (fileStatusItemObject.unusedBlocks == 0) { for (int i = 0; i < fileStatusItemObject.totalBlocks; i++) { blockReadBlocksFromFile.Add(null); } } else { IBlockchainParser blockFileParser = new BlockchainParser(blockchainFilePath, fileStatusItemObject.fileName, 1); List <ParserBlock> blocksOfFile = blockFileParser.ParseBlockchain().ToList(); foreach (ParserBlock block in blocksOfFile) { if (fileStatusItemObject.unusedBlockHash.Contains(block.Header.GetHash().ToString())) { blockReadBlocksFromFile.Add(block); } else { blockReadBlocksFromFile.Add(null); } } } } }
//g.获取创世区块 public ParserBlock get_GenesisBlock(bool displayMark) { if (Directory.Exists(blockchainFilePath)) { Console.WriteLine("正在获取创世区块........."); string blockfileName = get_filename(0); string blockchainFile = Path.Combine(blockchainFilePath, blockfileName); if (File.Exists(blockchainFile)) { IBlockchainParser blockFileParser = new BlockchainParser(blockchainFilePath, blockfileName, 1); List <ParserBlock> blocksOfFirstBlockFile = blockFileParser.ParseBlockchain().ToList(); ParserBlock genesisBlock = blocksOfFirstBlockFile[0]; if (displayMark) { Console.WriteLine("创世区块前一个区块hash:" + genesisBlock.Header.HashPrevBlock); Console.WriteLine("创世区块time:" + genesisBlock.Header.BlockTime); Console.WriteLine("创世区块hash:" + genesisBlock.Header.GetHash()); Console.WriteLine("**********************************************************"); } return(genesisBlock); } else { Console.WriteLine("区块文件:" + blockchainFile + " 不存在!!!"); return(null); } } else { Console.WriteLine("区块链文件路径不存在!!!"); return(null); } }
//b.加载下一个区块文件到区块池 public void load_NextFile_ToBlockPooling() { if (Directory.Exists(blockchainFilePath)) { currentLoadFileNumber++; string blockfileName = get_filename(currentLoadFileNumber); string blockfile = Path.Combine(blockchainFilePath, blockfileName); Console.WriteLine("正在加载:" + blockfile); if (File.Exists(blockfile)) { IBlockchainParser blockFileParser = new BlockchainParser(blockchainFilePath, blockfileName, 1); List <ParserBlock> blocksOfOneBlockFile = blockFileParser.ParseBlockchain().ToList(); blockReadBlocksFromFile.AddRange(blocksOfOneBlockFile); blockCountOfFile.Add(blocksOfOneBlockFile.Count); } else { missingBlockFile = true; Console.WriteLine("区块文件:" + blockfile + " 不存在!!!"); } } else { Console.WriteLine("区块链文件路径不存在!!!"); } }
//(弃)(可以直接读取一个文件) //5.读取一个编号blk*****文件夹下的blk00000.dat文件 public List <Block> load_one_blockfile(string blockFilePath) { List <Block> oneFileBlockData = new List <Block>(); IBlockchainParser blockFileParser = new BlockchainParser(blockFilePath); IEnumerable <Block> blocks = blockFileParser.ParseBlockchain(); oneFileBlockData = blocks.ToList(); return(oneFileBlockData); }
private static void ParseBlockchainFiles(string pathToBlockchain) { BlockchainStatistics overallStatistics = new BlockchainStatistics(); BlockchainStatistics blockFileStatistics = new BlockchainStatistics(); string currentBlockchainFile = null; // Instantiate a BlockchainParser. We will pass the path to the blockchain files // to its constructor. // TIP: Class IBlockchainParser provides several constructors that are useful // in different scenarios. IBlockchainParser blockchainParser = new BlockchainParser(pathToBlockchain, "blk00000.dat", 1); // Call blockchainParser.SetBlockId is the blockchain uses a value different than the standard one // for the "BlockId" field of each block. For example on testnet / testnet3. // blockchainParser.SetBlockId(0x0709110B); // Start the parsing process by calling blockchainParser.ParseBlockchain() and // process each block that is returned by the parser. // The parser exposes the blocks it parses via an "IEnumerable<Block>". // TIPS: // 1. An instance of type BitcoinBlockchain.Data.Block holds information // about all its transactions, inputs and outputs and it can use a lot of memory. // After you are done processing a block do not keep it around in memory. // For example do not simply collect all instances of type BitcoinBlockchain.Data.Block // in a list. That would consume huge amounts of memory. // // 2. To improve the performance of your application you may want to dispatch the processing // of a block on a background thread. // If you do that however you need to account for the fact that multiple blocks will // be processed concurrently. You have to be prepared to deal with various multi-threading // aspects. For example a transaction input may end up being processed before the output // it links to. You may want to consider a hybrid approach where some of the processing // for a block is done on the main thread and some of the processing is dispatched on a // background thread. // // 3. If during processing you need to store so much information that you expect to // exceed 2 GB of memory, build your tool for the x64 configuration. // // 4. Make sure that you are aware of the concept of stale blocks. // Depending on what your processing does, not accounting for stale blocks could // lead to incorrect results. The parser has no way to know that a block is stale // when it encounters it. It will enumerate it to you and you will have the chance // to detect the stale blocks once the parsing of all blocks is complete. // See: // https://bitcoin.org/en/developer-guide#orphan-blocks // https://bitcoin.org/en/glossary/stale-block // https://bitcoin.org/en/glossary/orphan-block // http://bitcoin.stackexchange.com/questions/5859/what-are-orphaned-and-stale-blocks //NBitcoin.Block b = new NBitcoin.Block(); IEnumerable <ParserBlock> blocks = blockchainParser.ParseBlockchain(); foreach (ParserBlock block in blocks) { int blocklength = block.BlockLength; string filename = block.BlockchainFileName; if (currentBlockchainFile != block.BlockchainFileName) { if (currentBlockchainFile != null) { ReportBlockChainStatistics(blockFileStatistics); blockFileStatistics.Reset(); } currentBlockchainFile = block.BlockchainFileName; Console.WriteLine("Parsing file: {0}", block.BlockchainFileName); } blockFileStatistics.AddStatistics(1, block.Transactions.Count, block.TransactionInputsCount, block.TransactionOutputsCount); overallStatistics.AddStatistics(1, block.Transactions.Count, block.TransactionInputsCount, block.TransactionOutputsCount); } ReportBlockChainStatistics(blockFileStatistics); Console.WriteLine("================================================="); Console.WriteLine("Overall statistics:"); ReportBlockChainStatistics(overallStatistics); }
private static void ParseBlockchainFiles(string pathToBlockchain, string firstBlock) { BlockchainStatistics overallStatistics = new BlockchainStatistics(); BlockchainStatistics blockFileStatistics = new BlockchainStatistics(); string currentBlockchainFile = null; // Instantiate a BlockchainParser. We will pass the path to the blockchain files // to its constructor. // TIP: Class IBlockchainParser provides several constructors that are useful // in different scenarios. IBlockchainParser blockchainParser = new BlockchainParser(pathToBlockchain, firstBlock); // Call blockchainParser.SetBlockId is the blockchain uses a value different than the standard one // for the "BlockId" field of each block. For example on testnet / testnet3. // blockchainParser.SetBlockId(0x0709110B); // Start the parsing process by calling blockchainParser.ParseBlockchain() and // process each block that is returned by the parser. // The parser exposes the blocks it parses via an "IEnumerable<Block>". // TIPS: // 1. An instance of type BitcoinBlockchain.Data.Block holds information // about all its transactions, inputs and outputs and it can use a lot of memory. // After you are done processing a block do not keep it around in memory. // For example do not simply collect all instances of type BitcoinBlockchain.Data.Block // in a list. That would consume huge amounts of memory. // // 2. To improve the performance of your application you may want to dispatch the processing // of a block on a background thread. // If you do that however you need to account for the fact that multiple blocks will // be processed concurrently. You have to be prepared to deal with various multi-threading // aspects. For example a transaction input may end up being processed before the output // it links to. You may want to consider a hybrid approach where some of the processing // for a block is done on the main thread and some of the processing is dispatched on a // background thread. // // 3. If during processing you need to store so much information that you expect to // exceed 2 GB of memory, build your tool for the x64 configuration. // // 4. Make sure that you are aware of the concept of stale blocks. // Depending on what your processing does, not accounting for stale blocks could // lead to incorrect results. The parser has no way to know that a block is stale // when it encounters it. It will enumerate it to you and you will have the chance // to detect the stale blocks once the parsing of all blocks is complete. // See: // https://bitcoin.org/en/developer-guide#orphan-blocks // https://bitcoin.org/en/glossary/stale-block // https://bitcoin.org/en/glossary/orphan-block // http://bitcoin.stackexchange.com/questions/5859/what-are-orphaned-and-stale-blocks long[,] TXInCount = new long[10, 10]; long[,] TXOutCount = new long[10, 10]; long[] TransactionCounts = new long[10]; for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { TXInCount[i, j] = 0; TXOutCount[i, j] = 0; } TransactionCounts[i] = 0; } foreach (Block block in blockchainParser.ParseBlockchain()) { if (currentBlockchainFile != block.BlockchainFileName) { if (currentBlockchainFile != null) { ReportBlockChainStatistics(blockFileStatistics); blockFileStatistics.Reset(); } currentBlockchainFile = block.BlockchainFileName; Console.WriteLine("Parsing file: {0}", block.BlockchainFileName); } blockFileStatistics.AddStatistics(1, block.Transactions.Count, block.TransactionInputsCount, block.TransactionOutputsCount); overallStatistics.AddStatistics(1, block.Transactions.Count, block.TransactionInputsCount, block.TransactionOutputsCount); int year = block.BlockHeader.BlockTimestamp.Year; TransactionCounts[year - 2009] += block.TransactionsCount; foreach (Transaction transaction in block.Transactions) { if (transaction.TransactionInputsCount < 10 && transaction.TransactionOutputsCount < 10) { TXInCount[year - 2009, transaction.TransactionInputsCount]++; TXOutCount[year - 2009, transaction.TransactionOutputsCount]++; } else { TXInCount[year - 2009, 0]++; TXOutCount[year - 2009, 0]++; } } } ReportBlockChainStatistics(blockFileStatistics); Console.WriteLine("================================================="); Console.WriteLine("Overall statistics:"); ReportBlockChainStatistics(overallStatistics); string filePath = @"F:\Statistic.csv"; try { StreamWriter sw = File.CreateText(filePath); sw.Write("NUM/ITEMS"); for (int i = 0; i < 10; i++) { sw.Write(", {0}_TXIn_NumStatistic, {0}_TXIn_NumStatisticInPercent, {0}_TXOut_NumStatistic, {0}_TXOut_NumStatisticInPercent", 2009 + i); } sw.WriteLine(); for (int i = 1; i < 10; i++) { sw.Write("{0}", i); for (int j = 0; j < 10; j++) { sw.Write(", {0}, {1:000}%, {2:000}, {3}%", TXInCount[j, i], (float)(TXInCount[j, i] * 100.0 / TransactionCounts[j]), TXOutCount[j, i], (float)(TXOutCount[j, i] * 100.0 / TransactionCounts[j])); } sw.WriteLine(); } sw.Write("Other"); for (int i = 0; i < 10; i++) { sw.Write(", {0}, {1:000}%, {2:000}, {3}%", TXInCount[i, 0], (float)(TXInCount[i, 0] * 100.0 / TransactionCounts[i]), TXOutCount[i, 0], (float)(TXOutCount[i, 0] * 100.0 / TransactionCounts[i])); } sw.WriteLine(); sw.Write("Total"); for (int i = 0; i < 10; i++) { sw.Write(", {0}, 1, {0}, 1", TransactionCounts[i]); } sw.Close(); } catch (Exception e) { Console.WriteLine(e.Message); } }